/*
* 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 (UD) and use.local.desc (ULD) 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.
*
* Thanks to KillerFox and #gentoo-hppa for their programming clues. :)
*
* This program was written by JeR in 2005, released first on May 9,
* 2005 and is distributed under the GNU General Public License
* version 2, a copy of which may be found at
* <http://www.gnu.org/licenses/gpl.txt>.
*
* Mail your suggestions, improvements, complaints and questions to
* jer at xs4all dot nl
*
* TODO: Add code to check a per user .euses file for the saved value of
* PORTDIR -- Saves lots of time as opposed to opening a shell every time.
* TODO: Add a reading pipe to obtain a (list of) string(s).
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define LINE_LENGTH 1024
#define UD "use.desc"
#define ULD "use.local.desc"
#define PROFILES "/profiles/"
#define EMF "/etc/make.conf"
/*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 BR "\033[01;31m" /* Bright Red */
void usage()
{
(void)puts("Usage: euses <string>");
(void)
puts
("euses displays descriptions from use.[local.]desc of USE flags matching <string>");
(void)printf("euses %s Copyright JeR 2005\n", VERSION);
exit(EXIT_SUCCESS);
}
void err_no(int err_no)
{
switch (err_no) {
case 0:
printf("%s not found\n", EMF);
break;
case 1:
printf("%s not found\n", UD);
break;
case 2:
printf("%s not found\n", ULD);
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 *portdir)
{
FILE *ptr;
ptr = popen("source /etc/make.conf; echo -n ${PORTDIR}", "r");
if (fgets(portdir, LINE_LENGTH, ptr) == NULL)
err_no(0);
if (strlen(portdir) == 0)
(void)strcat(portdir, "/usr/portage");
(void)pclose(ptr);
}
void ud_flag_fest(char *use_line, char *flag)
{
int i = 0;
int j = 0;
while (use_line[i] != '\0') {
while (use_line[i] != ' ') {
flag[j++] = use_line[i++];
continue;
}
break;
}
}
void uld_flag_fest(char *use_line, char *flag)
{
int i = 0;
int j = 0;
int chr_copy = 0;
/* Remove the package name at the beginning */
while (use_line[i] != '\0') {
while (use_line[i] != ' ') {
if (use_line[i] == ':') {
chr_copy = 1;
++i;
} else {
}
if (chr_copy == 1)
flag[j++] = use_line[i];
++i;
continue;
}
break;
}
}
int filter_comments(char *line)
{
if (line[0] == '#' || line[0] == '\n' || line[0] == ' ')
return 1;
else
return 0;
}
void print_ud(int colour, char *use_line)
{
if (colour == 1)
(void)ud_format(use_line);
else
printf(" %s: %s", UD, use_line);
}
int match_ud(char *string,
char *use_line, char *ud_path, int ud_matches, int colour)
{
FILE *ptr = NULL;
int matches = 0; /* Local match counter */
char ud_flag[LINE_LENGTH]; /* The UD flag from use_line */
char *match_chr; /* Pointer to first matching character */
ptr = fopen(ud_path, "r");
if (ptr == NULL)
err_no(1);
while (feof(ptr) == 0) {
while (fgets(use_line, LINE_LENGTH, ptr) != NULL) {
if (filter_comments(use_line) == 0) {
(void)ud_flag_fest(use_line, ud_flag);
match_chr = strstr(ud_flag, string);
(void)memset(ud_flag, 0, sizeof(ud_flag));
if (match_chr != 0) {
matches++;
print_ud(colour, use_line);
}
}
}
}
(void)fclose(ptr);
ptr = NULL;
if (matches > 0)
ud_matches++;
return ud_matches;
}
void match_err(int colour, char *string)
{
if (colour == 1)
printf("No matches for: %s%s%s\n", BR, string, FC);
else
printf("No matches for: %s\n", string);
}
void print_uld(int colour, char *use_line)
{
if (colour == 1)
(void)uld_format(use_line);
else
printf("%s: %s", ULD, use_line);
}
int match_uld(char *string, char *use_line, char *uld_path, int uld_matches,
int colour)
{
FILE *ptr = NULL;
int matches = 0; /* Local match counter */
char uld_flag[LINE_LENGTH]; /* The ULD flag from use_line */
char *match_chr; /* Pointer to first matching character */
ptr = fopen(uld_path, "r");
if (ptr == NULL)
err_no(2);
while (feof(ptr) == 0) {
while (fgets(use_line, LINE_LENGTH, ptr) != NULL) {
if (filter_comments(use_line) == 0) {
(void)uld_flag_fest(use_line, uld_flag);
match_chr = strstr(uld_flag, string);
(void)memset(uld_flag, 0, sizeof(uld_flag));
if (match_chr != 0) {
matches++;
print_uld(colour, use_line);
}
}
}
}
(void)fclose(ptr);
ptr = NULL;
if (matches > 0)
uld_matches++;
return uld_matches;
}
int main(int argc, char **argv)
{
int i;
int colour = 0; /* True if tty, otherwise False */
int flag_matches = 0; /* Counts the total number of matches */
int ud_matches = 0; /* Counter for the number of UD matches */
int uld_matches = 0; /* Counter for the number of ULD matches */
char ud_path[LINE_LENGTH * 2]; /* Path to UD */
char uld_path[LINE_LENGTH * 2]; /* Path to ULD */
char use_line[LINE_LENGTH]; /* A single line from UD or ULD */
char path[LINE_LENGTH]; /* Stores a path */
char *portdir = path; /* Points to stored path */
char ud_flag[LINE_LENGTH]; /* The UD flag from use_line */
char uld_flag[LINE_LENGTH]; /* The ULD flag from use_line */
(void)memset(ud_path, 0, sizeof(ud_path));
(void)memset(uld_path, 0, sizeof(uld_path));
(void)memset(ud_flag, 0, sizeof(ud_flag));
(void)memset(uld_flag, 0, sizeof(uld_flag));
/* Check in EMF where Portage is */
getportdir(portdir);
strcat(ud_path, portdir);
strcat(ud_path, PROFILES);
strcat(ud_path, UD);
strcat(uld_path, portdir);
strcat(uld_path, PROFILES);
strcat(uld_path, ULD);
if (isatty(STDOUT_FILENO) == 1)
colour = 1;
if (argc < 2)
usage();
else {
for (i = 1; i < argc; ++i) {
ud_matches = 0;
ud_matches =
match_ud(argv[i], use_line, ud_path, ud_matches,
colour);
uld_matches = 0;
uld_matches =
match_uld(argv[i], use_line, uld_path, uld_matches,
colour);
if (ud_matches > 0 || uld_matches > 0)
flag_matches++;
else
match_err(colour, argv[i]);
}
}
if (flag_matches != argc - 1)
exit(EXIT_FAILURE);
else
exit(EXIT_SUCCESS);
}
syntax highlighted by Code2HTML, v. 0.9.1