/*
* 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 dot nl
*/
#include <stdio.h> /* */
#include <stdlib.h> /* */
#include <string.h> /* */
#include <unistd.h> /* */
#define MAX_LINE_LENGTH 1024
/*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 */
void usage(char *program_name, int colour)
{
if (program_name == NULL) program_name = "euses";
/* Catch program name without slash. */
else program_name = strrchr(program_name, '/') + 1;
(void) printf("Usage: %s <USE flag to search>\n", program_name);
(void) printf
("%s searches use.desc and use.local.desc for your USE flag.\n",
program_name);
exit(EXIT_SUCCESS);
}
void err_no(int err_no)
{
switch (err_no) {
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 ud_format(char *use_line)
{
int i;
size_t len;
len = strlen(use_line);
(void)printf("%s", BG);
for (i = 0; i < (int)len; ++i) {
if (use_line[i] == ' ') {
(void)printf("%s", FC);
}
(void)printf("%c", use_line[i]);
}
return;
}
void uld_format(char *use_line)
{
int i;
size_t len;
int past_colon = 0;
len = strlen(use_line);
(void)printf("%s", NC);
for (i = 0; i < (int)len; ++i) {
if (&use_line[i] >= strstr(use_line, ":")) {
switch (use_line[i]) {
case ':':{
if (past_colon == 0)
(void)printf("%s%c%s", FC,
use_line[i], BG);
}
past_colon = 1;
break;
case ' ':
(void)printf("%s%c", FC, use_line[i]);
break;
default:
(void)printf("%c", use_line[i]);
break;
}
} else
printf("%c", use_line[i]);
}
return;
}
void getportdir(char *new_portdir)
{
char etc_line[MAX_LINE_LENGTH * 2];
FILE *ptr = NULL;
const char *portdir_key = "PORTDIR=\"";
const char *def_portdir = "/usr/portage";
int i = 9;
int j = 0;
ptr = fopen("/etc/make.conf", "r");
if (ptr == NULL) {
err_no(0);
exit(EXIT_FAILURE);
}
/* This is turning out to be incredibly difficult:
* Difficult cases to parse are:
*
* PORTDIR="/usr"; PORTDIR="${PORTDIR}/portage"
* PORT\
* and
* DIR="/usr/portage"
* to name but two. */
while (feof(ptr) == 0) {
while (fgets(etc_line, MAX_LINE_LENGTH, ptr) != NULL) {
if (strstr(etc_line, portdir_key) != 0) {
while (etc_line[i] != '\0') {
if (etc_line[i] != '"')
new_portdir[j++] =
etc_line[i++];
else {
++i;
++j;
}
}
new_portdir[j] = '\0';
}
}
continue;
}
(void)fclose(ptr);
ptr = NULL;
if (strlen(new_portdir) == 0)
strncpy(new_portdir, def_portdir, strlen(def_portdir));
}
int main(int argc, char **argv)
{
FILE *ptr = NULL;
char *match_chr; /* Pointer to first matching character */
int ud_match = 0; /* True when at least one line in UD matches */
int uld_match = 0; /* True when at least one line in ULD matches */
char ud_path[MAX_LINE_LENGTH * 2];
char uld_path[MAX_LINE_LENGTH * 2];
const char *ud_file = "/profiles/use.desc";
const char *uld_file = "/profiles/use.local.desc";
int colour = 0; /* True if tty, otherwise False */
char use_line[MAX_LINE_LENGTH];
char path[MAX_LINE_LENGTH];
char *new_portdir = path;
memset(ud_path, 0, sizeof(ud_path));
memset(uld_path, 0, sizeof(uld_path));
getportdir(new_portdir); /* Check in /etc/make.conf where Portage is: */
strcat(ud_path, new_portdir);
strcat(ud_path, ud_file);
strcat(uld_path, new_portdir);
strcat(uld_path, uld_file);
if (isatty(STDOUT_FILENO) == 1)
colour = 1;
/* First look in use.desc: */
if (argc < 2)
usage(argv[0], colour);
ptr = fopen(ud_path, "r");
if (ptr == 0) {
err_no(1);
exit(EXIT_FAILURE);
}
while (feof(ptr) == 0) {
while (fgets(use_line, MAX_LINE_LENGTH, ptr) != NULL) {
if (use_line[0] == '#')
continue;
match_chr = strstr(use_line, argv[1]);
if (match_chr != 0) {
if (colour == 1) {
if (ud_match == 0) {
printf
(" %s*%s Found '%s%s%s' in %suse.desc%s:\n",
BG, FC, BW, argv[1], FC,
BB, FC);
ud_match = 1;
}
(void)ud_format(use_line); /* Format a single line */
} else {
printf(" use.desc: %s", use_line); /* Don't format */
}
}
}
}
(void)fclose(ptr);
ptr = NULL;
/* Then look in use.local.desc: */
ptr = fopen(uld_path, "r");
if (ptr == NULL) {
err_no(2);
exit(EXIT_FAILURE);
}
while (feof(ptr) == 0) {
while (fgets(use_line, MAX_LINE_LENGTH, ptr) != NULL) {
if (use_line[0] == '#')
continue;
if (strstr(use_line, argv[1]) != 0) {
if (colour == 1) {
if (uld_match == 0) {
printf
(" %s*%s Found %s%s%s in %suse.local.desc%s:\n",
BG, FC, BW, argv[1], FC,
BB, FC);
uld_match = 1;
}
(void)uld_format(use_line);
} else {
printf("use.local.desc: %s", use_line);
}
}
}
}
(void)fclose(ptr);
ptr = NULL;
if (ud_match != 0 || uld_match != 0) exit(EXIT_SUCCESS);
else exit(EXIT_FAILURE);
}
syntax highlighted by Code2HTML, v. 0.9.1