123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706 |
- /*
- * Copyright (c) 1993 by David I. Bell
- * Permission is granted to use, distribute, or modify this source,
- * provided that this copyright notice remains intact.
- *
- * Utility routines.
- */
- #include "sash.h"
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <dirent.h>
- #include <time.h>
- #include <utime.h>
- #include <fcntl.h>
- #include <fnmatch.h>
- #ifdef L_intflag
- int intflag;
- #endif
- #ifdef L_modestring
- /*
- * Return the standard ls-like mode string from a file mode.
- * This is static and so is overwritten on each call.
- */
- char *
- modestring(mode)
- {
- static char buf[12];
- strcpy(buf, "----------");
- /*
- * Fill in the file type.
- */
- if (S_ISDIR(mode))
- buf[0] = 'd';
- if (S_ISCHR(mode))
- buf[0] = 'c';
- if (S_ISBLK(mode))
- buf[0] = 'b';
- if (S_ISFIFO(mode))
- buf[0] = 'p';
- #ifdef S_ISLNK
- if (S_ISLNK(mode))
- buf[0] = 'l';
- #endif
- #ifdef S_ISSOCK
- if (S_ISSOCK(mode))
- buf[0] = 's';
- #endif
- /*
- * Now fill in the normal file permissions.
- */
- if (mode & S_IRUSR)
- buf[1] = 'r';
- if (mode & S_IWUSR)
- buf[2] = 'w';
- if (mode & S_IXUSR)
- buf[3] = 'x';
- if (mode & S_IRGRP)
- buf[4] = 'r';
- if (mode & S_IWGRP)
- buf[5] = 'w';
- if (mode & S_IXGRP)
- buf[6] = 'x';
- if (mode & S_IROTH)
- buf[7] = 'r';
- if (mode & S_IWOTH)
- buf[8] = 'w';
- if (mode & S_IXOTH)
- buf[9] = 'x';
- /*
- * Finally fill in magic stuff like suid and sticky text.
- */
- if (mode & S_ISUID)
- buf[3] = ((mode & S_IXUSR) ? 's' : 'S');
- if (mode & S_ISGID)
- buf[6] = ((mode & S_IXGRP) ? 's' : 'S');
- if (mode & S_ISVTX)
- buf[9] = ((mode & S_IXOTH) ? 't' : 'T');
- return buf;
- }
- #endif
- #ifdef L_timestring
- /*
- * Get the time to be used for a file.
- * This is down to the minute for new files, but only the date for old files.
- * The string is returned from a static buffer, and so is overwritten for
- * each call.
- */
- char *
- timestring(t)
- long t;
- {
- long now;
- char *str;
- static char buf[26];
- time(&now);
- str = ctime(&t);
- strcpy(buf, &str[4]);
- buf[12] = '\0';
- if ((t > now) || (t < now - 365*24*60*60L)) {
- strcpy(&buf[7], &str[20]);
- buf[11] = '\0';
- }
- return buf;
- }
- #endif
- #ifdef L_isadir
- /*
- * Return TRUE if a filename is a directory.
- * Nonexistant files return FALSE.
- */
- BOOL
- isadir(name)
- char *name;
- {
- struct stat statbuf;
- if (stat(name, &statbuf) < 0)
- return FALSE;
- return S_ISDIR(statbuf.st_mode);
- }
- #endif
- #ifdef L_copyfile
- /*
- * Copy one file to another, while possibly preserving its modes, times,
- * 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.)
- */
- BOOL
- copyfile(srcname, destname, setmodes)
- char *srcname;
- char *destname;
- BOOL setmodes;
- {
- int rfd;
- int wfd;
- int rcc;
- int wcc;
- char *bp;
- struct stat statbuf1;
- struct stat statbuf2;
- struct utimbuf times;
- int len = 8192-16;
- char * buf = 0;
-
- if (stat(srcname, &statbuf1) < 0) {
- perror(srcname);
- return FALSE;
- }
- if (stat(destname, &statbuf2) < 0) {
- statbuf2.st_ino = -1;
- statbuf2.st_dev = -1;
- }
- if (S_ISREG(statbuf1.st_mode) &&
- (statbuf1.st_dev == statbuf2.st_dev) &&
- (statbuf1.st_ino == statbuf2.st_ino))
- {
- fprintf(stderr, "Copying file \"%s\" to itself\n", srcname);
- return FALSE;
- }
- rfd = open(srcname, 0);
- if (rfd < 0) {
- perror(srcname);
- return FALSE;
- }
- wfd = open(destname, O_WRONLY|O_CREAT|O_TRUNC, statbuf1.st_mode);
- if (wfd < 0) {
- perror(destname);
- close(rfd);
- return FALSE;
- }
- buf = malloc(len);
- if (!buf) {
- fprintf(stderr,"Unable to allocate buffer of %d bytes\n", len);
- return FALSE;
- }
-
- while ((rcc = read(rfd, buf, len)) > 0) {
- if (intflag) {
- close(rfd);
- close(wfd);
- free(buf);
- return FALSE;
- }
- bp = buf;
- while (rcc > 0) {
- wcc = write(wfd, bp, rcc);
- if (wcc < 0) {
- perror(destname);
- free(buf);
- goto error_exit;
- }
- bp += wcc;
- rcc -= wcc;
- }
- }
-
- free(buf);
- if (rcc < 0) {
- perror(srcname);
- goto error_exit;
- }
- close(rfd);
- if (close(wfd) < 0) {
- perror(destname);
- return FALSE;
- }
- if (setmodes) {
- (void) chmod(destname, statbuf1.st_mode);
- (void) chown(destname, statbuf1.st_uid, statbuf1.st_gid);
- times.actime = statbuf1.st_atime;
- times.modtime = statbuf1.st_mtime;
- (void) utime(destname, ×);
- }
- return TRUE;
- error_exit:
- close(rfd);
- close(wfd);
- return FALSE;
- }
- #endif
- #ifdef L_buildname
- /*
- * Build a path name from the specified directory name and file name.
- * If the directory name is NULL, then the original filename is returned.
- * The built path is in a static area, and is overwritten for each call.
- */
- char *
- buildname(dirname, filename)
- char *dirname;
- char *filename;
- {
- char *cp;
- static char buf[PATHLEN];
- if ((dirname == NULL) || (*dirname == '\0'))
- return filename;
- cp = strrchr(filename, '/');
- if (cp)
- filename = cp + 1;
- strcpy(buf, dirname);
- strcat(buf, "/");
- strcat(buf, filename);
- return buf;
- }
- #endif
- #ifdef L_expandwildcards
- /*
- * Expand the wildcards in a filename, if any.
- * Returns an argument list with matching filenames in sorted order.
- * The expanded names are stored in memory chunks which can later all
- * be freed at once. Returns zero if the name is not a wildcard, or
- * returns the count of matched files if the name is a wildcard and
- * there was at least one match, or returns -1 if too many filenames
- * matched (with an error output).
- * If the name is a wildcard and no names match, returns 0 as
- * if the name were not a wildcard.
- */
- int
- expandwildcards(name, maxargc, retargv)
- char *name;
- int maxargc;
- char *retargv[];
- {
- char *last;
- char *cp1, *cp2, *cp3;
- DIR *dirp;
- struct dirent *dp;
- int dirlen;
- int matches;
- char dirname[PATHLEN];
- last = strrchr(name, '/');
- if (last)
- last++;
- else
- last = name;
- cp1 = strchr(name, '*');
- cp2 = strchr(name, '?');
- cp3 = strchr(name, '[');
- if ((cp1 == NULL) && (cp2 == NULL) && (cp3 == NULL))
- return 0;
- if ((cp1 && (cp1 < last)) || (cp2 && (cp2 < last)) ||
- (cp3 && (cp3 < last)))
- {
- fprintf(stderr, "Wildcards only implemented for last filename component\n");
- return -1;
- }
- dirname[0] = '.';
- dirname[1] = '\0';
- if (last != name) {
- memcpy(dirname, name, last - name);
- dirname[last - name - 1] = '\0';
- if (dirname[0] == '\0') {
- dirname[0] = '/';
- dirname[1] = '\0';
- }
- }
- dirp = opendir(dirname);
- if (dirp == NULL) {
- perror(dirname);
- return -1;
- }
- dirlen = strlen(dirname);
- if (last == name) {
- dirlen = 0;
- dirname[0] = '\0';
- } else if (dirname[dirlen - 1] != '/') {
- dirname[dirlen++] = '/';
- dirname[dirlen] = '\0';
- }
- matches = 0;
- while ((dp = readdir(dirp)) != NULL) {
- if ((strcmp(dp->d_name, ".") == 0) ||
- (strcmp(dp->d_name, "..") == 0))
- continue;
- if (!match(dp->d_name, last))
- continue;
- if (matches >= maxargc) {
- fprintf(stderr, "Too many filename matches\n");
- closedir(dirp);
- return -1;
- }
- cp1 = getchunk(dirlen + strlen(dp->d_name) + 1);
- if (cp1 == NULL) {
- fprintf(stderr, "No memory for filename\n");
- closedir(dirp);
- return -1;
- }
- if (dirlen)
- memcpy(cp1, dirname, dirlen);
- strcpy(cp1 + dirlen, dp->d_name);
- retargv[matches++] = cp1;
- }
- closedir(dirp);
- if (matches == 0) {
- return 0;
- }
- qsort((char *) retargv, matches, sizeof(char *), namesort);
- return matches;
- }
- #endif
- #ifdef L_namesort
- /*
- * Sort routine for list of filenames.
- */
- int
- namesort(p1, p2)
- char **p1;
- char **p2;
- {
- return strcmp(*p1, *p2);
- }
- #endif
- #ifdef L_match
- /*
- * 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.
- */
- BOOL
- match(text, pattern)
- char *text;
- char *pattern;
- {
- return fnmatch(pattern, text, 0) == 0;
- }
- #endif
- #ifdef L_makeargs
- /*
- * Take a command string, and break it up into an argc, argv list.
- * The returned argument list and strings are in static memory, and so
- * are overwritten on each call. The argument array is ended with an
- * extra NULL pointer for convenience. Returns TRUE if successful,
- * or FALSE on an error with a message already output.
- *
- * Note that leading quotes are *not* removed at this point, but
- * trailing quotes are.
- */
- BOOL
- makeargs(cmd, argcptr, argvptr)
- char *cmd;
- int *argcptr;
- char ***argvptr;
- {
- char *cp;
- int argc;
- static char strings[CMDLEN+1];
- static char *argtable[MAXARGS+1];
- static char quoted[MAXARGS+1];
- /*
- * Copy the command string and then break it apart
- * into separate arguments.
- */
- strcpy(strings, cmd);
- argc = 0;
- cp = strings;
- while (*cp) {
- if (argc >= MAXARGS) {
- fprintf(stderr, "Too many arguments\n");
- return FALSE;
- }
- quoted[argc] = 0;
- argtable[argc++] = cp;
- while (*cp && !isblank(*cp)) {
- if (*cp == '"' || *cp == '\'') {
- char *sp = cp++;
- while (*cp && *cp != *sp)
- cp++;
- if (*cp == *sp) {
- /* Chop off the trailing quote, but leave the leading quote
- * so that later processing will know the argument is quoted
- */
- *cp++ = 0;
- }
- } else
- cp++;
- }
- while (isblank(*cp))
- *cp++ = '\0';
- }
- argtable[argc] = NULL;
- *argcptr = argc;
- *argvptr = argtable;
- return TRUE;
- }
- #endif
- #ifdef L_makestring
- /*
- * Make a NULL-terminated string out of an argc, argv pair.
- * Returns TRUE if successful, or FALSE if the string is too long,
- * with an error message given. This does not handle spaces within
- * arguments correctly.
- */
- BOOL
- makestring(argc, argv, buf, buflen)
- char **argv;
- char *buf;
- {
- int len;
- while (argc-- > 0) {
- len = strlen(*argv);
- if (len >= buflen) {
- fprintf(stderr, "Argument string too long\n");
- return FALSE;
- }
- strcpy(buf, *argv++);
- buf += len;
- buflen -= len;
- if (argc)
- *buf++ = ' ';
- buflen--;
- }
- *buf = '\0';
- return TRUE;
- }
- #endif
- #ifdef L_chunks
- typedef struct chunk CHUNK;
- #define CHUNKINITSIZE 4
- struct chunk {
- CHUNK *next;
- char data[CHUNKINITSIZE]; /* actually of varying length */
- };
- static CHUNK * chunklist;
- /*
- * Allocate a chunk of memory (like malloc).
- * The difference, though, is that the memory allocated is put on a
- * list of chunks which can be freed all at one time. You CAN NOT free
- * an individual chunk.
- */
- char *
- getchunk(size)
- {
- CHUNK *chunk;
- if (size < CHUNKINITSIZE)
- size = CHUNKINITSIZE;
- chunk = (CHUNK *) malloc(size + sizeof(CHUNK) - CHUNKINITSIZE);
- if (chunk == NULL)
- return NULL;
- chunk->next = chunklist;
- chunklist = chunk;
- return chunk->data;
- }
- /*
- * Free all chunks of memory that had been allocated since the last
- * call to this routine.
- */
- void
- freechunks()
- {
- CHUNK *chunk;
- while (chunklist) {
- chunk = chunklist;
- chunklist = chunk->next;
- free((char *) chunk);
- }
- }
- #endif
- #ifdef L_expandenvvar
- /* Expand environment variables
- * Variable names must use a-z, A-Z, 0-9, or _
- * Backslashes are also interpreted to preserve the literal value of the
- * next character.
- * Returns NULL if there is an error, otherwise returns a pointer
- * to a static buffer containing the expand command line.
- *
- * Makes a lame attempt to not expand inside single quotes.
- */
- char *
- expandenvvar(cmd)
- char *cmd;
- {
- static char newcmd[CMDLEN+1];
- char* newp = newcmd;
- int freelength = CMDLEN; /* Don't include final terminator */
- char varname[CMDLEN+1];
- char* varp;
- char* value;
- int valuelength;
- int quoted = 0;
- if (cmd == NULL) {
- return NULL;
- }
- if (strlen(cmd) > freelength) {
- fprintf(stderr, "Variable expansion too long\n");
- return NULL;
- }
- while (*cmd) {
- int copy = 1;
- switch (*cmd) {
- case '$':
- if (!quoted) {
- copy = 0;
- cmd++;
- varp = varname;
- while (isalnum(*cmd) || (*cmd == '_') || (*cmd == '?')) {
- *varp++ = *cmd++;
- }
- *varp = '\0';
- if ((*varname) && (value = getenv(varname))) {
- valuelength = strlen(value);
- if (valuelength > freelength) {
- fprintf(stderr, "Variable expansion too long\n");
- return NULL;
- }
- strncpy(newp, value, valuelength);
- newp += valuelength;
- freelength -= valuelength;
- }
- }
- break;
- case '\'':
- quoted = !quoted;
- break;
- case '\\':
- cmd++;
- break;
- }
- if (copy) {
- if (freelength < 1) {
- fprintf(stderr, "Variable expansion too long\n");
- return NULL;
- }
- *newp++ = *cmd++;
- freelength--;
- }
- }
- *newp = '\0';
- return newcmd;
- }
- #endif
- /* END CODE */
|