/*
 * euses is the first working incarnation of something
 * I called `guses' (for Gentoo uses, see
 * <http://www.xs4all.nl/~rooversj/gentoo/guses>) which
 * is a bash script I wrote that searches crudely for USE
 * flags in use.desc and use.local.desc and returns the
 * matching lines with some fancy colouring.
 * I originally intended that to be the ultimate, but I
 * opted to learn a bit of C instead and have a much
 * faster working program. Not that speed matters much in
 * this case...
 *
 * It should compile on any basic Linux system, but since it
 * is intended to search in two Gentoo-specific files (and
 * because right now the paths are hard-wired and no error-
 * checking is in place) compiling it (with whatever gcc
 * options you prefer) will probably simply work.
 *
 * Thanks to KillerFox and #gentoo-hppa for their programming clues. :)
 * 
 * This program was written by JeR in 2005, released on May 9, 2005
 * and is distributed under the GNU General Public License
 * version 2 or later.
 *
 * Mail your suggestions, improvements and complaints to
 *   jer <at> xs4all.nl
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>

#define MAX_LINE_LENGTH 512
#define PORTDIR_KEY "PORTDIR=\""
#define PORTDIR_DEFAULT "/usr/portage"

/*Color definitions: */
#define BG "\033[01;32m"	/* Bright Green */
#define FC "\033[00m"		/* Normal       */
#define BW "\033[01;29m"	/* Bright White */
#define NC "\033[00;36m"	/* Normal Cyan  */
#define BB "\033[01;34m"	/* Bright Blue  */

char use_line[MAX_LINE_LENGTH];
int interactive = 0;
char *portdir = "/usr/portage";
char portage_path[MAX_LINE_LENGTH * 2];

void print_usage(char *program_name)
{
	if (program_name && strrchr(program_name, '/'))
		program_name = strrchr(program_name, '/') + 1;
	if (interactive)
		printf("Usage: %s%s <USE flag to search>%s\n", BG, program_name, FC);
	else
		printf("Usage: %s <USE flag to search>\n", program_name);
	printf("%s searches use.desc and use.local.desc for your USE flag.\n",
	       program_name);
	exit(EXIT_FAILURE);
}

void use_desc_format(char *use_line)
{
	int i;
	size_t use_len;
	use_len = strlen(use_line);
	printf("%s", BG);
	for (i = 0; i < use_len; ++i) {
		if (use_line[i] == ' ') {
			printf("%s", FC);
		}
		printf("%c", use_line[i]);
	}
	return;
}

void use_local_desc_format(char *use_line)
{
	int i;
	size_t use_len;
	int past_colon = 0;
	use_len = strlen(use_line);
	printf("%s", NC);
	for (i = 0; i < use_len; ++i) {
		if (&use_line[i] >= strstr(use_line, ":")) {
			switch (use_line[i]) {
			case ':':
				if (past_colon == 0)
					printf("%s%c%s", FC, use_line[i], BG);
				past_colon = 1;
				break;
			case ' ':
				printf("%s%c", FC, use_line[i]);
				break;
			default:
				printf("%c", use_line[i]);
				break;
			}
		} else
			printf("%c", use_line[i]);
	}
	return;
}

void toerrishuman(int whichone)
{
	switch (whichone)
	{
		case 0: puts("/etc/make.conf not found\n"); break;
		case 1: puts("use.desc not found\n"); break;
		case 2: puts("use.local.desc not found\n"); break;
		default: puts("Do you Gentoo?\n"); break;
	}
	exit(EXIT_FAILURE);
}

void getmakeconf() {
	char etc_line[MAX_LINE_LENGTH * 2];
	FILE *ptr = NULL;
	char *match_char;
	const char *etc_make_conf_path = "/etc/make.conf";
	const char *portdir = "PORTDIR=\"";
	char *i = NULL;
	int portage_ptr = 0;

	if (! (ptr = fopen(etc_make_conf_path, "r"))) toerrishuman(0);

	memset(&portage_path, 0, MAX_LINE_LENGTH * 2);

	while (feof(ptr) == 0) {
		fgets(etc_line, MAX_LINE_LENGTH * 2, ptr);
		if (etc_line[0] == '#')
			continue;
		match_char = strstr(etc_line, portdir);
		if (match_char != 0) {
			for (i = index(etc_line, '\"') + 1; portage_ptr < (MAX_LINE_LENGTH * 2) && *i && *i != '\"';
			     ++i) {
				portage_path[portage_ptr++] = *i;
			}
			break;
		}
	}

	fclose(ptr);
	if (strlen(portage_path) == 0) {
		strcpy(portage_path, "/usr/portage");
	}
	return;
}

int main(int argc, char **argv)
{
	FILE *ptr = NULL;
	char *match_char;
	int use_desc_matches = 0;
	int use_local_desc_matches = 0;
	char use_desc_path[MAX_LINE_LENGTH * 2];
	char use_local_desc_path[MAX_LINE_LENGTH * 2];
	const char *use_desc_file = "/profiles/use.desc";
	const char *use_local_desc_file = "/profiles/use.local.desc";

	memset(&use_desc_path, 0, MAX_LINE_LENGTH);
	memset(&use_local_desc_path, 0, MAX_LINE_LENGTH);

	/* Check in /etc/make.conf where Portage is: */
	getmakeconf();

	strncat(use_desc_path, portage_path, MAX_LINE_LENGTH -1);
	strncat(use_desc_path, use_desc_file, (MAX_LINE_LENGTH - strlen(use_desc_path)));

	strncat(use_local_desc_path, portage_path, MAX_LINE_LENGTH -1);
	strncat(use_local_desc_path, use_local_desc_file, (MAX_LINE_LENGTH - strlen(use_local_desc_path)));

	if (isatty(STDOUT_FILENO))
		interactive = 1;

	/* First look in use.desc: */

	if (argc < 2)
		print_usage(argv[0]);
	if (! (ptr = fopen(use_desc_path, "r"))) toerrishuman(1);
	while (feof(ptr) == 0) {
		fgets(use_line, MAX_LINE_LENGTH, ptr);
		if (use_line[0] == '#')
			continue;
		match_char = strstr(use_line, argv[1]);
		if (match_char != 0) {
			if (interactive) {
				if (use_desc_matches == 0) {
					printf
					    (" %s*%s Found '%s%s%s' in %suse.desc%s:\n",
					     BG, FC, BW, argv[1], FC, BB, FC);
					use_desc_matches = 1;
				}
				use_desc_format(use_line);	/* Format a single line */
			} else {
				printf("      use.desc: %s", use_line);	/* Don't format */
			}
		}
	}

	fclose(ptr);

	/* Then look in use.local.desc: */

	if (! (ptr = fopen(use_local_desc_path, "r"))) toerrishuman(2);
	while (feof(ptr) == 0) {
		fgets(use_line, MAX_LINE_LENGTH, ptr);
		if (use_line[0] == '#')
			continue;
		if (strstr(use_line, argv[1]) != 0) {
			if (interactive) {
				if (use_local_desc_matches == 0) {
					printf
					    (" %s*%s Found %s%s%s in %suse.local.desc%s:\n",
					     BG, FC, BW, argv[1], FC, BB, FC);
					use_local_desc_matches = 1;
				}
				use_local_desc_format(use_line);
			} else {
				printf("use.local.desc: %s", use_line);
			}
		}
	}
	if (use_desc_matches == 0 && use_local_desc_matches == 0)
		exit(EXIT_FAILURE);
	else exit(EXIT_SUCCESS);
}


syntax highlighted by Code2HTML, v. 0.9.1