X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=utility.c;h=26568320fcac1874f177708ae71a2e6ec11139b5;hb=2f6c04f63c55a03366dfd5848f00bda664c9a90d;hp=c6121cb11322ba3a9b42a04add578b7656cb303a;hpb=bed30e97005aca748a44806399c646633038daa8;p=oweals%2Fbusybox.git diff --git a/utility.c b/utility.c index c6121cb11..26568320f 100644 --- a/utility.c +++ b/utility.c @@ -1,7 +1,9 @@ /* * Utility routines. * - * Copyright (C) 1998 by Erik Andersen + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,6 +34,41 @@ #include #include #include +#include + +/* volatile so gcc knows this is the enod of the line */ +volatile void usage(const char *usage) +{ + fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n", BB_VER, BB_BT); + fprintf(stderr, "Usage: %s\n", usage); + exit(FALSE); +} + + +#if defined (BB_INIT) || defined (BB_PS) + +/* Returns kernel version encoded as major*65536 + minor*256 + patch, + * so, for example, to check if the kernel is greater than 2.2.11: + * if (get_kernel_revision() <= 2*65536+2*256+11) { } + */ +int +get_kernel_revision() +{ + FILE *file; + int major=0, minor=0, patch=0; + char* filename="/proc/sys/kernel/osrelease"; + + file = fopen(filename,"r"); + if (file == NULL) { + /* bummer, /proc must not be mounted... */ + return( 0); + } + fscanf(file,"%d.%d.%d",&major,&minor,&patch); + fclose(file); + return major*65536 + minor*256 + patch; +} + +#endif @@ -57,6 +94,7 @@ int isDirectory(const char *name) * and modes. Returns TRUE if successful, or FALSE on a failure with an * error message output. (Failure is not indicted if the attributes cannot * be set.) + * -Erik Andersen */ int copyFile( const char *srcName, const char *destName, @@ -279,94 +317,6 @@ const char *timeString(time_t timeVal) } -/* - * Routine to see if a text string is matched by a wildcard pattern. - * Returns TRUE if the text is matched, or FALSE if it is not matched - * or if the pattern is invalid. - * * matches zero or more characters - * ? matches a single character - * [abc] matches 'a', 'b' or 'c' - * \c quotes character c - * Adapted from code written by Ingo Wilken. - */ -int match(const char *text, const char *pattern) -{ - const char *retryPat; - const char *retryText; - int ch; - int found; - - retryPat = NULL; - retryText = NULL; - - while (*text || *pattern) { - ch = *pattern++; - - switch (ch) { - case '*': - retryPat = pattern; - retryText = text; - break; - - case '[': - found = FALSE; - - while ((ch = *pattern++) != ']') { - if (ch == '\\') - ch = *pattern++; - - if (ch == '\0') - return FALSE; - - if (*text == ch) - found = TRUE; - } - - if (!found) { - pattern = retryPat; - text = ++retryText; - } - - /* fall into next case */ - - case '?': - if (*text++ == '\0') - return FALSE; - - break; - - case '\\': - ch = *pattern++; - - if (ch == '\0') - return FALSE; - - /* fall into next case */ - - default: - if (*text == ch) { - if (*text) - text++; - break; - } - - if (*text) { - pattern = retryPat; - text = ++retryText; - break; - } - - return FALSE; - } - - if (pattern == NULL) - return FALSE; - } - - return TRUE; -} - - /* * Write all of the supplied buffer out to a file. * This does multiple writes as necessary. @@ -431,9 +381,13 @@ int fullRead(int fd, char *buf, int len) * Walk down all the directories under the specified * location, and do something (something specified * by the fileAction and dirAction function pointers). + * + * Unfortunatly, while nftw(3) could replace this and reduce + * code size a bit, nftw() wasn't supported before GNU libc 2.1, + * and so isn't sufficiently portable to take over... */ int -recursiveAction(const char *fileName, int recurse, int followLinks, int delayDirAction, +recursiveAction(const char *fileName, int recurse, int followLinks, int depthFirst, int (*fileAction) (const char *fileName, struct stat* statbuf), int (*dirAction) (const char *fileName, struct stat* statbuf)) { @@ -467,7 +421,7 @@ recursiveAction(const char *fileName, int recurse, int followLinks, int delayDir perror(fileName); return (FALSE); } - if (dirAction != NULL && delayDirAction == FALSE) { + if (dirAction != NULL && depthFirst == FALSE) { status = dirAction(fileName, &statbuf); if (status == FALSE) { perror(fileName); @@ -482,7 +436,7 @@ recursiveAction(const char *fileName, int recurse, int followLinks, int delayDir } sprintf(nextFile, "%s/%s", fileName, next->d_name); status = - recursiveAction(nextFile, TRUE, followLinks, delayDirAction, + recursiveAction(nextFile, TRUE, followLinks, depthFirst, fileAction, dirAction); if (status < 0) { closedir(dir); @@ -494,7 +448,7 @@ recursiveAction(const char *fileName, int recurse, int followLinks, int delayDir perror(fileName); return (FALSE); } - if (dirAction != NULL && delayDirAction == TRUE) { + if (dirAction != NULL && depthFirst == TRUE) { status = dirAction(fileName, &statbuf); if (status == FALSE) { perror(fileName); @@ -548,13 +502,17 @@ extern void createPath (const char *name, int mode) #if defined (BB_CHMOD_CHOWN_CHGRP) || defined (BB_MKDIR) -/* [ugoa]{+|-|=}[rwxstl] */ -extern int parse_mode( const char* s, mode_t* theMode) +/* [ugoa]{+|-|=}[rwxst] */ + + + +extern int +parse_mode( const char* s, mode_t* theMode) { - mode_t or; - mode_t and; + mode_t andMode = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; + mode_t orMode = 0; mode_t mode = 0; - mode_t groups = S_ISVTX; + mode_t groups = 0; char type; char c; @@ -562,7 +520,7 @@ extern int parse_mode( const char* s, mode_t* theMode) for ( ; ; ) { switch ( c = *s++ ) { case '\0': - return (FALSE); + return -1; case 'u': groups |= S_ISUID|S_IRWXU; continue; @@ -579,13 +537,13 @@ extern int parse_mode( const char* s, mode_t* theMode) case '=': case '-': type = c; - if ( groups == S_ISVTX ) /* The default is "all" */ + if ( groups == 0 ) /* The default is "all" */ groups |= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; break; default: - if ( c >= '0' && c <= '7' && mode == 0 && groups == S_ISVTX ) { - and = 0; - or = strtol(--s, 0, 010); + if ( isdigit(c) && c >= '0' && c <= '7' && + mode == 0 && groups == 0 ) { + *theMode = strtol(--s, NULL, 8); return (TRUE); } else @@ -611,28 +569,291 @@ extern int parse_mode( const char* s, mode_t* theMode) mode |= S_IXGRP|S_ISUID|S_ISGID; continue; case 't': - mode |= S_ISVTX; + mode |= 0; continue; default: - return (FALSE); + *theMode &= andMode; + *theMode |= orMode; + return( TRUE); } break; } switch ( type ) { case '=': - and &= ~(groups); + andMode &= ~(groups); /* fall through */ case '+': - or |= mode & groups; + orMode |= mode & groups; break; case '-': - and &= ~(mode & groups); - or &= and; + andMode &= ~(mode & groups); + orMode &= andMode; break; } } while ( c == ',' ); + *theMode &= andMode; + *theMode |= orMode; return (TRUE); } + + #endif + + + + + + +#if defined (BB_CHMOD_CHOWN_CHGRP) || defined (BB_PS) + +/* Use this to avoid needing the glibc NSS stuff + * This uses storage buf to hold things. + * */ +uid_t +my_getid(const char *filename, char *name, uid_t id) +{ + FILE *file; + char *rname, *start, *end, buf[128]; + uid_t rid; + + file=fopen(filename,"r"); + if (file == NULL) { + perror(filename); + return (-1); + } + + while (fgets (buf, 128, file) != NULL) { + if (buf[0] == '#') + continue; + + start = buf; + end = strchr (start, ':'); + if (end == NULL) + continue; + *end = '\0'; + rname = start; + + start = end + 1; + end = strchr (start, ':'); + if (end == NULL) + continue; + + start = end + 1; + rid = (uid_t) strtol (start, &end, 10); + if (end == start) + continue; + + if (name) { + if (0 == strcmp(rname, name)) + return( rid); + } + if ( id != -1 && id == rid ) { + strncpy(name, rname, 8); + return( TRUE); + } + } + fclose(file); + return (-1); +} + +uid_t +my_getpwnam(char *name) +{ + return my_getid("/etc/passwd", name, -1); +} + +gid_t +my_getgrnam(char *name) +{ + return my_getid("/etc/group", name, -1); +} + +void +my_getpwuid(char* name, uid_t uid) +{ + my_getid("/etc/passwd", name, uid); +} + +void +my_getgrgid(char* group, gid_t gid) +{ + my_getid("/etc/group", group, gid); +} + + +#endif + + + + +#if (defined BB_CHVT) || (defined BB_DEALLOCVT) + + +#include +#include + +int is_a_console(int fd) +{ + char arg; + + arg = 0; + return (ioctl(fd, KDGKBTYPE, &arg) == 0 + && ((arg == KB_101) || (arg == KB_84))); +} + +static int open_a_console(char *fnam) +{ + int fd; + + /* try read-only */ + fd = open(fnam, O_RDWR); + + /* if failed, try read-only */ + if (fd < 0 && errno == EACCES) + fd = open(fnam, O_RDONLY); + + /* if failed, try write-only */ + if (fd < 0 && errno == EACCES) + fd = open(fnam, O_WRONLY); + + /* if failed, fail */ + if (fd < 0) + return -1; + + /* if not a console, fail */ + if (! is_a_console(fd)) + { + close(fd); + return -1; + } + + /* success */ + return fd; +} + +/* + * Get an fd for use with kbd/console ioctls. + * We try several things because opening /dev/console will fail + * if someone else used X (which does a chown on /dev/console). + * + * if tty_name is non-NULL, try this one instead. + */ + +int get_console_fd(char* tty_name) +{ + int fd; + + if (tty_name) + { + if (-1 == (fd = open_a_console(tty_name))) + return -1; + else + return fd; + } + + fd = open_a_console("/dev/tty"); + if (fd >= 0) + return fd; + + fd = open_a_console("/dev/tty0"); + if (fd >= 0) + return fd; + + fd = open_a_console("/dev/console"); + if (fd >= 0) + return fd; + + for (fd = 0; fd < 3; fd++) + if (is_a_console(fd)) + return fd; + + fprintf(stderr, + "Couldnt get a file descriptor referring to the console\n"); + return -1; /* total failure */ +} + + +#endif + + +#if !defined BB_REGEXP && (defined BB_GREP || defined BB_FIND || defined BB_SED) + +/* Do a case insensitive strstr() */ +char* stristr(char *haystack, const char *needle) +{ + int len = strlen( needle ); + while( *haystack ) { + if( !strncasecmp( haystack, needle, len ) ) + break; + haystack++; + } + + if( !(*haystack) ) + haystack = NULL; + + return haystack; +} + +/* This tries to find a needle in a haystack, but does so by + * only trying to match literal strings (look 'ma, no regexps!) + * This is short, sweet, and carries _very_ little baggage, + * unlike its beefier cousin in regexp.c + * -Erik Andersen + */ +extern int find_match(char *haystack, char *needle, int ignoreCase) +{ + + if (ignoreCase == FALSE) + haystack = strstr (haystack, needle); + else + haystack = stristr (haystack, needle); + if (haystack == NULL) + return FALSE; + return TRUE; +} + + +/* This performs substitutions after a string match has been found. */ +extern int replace_match(char *haystack, char *needle, char *newNeedle, int ignoreCase) +{ + int foundOne=0; + char *where, *slider, *slider1, *oldhayStack; + + if (ignoreCase == FALSE) + where = strstr (haystack, needle); + else + where = stristr (haystack, needle); + + if (strcmp(needle, newNeedle)==0) + return FALSE; + + oldhayStack = (char*)malloc((unsigned)(strlen(haystack))); + while(where!=NULL) { + foundOne++; + strcpy(oldhayStack, haystack); +#if 0 + if ( strlen(newNeedle) > strlen(needle)) { + haystack = (char *)realloc(haystack, (unsigned)(strlen(haystack) - + strlen(needle) + strlen(newNeedle))); + } +#endif + for(slider=haystack,slider1=oldhayStack;slider!=where;slider++,slider1++); + *slider=0; + haystack=strcat(haystack, newNeedle); + slider1+=strlen(needle); + haystack = strcat(haystack, slider1); + where = strstr (slider, needle); + } + free( oldhayStack); + + if (foundOne > 0) + return TRUE; + else + return FALSE; +} + + +#endif /* END CODE */ +