From 21509ef941d9f32fb2b4a98455cfeafe9106ae0c Mon Sep 17 00:00:00 2001 From: hsn <> Date: Sat, 4 Oct 2003 11:26:09 +0000 Subject: [PATCH] Initial revision --- bsd_src/function.c | 629 +++++++++++++++++++++++++++++++++++++++++++++ bsd_src/ls.c | 441 +++++++++++++++++++++++++++++++ bsd_src/option.c | 127 +++++++++ common/udp_io.c | 164 ++++++++++++ include/find.h | 131 ++++++++++ 5 files changed, 1492 insertions(+) create mode 100644 bsd_src/function.c create mode 100644 bsd_src/ls.c create mode 100644 bsd_src/option.c create mode 100644 common/udp_io.c create mode 100644 include/find.h diff --git a/bsd_src/function.c b/bsd_src/function.c new file mode 100644 index 0000000..0d466b0 --- /dev/null +++ b/bsd_src/function.c @@ -0,0 +1,629 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Cimarron D. Taylor of the University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "tweak.h" +#ifdef HAVE_UNISTD_H +#ifndef __hpux +#include +#endif +#endif +#include +#ifdef STDC_HEADERS +#include +#endif +#include "my-string.h" +#include +#include +#include +#ifdef _POSIX_SOURCE +#include "limits.h" +#if !defined(MAXPATHLEN) && defined(PATH_MAX) +#define MAXPATHLEN PATH_MAX +#endif +#endif +#ifdef HAVE_TZFILE_H +#include +#endif +#include "common_def.h" +#include "client_def.h" +#include "c_extern.h" +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#ifdef HAVE_SYS_WAIT_H +#include +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif +#include "find.h" + + +#define FIND_EQUAL 0 +#define FIND_LESSTHAN 1 +#define FIND_GREATER 2 + +#define COMPARE(a, b) { \ + switch(plan->flags) { \ + case FIND_EQUAL: \ + return(a == b); \ + case FIND_LESSTHAN: \ + return(a < b); \ + case FIND_GREATER: \ + return(a > b); \ + } \ + return(0); \ +} + +#ifdef PROTOTYPES +static PLAN *palloc (enum ntype t, int (*f)()) +#else +static PLAN *palloc (t, f) + enum ntype t; + int (*f)(); +#endif +{ + PLAN *new; + + new = (PLAN *) malloc(sizeof(PLAN)); + + if ( new ) { + new->type = t; + new->eval = f; + new->flags = 0; + new->next = NULL; + return(new); + } + perror("palloc"); + exit(1); +} + +extern int isoutput; +extern int process; + +/* + * find_parsenum -- + * Parse a string of the form [+-]# and return the value. + */ +static long find_parsenum PROTO4(PLAN *, plan, const char *, option, char *, str, + char *, endch) +{ + long value; + char *endchar; /* pointer to character ending conversion */ + + /* determine comparison from leading + or - */ + switch(*str) { + case '+': + ++str; + plan->flags = FIND_GREATER; + break; + case '-': + ++str; + plan->flags = FIND_LESSTHAN; + break; + default: + plan->flags = FIND_EQUAL; + break; + } + + /* + * convert the string with strtol(). Note, if strtol() returns zero + * and endchar points to the beginning of the string we know we have + * a syntax error. + */ + value = strtol(str, &endchar, 10); + if ( (!value && endchar == str) || (endchar[0] && + (!endch || endchar[0] != *endch))) { + fprintf(stderr,"%s: %s", option, "illegal numeric value"); + exit(1); + } + if (endch) + *endch = endchar[0]; + return(value); +} + +/* + * -time n functions -- + * + * True if the difference between the file time and the + * current time is n 24 hour periods. + * + */ + +extern time_t now; +static int find_time PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) +{ + + /* with FSP sbuf.st_atime=sbuf.st_ctime=sbuf.st_mtime */ + COMPARE((now - sbuf->st_atime + SECSPERDAY - 1) / SECSPERDAY, plan->t_data); +} + + +PLAN * c_time PROTO1(char *, arg) +{ + PLAN *new; + + new = palloc(N_TIME, find_time); + new->t_data = find_parsenum(new, "-time", arg, NULL); + return(new); +} + +/* + * brace_subst -- + * Replace occurrences of {} in s1 with s2 and return the result string. + */ +static void brace_subst PROTO4(char *, orig, char **, store, char *, path, int,len) +{ + register int plen; + register char ch, *p; + + plen = strlen(path); + for (p = *store; (ch = *orig) ; ++orig) + if (ch == '{' && orig[1] == '}') { + while ((p - *store) + plen > len) + if (!(*store = (char *)realloc(*store, len *= 2))) { + perror("realloc"); + client_done(); + exit(1); + } + bcopy(path, p, plen); + p += plen; + ++orig; + } else + *p++ = ch; + *p = '\0'; +} + +/* + * queryuser -- + * print a message to standard error and then read input from standard + * input. If the input is 'y' then 1 is returned. + */ +static int queryuser PROTO1(char **, argv) +{ + int ch, first, nl; + + fprintf(stderr, "\"%s", *argv); + while (*++argv) fprintf(stderr, " %s", *argv); + fprintf(stderr, "\"? "); + fflush(stderr); + + first = ch = getchar(); + for (nl = 0;;) + { + if (ch == '\n') + { + nl = 1; + break; + } + if (ch == EOF) break; + ch = getchar(); + } + + if (!nl) { + fprintf(stderr, "\n"); + fflush(stderr); + } + return(first == 'y'); +} + +/* + * [-exec | -ok] utility [arg ... ] ; functions -- + * + * True if the executed utility returns a zero value as exit status. + * The end of the primary expression is delimited by a semicolon. If + * "{}" occurs anywhere, it gets replaced by the current pathname. + * The current directory for the execution of utility is the same as + * the current directory when the find utility was started. + * + * The primary -ok is different in that it requests affirmation of the + * user before executing the utility. + */ +static int find_exec PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) +{ + register int cnt; + pid_t pid; +#ifndef HAVE_UNION_WAIT + int status; +#else + union wait status; +#endif + + for (cnt = 0; plan->e_argv[cnt]; ++cnt) + if (plan->e_len[cnt]) + brace_subst(plan->e_orig[cnt], &plan->e_argv[cnt], path, + plan->e_len[cnt]); + + if (plan->flags && !queryuser(plan->e_argv)) return(0); + + switch(pid = fork()) + { + case -1: + perror ("fork"); + exit(1); + case 0: + execvp(plan->e_argv[0], plan->e_argv); + perror ("execvp"); + exit(1); + } + pid = wait(&status); + + return(pid != -1 && WIFEXITED(status) && !WEXITSTATUS(status)); +} + +static char *emalloc_ffind PROTO1(unsigned int, len) +{ + char *p; + + if ( (p = (char *)malloc(len))) return((char *)p); + perror("malloc"); + exit(1); +} + +/* + * c_exec -- + * build three parallel arrays, one with pointers to the strings passed + * on the command line, one with (possibly duplicated) pointers to the + * argv array, and one with integer values that are lengths of the + * strings, but also flags meaning that the string has to be massaged. + */ +PLAN *c_exec PROTO2(char ***, argvp, int, isok) +{ + PLAN *new; /* node returned */ + register int cnt; + register char **argv, **ap, *p; + + isoutput = 1; + + new = palloc(N_EXEC, find_exec); + new->flags = isok; + + for (ap = argv = *argvp;; ++ap) { + if (!*ap) { + fprintf(stderr,"%s: no terminating", isok ? "-ok" : "-exec"); + exit(1); + } + if (**ap == ';') break; + } + + cnt = ap - *argvp + 1; + new->e_argv = (char **)emalloc_ffind((unsigned int)cnt * sizeof(char *)); + new->e_orig = (char **)emalloc_ffind((unsigned int)cnt * sizeof(char *)); + new->e_len = (int *)emalloc_ffind((unsigned int)cnt * sizeof(int)); + + for (argv = *argvp, cnt = 0; argv < ap; ++argv, ++cnt) { + new->e_orig[cnt] = *argv; + for (p = *argv; *p; ++p) + if (p[0] == '{' && p[1] == '}') { + new->e_argv[cnt] = (char *)emalloc_ffind((unsigned int)MAXPATHLEN); + new->e_len[cnt] = MAXPATHLEN; + break; + } + if (!*p) { + new->e_argv[cnt] = *argv; + new->e_len[cnt] = 0; + } + } + new->e_argv[cnt] = new->e_orig[cnt] = NULL; + + *argvp = argv + 1; + return(new); +} + +static void printtime_ffind PROTO1(time_t, ftime) +{ + int i; + char *longstring; + + longstring = (char *)ctime((long *)&ftime); + for (i = 4; i < 11; ++i) putchar(longstring[i]); + +#define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY) + + if (ftime + SIXMONTHS > time((time_t *)NULL)) + for (i = 11; i < 16; ++i) putchar(longstring[i]); + else { + (void)putchar(' '); + for (i = 20; i < 24; ++i) putchar(longstring[i]); + } + putchar(' '); +} + +#define BLK(A) (((A)+1023)/1024) + +static void printlong_ffind PROTO2(char *, name, struct stat *, sb) +{ + const char *modep; + + printf("%4ld ", (long)BLK(sb->st_size)); + modep = ((S_IFDIR & sb->st_mode)) ? "drwxrwxrwx" : "-rw-rw-rw-" ; + printf("%s %3u %-*s %-*s ", modep, sb->st_nlink, 8, "nobody", 8, "nobody"); + + printf("%8ld ", (long)sb->st_size); + printtime_ffind(sb->st_mtime); + printf("%s", name); + putchar('\n'); +} + +/* + * -ls functions -- + * + * Always true - prints the current sbuf to stdout in "ls" format. + */ +static int find_ls PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) +{ + printlong_ffind(path, sbuf); + return(1); +} + +PLAN *c_ls PROTO0((void)) +{ + isoutput = 1; + return(palloc(N_LS, find_ls)); +} + +/* + * -name functions -- + * + * True if the basename of the filename being examined + * matches pattern using Pattern Matching Notation S3.14 + */ +static int find_name PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) +{ + register char *name; + + /* extract filename */ + for (name = path + strlen(path); name > path && *name != '/'; name--); + if (*name == '/') name++; + return(fnmatch(plan->c_data, name)); +} + +PLAN *c_name PROTO1(char *, pattern) +{ + PLAN *new; + + new = palloc(N_NAME, find_name); + new->c_data = pattern; + return(new); +} + +/* + * -newer file functions -- + * + * True if the current file has been modified more recently + * then the modification time of the file named by the pathname + * file. + */ +static int find_newer PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) +{ + return(sbuf->st_mtime > plan->t_data); +} + +PLAN *c_newer PROTO1(char *, filename) +{ + PLAN *new; + struct stat sb; + + if (stat(filename, &sb)) { + perror("stat"); + exit(1); + } + new = palloc(N_NEWER, find_newer); + new->t_data = sb.st_mtime; + return(new); +} + +/* + * -print functions -- + * + * Always true, causes the current pathame to be written to + * standard output. + */ +static int find_print PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) +{ + (void)printf("%s\n", path); + return(1); +} + +PLAN *c_print PROTO0((void)) +{ + isoutput = 1; + + return(palloc(N_PRINT, find_print)); +} + +/* + * -prune functions -- + * + * Prune a portion of the hierarchy. + */ +static int find_prune PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) +{ + process = -1; + return(1); +} + +PLAN *c_prune PROTO0((void)) +{ + return(palloc(N_PRUNE, find_prune)); +} + +/* + * -size n[c] functions -- + * + * True if the file size in bytes, divided by an implementation defined + * value and rounded up to the next integer, is n. If n is followed by + * a c, the size is in bytes. + */ +#define FIND_SIZE 512 +static int divsize = 1; + +static int find_size PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) +{ + off_t size; + + size = divsize ? ((sbuf->st_size + FIND_SIZE - 1)/FIND_SIZE) : sbuf->st_size; + COMPARE(size, plan->o_data); +} + +PLAN *c_size PROTO1(char *, arg) +{ + PLAN *new; + char endch='c'; + + new = palloc(N_SIZE, find_size); + new->o_data = find_parsenum(new, "-size", arg, &endch); + if (endch == 'c') divsize = 0; + return(new); +} + +/* + * -type c functions -- + * + * True if the type of the file is c, where c is d or f for + * directory or regular file, respectively. + */ +static int find_type PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) +{ + return((sbuf->st_mode & S_IFMT) == plan->m_data); +} + +PLAN *c_type PROTO1(char *, typestring) +{ + PLAN *new; + mode_t mask; + + switch (typestring[0]) { + case 'd': + mask = S_IFDIR; + break; + case 'f': + mask = S_IFREG; + break; + default: + fprintf(stderr,"-type: unknown type"); + exit(1); + } + + new = palloc(N_TYPE, find_type); + new->m_data = mask; + return(new); +} + +/* + * ( expression ) functions -- + * + * True if expression is true. + */ +int find_expr PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) +{ + register PLAN *p; + register int state; + + for(p=plan->p_data[0]; p && (state=(p->eval)(p, sbuf, path)); p=p->next); + return(state); +} + +/* + * N_OPENPAREN and N_CLOSEPAREN nodes are temporary place markers. They are + * eliminated during phase 2 of find_formplan() --- the '(' node is converted + * to a N_EXPR node containing the expression and the ')' node is discarded. + */ +PLAN *c_openparen PROTO0((void)) +{ + return(palloc(N_OPENPAREN, (int (*)())-1)); +} + +PLAN *c_closeparen PROTO0((void)) +{ + return(palloc(N_CLOSEPAREN, (int (*)())-1)); +} + + +/* + * ! expression functions -- + * + * Negation of a primary; the unary NOT operator. + */ +static int find_not PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) +{ + register PLAN *p; + register int state; + + for(p=plan->p_data[0]; p && (state=(p->eval)(p, sbuf, path)); p=p->next); + return(!state); +} + +PLAN *c_not PROTO0((void)) +{ + return(palloc(N_NOT, find_not)); +} + +/* + * expression -o expression functions -- + * + * Alternation of primaries; the OR operator. The second expression is + * not evaluated if the first expression is true. + */ +static int find_or PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) +{ + register PLAN *p; + register int state; + + for(p=plan->p_data[0]; p && (state=(p->eval)(p, sbuf, path)); p=p->next); + + if (state) return(1); + + for(p=plan->p_data[1]; p && (state=(p->eval)(p, sbuf, path)); p=p->next); + return(state); +} + +PLAN *c_or PROTO0((void)) +{ + return(palloc(N_OR, find_or)); +} diff --git a/bsd_src/ls.c b/bsd_src/ls.c new file mode 100644 index 0000000..99a9b97 --- /dev/null +++ b/bsd_src/ls.c @@ -0,0 +1,441 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Michael Fischbein. + * + * Redistribution and use in source and binary forms are permitted + * provided that: (1) source distributions retain this entire copyright + * notice and comment, and (2) distributions including binaries display + * the following acknowledgement: ``This product includes software + * developed by the University of California, Berkeley and its contributors'' + * in the documentation or other materials provided with the distribution + * and in all advertising materials mentioning features or use of this + * software. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1989 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#include "tweak.h" +#include "bsd_extern.h" +#include "client_def.h" +#include "c_extern.h" +#include +#ifdef STDC_HEADERS +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#include "my-string.h" +#include "ls.h" + +static char path[2*1024 + 1]; +static char *endofpath = path; + +typedef int (*COMPAR)(const void *, const void *); +int (*sortfcn)PROTO0((LS *, LS *)); +void (*printfcn)PROTO0((LS *, int)); + +int termwidth = 80; /* default terminal width */ + +/* flags */ +int f_accesstime; /* use time of last access */ +int f_column; /* columnated format */ +int f_group; /* show group ownership of a file */ +int f_ignorelink; /* indirect through symbolic link operands */ +int f_inode; /* print inode */ +int f_kblocks; /* print size in kilobytes */ +int f_listalldot; /* list . and .. as well */ +int f_listdir; /* list actual directory, not contents */ +int f_listdot; /* list files beginning with . */ +int f_longform; /* long listing format */ +int f_needstat; /* if need to stat files */ +int f_newline; /* if precede with newline */ +int f_nonprint; /* show unprintables as ? */ +int f_nosort; /* don't sort output */ +int f_recursive; /* ls subdirectories also */ +int f_reversesort; /* reverse whatever sort is used */ +int f_singlecol; /* use single column output */ +int f_size; /* list size in short listing */ +int f_statustime; /* use time of last mode change */ +int f_dirname; /* if precede with directory name */ +int f_timesort; /* sort by time vice name */ +int f_total; /* if precede with "total" line */ +int f_type; /* add type character for non-regular files */ + +static int tabdir PROTO2(LS *, lp, LS **, s_stats) +{ + register RDIR *dirp; + register int cnt, maxentry, maxlen; + register char *p; + struct rdirent *dp; + unsigned long blocks; + LS *stats; + + if (!(dirp = util_opendir("."))) { + perror(lp->name); + return(0); + } + blocks = maxentry = maxlen = 0; + stats = NULL; + for (cnt = 0; (dp = util_readdir(dirp));) { + /* this does -A and -a */ + p = dp->d_name; + if (p[0] == '.') { + if (!f_listdot) continue; + if (!f_listalldot && (!p[1] || (p[1] == '.' && !p[2]))) continue; + } + if (cnt == maxentry) { +#define DEFNUM 256 + maxentry += DEFNUM; + if(stats) { + *s_stats = stats = (LS *)realloc((char *)stats, + (unsigned int)maxentry * sizeof(LS)); + if (!*s_stats) nomem(); + } else { + *s_stats = stats = (LS *)malloc((unsigned int)maxentry * sizeof(LS)); + if (!*s_stats) nomem(); + } + } + if (f_needstat && util_stat(dp->d_name, &stats[cnt].lstat)) { + /* + * don't exit -- this could be an NFS mount that has + * gone away. Flush stdout so the messages line up. + */ + (void)fflush(stdout); + perror(dp->d_name); + continue; + } + stats[cnt].name = dp->d_name; + + /* + * get the inode from the directory, so the -f flag + * works right. + */ + stats[cnt].lstat.st_ino = dp->d_fileno; + + /* save name length for -C format */ + stats[cnt].len = dp->d_namlen; + + /* calculate number of blocks if -l/-s formats */ + if (f_longform || f_size) blocks += (stats[cnt].lstat.st_size+1023)/1024; + + /* save max length if -C format */ + if (f_column && maxlen < (int)dp->d_namlen) maxlen = dp->d_namlen; + ++cnt; + } + (void)util_closedir(dirp); + + if (cnt) { + stats[0].lstat.st_btotal = blocks; + stats[0].lstat.st_maxlen = maxlen; + } else if (stats) { + (void)free((char *)stats); + } + return(cnt); +} + +static void displaydir PROTO0((LS *, register int)); + +static void subdir PROTO1(LS *, lp) +{ + LS *stats; + int num; + + if (f_newline) (void)putchar('\n'); + if (f_dirname) (void)printf("%s:\n", path); + + if (util_cd2(lp->name)) { + perror(lp->name); + return; + } + if ( (num = tabdir(lp, &stats))) { + displaydir(stats, num); + (void)free((char *)stats); + } + if (util_cd2("..")) { + perror(".."); + ls_bad(1); + } +} + +static void displaydir PROTO2(LS *, stats, register int, num) +{ + register char *p, *savedpath; + LS *lp; + + if (num > 1 && !f_nosort) { + unsigned long save1, save2; + + save1 = stats[0].lstat.st_btotal; + save2 = stats[0].lstat.st_maxlen; + qsort((char *)stats, num, sizeof(LS), (COMPAR) sortfcn); + stats[0].lstat.st_btotal = save1; + stats[0].lstat.st_maxlen = save2; + } + + printfcn(stats, num); + + if (f_recursive) { + savedpath = endofpath; + for (lp = stats; num--; ++lp) { + if (!(S_ISDIR(lp->lstat.st_mode))) continue; + p = lp->name; + if (p[0] == '.' && (!p[1] || (p[1] == '.' && !p[2]))) continue; + if (endofpath != path && endofpath[-1] != '/') *endofpath++ = '/'; + for (; (*endofpath = *p++); ++endofpath); + f_newline = f_dirname = f_total = 1; + subdir(lp); + *(endofpath = savedpath) = '\0'; + } + } +} + +static void doargs PROTO2(int, argc, char **, argv) +{ + register LS *dstatp, *rstatp; + register int cnt, dircnt, dirmax, maxlen, regcnt, regmax; + LS *dstats, *rstats; + struct stat sb; + char top[2*1024 + 1], **av, *av2[2]; + unsigned long blocks; + + /* + * walk through the operands, building separate arrays of LS + * structures for directory and non-directory files. + */ + dstats = rstats = NULL; + dirmax = regmax = 0; + + for (dircnt = regcnt = 0; *argv; ++argv) { + if(!(av = glob(*argv))) { + av = av2; + av2[0] = *argv; + av2[1] = 0; + } + + for( ; *av; av++) { + if (util_stat(*av, &sb)) { + perror(*av); + if (errno == ENOENT) continue; + ls_bad(1); + } + if ((S_ISDIR(sb.st_mode)) && !f_listdir) { + if(dirmax == dircnt) { + dirmax += 10; + if (!dstats) { + dstatp = dstats = (LS *)emalloc(dirmax * (sizeof(LS))); + } else { + dstats = (LS *)realloc(dstats, dirmax * (sizeof(LS))); + dstatp = dstats + dircnt; + } + } + dstatp->name = *av; + dstatp->lstat = sb; + ++dstatp; + ++dircnt; + } else { + if(regmax == regcnt) { + regmax += 10; + if (!rstats) { + blocks = 0; + maxlen = -1; + rstatp = rstats = (LS *)emalloc(regmax * (sizeof(LS))); + } else { + rstats = (LS *)realloc(rstats, regmax * (sizeof(LS))); + rstatp = rstats + regcnt; + } + } + rstatp->name = *av; + rstatp->lstat = sb; + + /* save name length for -C format */ + rstatp->len = strlen(*av); + + if (f_nonprint) prcopy(*av, *av, rstatp->len); + + /* calculate number of blocks if -l/-s formats */ + if (f_longform || f_size) blocks += (sb.st_size + 1023)/1024; + + /* save max length if -C format */ + if (f_column && maxlen < rstatp->len) maxlen = rstatp->len; + + ++rstatp; + ++regcnt; + } + } + } + /* display regular files */ + if (regcnt) { + rstats[0].lstat.st_btotal = blocks; + rstats[0].lstat.st_maxlen = maxlen; + displaydir(rstats, regcnt); + f_newline = f_dirname = 1; + } + /* display directories */ + if (dircnt) { + register char *p; + + f_total = 1; + if (dircnt > 1) { + (void)util_getwd(top); + qsort((char *)dstats, dircnt, sizeof(LS), (COMPAR) sortfcn); + f_dirname = 1; + } + for (cnt = 0; cnt < dircnt; ++dstats) { + for (endofpath = path, p = dstats->name; + (*endofpath = *p++); ++endofpath); + subdir(dstats); + f_newline = 1; + if (++cnt < dircnt && util_cd2(top)) { + perror(top); + ls_bad(1); + } + } + } +} + +void fls_main PROTO2(int, argc, char **, argv) +{ + int ch; + char *p; + + /* terminal defaults to -Cq, non-terminal defaults to -1 */ + if (isatty(1)) { + f_nonprint = 1; + termwidth = 80; +#ifdef TIOCGWINSZ + { + struct winsize win; + if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) { + if ( (p = (char *)getenv("COLUMNS"))) termwidth = atoi(p); + } else termwidth = win.ws_col; + } +#endif + f_column = 1; + } else f_singlecol = 1; + + /* root is -A automatically */ + if (!getuid()) f_listdot = 1; + + while ((ch = getopt(argc, argv, "1ACFLRacdfgiklqrstu")) != EOF) { + switch (ch) { + /* + * -1, -C and -l all override each other + * so shell aliasing works right + */ + case '1': + f_singlecol = 1; + f_column = f_longform = 0; + break; + case 'C': + f_column = 1; + f_longform = f_singlecol = 0; + break; + case 'l': + f_longform = 1; + f_column = f_singlecol = 0; + break; + /* -c and -u override each other */ + case 'c': + f_statustime = 1; + f_accesstime = 0; + break; + case 'u': + f_accesstime = 1; + f_statustime = 0; + break; + case 'F': + f_type = 1; + break; + case 'L': + f_ignorelink = 1; + break; + case 'R': + f_recursive = 1; + break; + case 'a': + f_listalldot = 1; + /* FALLTHROUGH */ + case 'A': + f_listdot = 1; + break; + case 'd': + f_listdir = 1; + break; + case 'f': + f_nosort = 1; + break; + case 'g': + f_group = 1; + break; + case 'i': + f_inode = 1; + break; + case 'k': + f_kblocks = 1; + break; + case 'q': + f_nonprint = 1; + break; + case 'r': + f_reversesort = 1; + break; + case 's': + f_size = 1; + break; + case 't': + f_timesort = 1; + break; + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + /* -d turns off -R */ + if (f_listdir) + f_recursive = 0; + + /* if need to stat files */ + f_needstat = f_longform || f_recursive || f_timesort || f_size || f_type; + + /* select a sort function */ + if (f_reversesort) { + if (!f_timesort) sortfcn = revnamecmp; + else if (f_accesstime) sortfcn = revacccmp; + else if (f_statustime) sortfcn = revstatcmp; + else sortfcn = revmodcmp; /* use modification time */ + } else { + if (!f_timesort) sortfcn = namecmp; + else if (f_accesstime) sortfcn = acccmp; + else if (f_statustime) sortfcn = statcmp; + else sortfcn = modcmp; /* use modification time */ + } + + /* select a print function */ + if (f_singlecol) printfcn = printscol; + else if (f_longform) printfcn = printlong; + else printfcn = printcol; + + if (!argc) { + argc = 1; + argv[0] = "."; + argv[1] = NULL; + } + doargs(argc, argv); +} + diff --git a/bsd_src/option.c b/bsd_src/option.c new file mode 100644 index 0000000..cc192d6 --- /dev/null +++ b/bsd_src/option.c @@ -0,0 +1,127 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Cimarron D. Taylor of the University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "tweak.h" +#include +#include +#include +#ifdef STDC_HEADERS +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#include "my-string.h" +#include "find.h" + +OPTION options[] = { + {"!", N_NOT, c_not, O_ZERO}, + {"(", N_OPENPAREN, c_openparen, O_ZERO}, + {")", N_CLOSEPAREN, c_closeparen, O_ZERO}, + {"-a", N_AND, NULL, O_NONE}, + {"-and", N_AND, NULL, O_NONE}, + {"-exec", N_EXEC, c_exec, O_ARGVP}, + {"-ls", N_LS, c_ls, O_ZERO}, + {"-name", N_NAME, c_name, O_ARGV}, + {"-newer", N_NEWER, c_newer, O_ARGV}, + {"-o", N_OR, c_or, O_ZERO}, + {"-ok", N_OK, c_exec, O_ARGVP}, + {"-or", N_OR, c_or, O_ZERO}, + {"-print", N_PRINT, c_print, O_ZERO}, + {"-prune", N_PRUNE, c_prune, O_ZERO}, + {"-size", N_SIZE, c_size, O_ARGV}, + {"-time", N_TIME, c_time, O_ARGV}, + {"-type", N_TYPE, c_type, O_ARGV} +}; + +/* + * find_create -- + * create a node corresponding to a command line argument. + * + * TODO: + * add create/process function pointers to node, so we can skip + * this switch stuff. + */ +PLAN *find_create PROTO1(char ***, argvp) +{ + register OPTION *p; + PLAN *new; + char **argv; + + argv = *argvp; + + if ((p = option(*argv)) == NULL) { + (void)fprintf(stderr, "find: unknown option %s.\n", *argv); + exit(1); + } + ++argv; + if (p->flags & (O_ARGV|O_ARGVP) && !*argv) { + (void)fprintf(stderr, "find: %s requires additional arguments.\n", + *--argv); + exit(1); + } + + switch(p->flags) { + case O_NONE: + new = NULL; + break; + case O_ZERO: + new = (p->create)(); + break; + case O_ARGV: + new = (p->create)(*argv++); + break; + case O_ARGVP: + new = (p->create)(&argv, p->token == N_OK); + break; + } + *argvp = argv; + return(new); +} + +static int typecompare PROTO2(const void *, a, const void *, b) +{ + return(strcmp(((const OPTION *)a)->name, ((const OPTION *)b)->name)); +} + +OPTION *option PROTO1(char *, name) +{ + OPTION tmp; + + tmp.name = name; + return((OPTION *)bsearch(&tmp, options, sizeof(options)/sizeof(OPTION), + sizeof(OPTION), typecompare)); +} diff --git a/common/udp_io.c b/common/udp_io.c new file mode 100644 index 0000000..12a7d62 --- /dev/null +++ b/common/udp_io.c @@ -0,0 +1,164 @@ + /*********************************************************************\ + * Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu) * + * * + * You may copy or modify this file in any manner you wish, provided * + * that this notice is always included, and that you hold the author * + * harmless for any loss or damage resulting from the installation or * + * use of this software. * + \*********************************************************************/ + +#include "tweak.h" +#include "common_def.h" +#include "co_extern.h" +#include "my-string.h" +#ifdef HAVE_STDC_HEADERS +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + + +#define DSIZE (sizeof(int)*8) +#define SAVE_ERRNO(A) { int sav; sav = errno; A; errno = sav; } + +#ifndef EXOS_IPC +#include +#include + +int _x_udp PROTO1(unsigned short *, port) +{ + int f; + socklen_t len; + struct sockaddr_in me ; + struct sockaddr_in myadr; + int zz=1; + + memset(&me,0,sizeof(me)); + + me.sin_port = htons(*port); + me.sin_family = AF_INET; + + len=sizeof(me); + + if((f=socket(AF_INET,SOCK_DGRAM,0)) == -1) return(-1); + + if(setsockopt(f,SOL_SOCKET,SO_REUSEADDR,(char *)&zz,sizeof(zz)) < 0 || + bind(f,(struct sockaddr *) &me,len) < 0 || + getsockname(f,(struct sockaddr *)&myadr,&len) < 0) { + SAVE_ERRNO(((void) close(f))); + return(-1); + } + if(!*port) *port = ntohs((unsigned short) myadr.sin_port); + return(f); +} + +int _x_adr PROTO3(const char *, host, int, port, struct sockaddr_in *, his) +{ + char myhost[128]; + struct hostent *H; + int i; + char *s, *d; + + memset(his,0,sizeof(his)); + if(!host) { + gethostname(myhost,sizeof(myhost)); + host=myhost; + } + + /* if((his->sin_addr.s_addr = inet_addr(host)) != -1) */ + if(inet_aton(host,&his->sin_addr)) + his->sin_family = AF_INET; + else + if( (H = gethostbyname(host))) { + for(s = (char *)H->h_addr, d = (char *)&his->sin_addr, i = H->h_length; + i--; *d++ = *s++); + his->sin_family = H->h_addrtype; + } else return(-1); + his->sin_port = htons((unsigned short) port); + + return(0); +} + +int _x_select PROTO2(fd_set *, rf, long, tt) /* tt is in unit of ms */ +{ + struct timeval timeout; + + if(tt != -1) { + if(tt < MIN_DELAY) tt = MIN_DELAY; + timeout.tv_sec = tt / 1000; + timeout.tv_usec = (tt % 1000)*1000; + return(select(DSIZE, rf, NULL, NULL, &timeout)); + } + + return(select(DSIZE, rf, NULL, NULL , (struct timeval *) 0)); +} +#endif /* not EXOS_IPC */ + +#ifdef EXOS_IPC + +extern long rhost(); + +int _x_udp PROTO1(int *, port) +{ + struct sockaddr_in sin; int f; + + sin = INET_ZERO; + sin.sin_family = AF_INET; + sin.sin_port = htons((unsigned short) *port); + if((f = socket(SOCK_DGRAM, (struct sockproto *) 0, &sin, + SO_REUSEADDR)) == -1) + return(-1); + sin = INET_ZERO; + if(socketaddr(f,&sin) == -1) { + SAVE(((void) close(f))); + return(-1); + } + if(!*port) *port = ntohs((unsigned short) sin.sin_port); + return(f); +} + +int _x_adr PROTO3(char *, host, int, port, struct sockaddr_in *, his) +{ + char myhost[128]; + int f; + + *his = INET_ZERO; + if(!host) (void) gethostname(host = myhost,sizeof(myhost)); + + his->sin_family = AF_INET; + his->sin_port = htons((unsigned short) port); + + if((his->sin_addr.s_addr = rhost(&host)) == -1) return(-1); + + return(0); +} + +int _x_select PROTO2(unsigned int *, readfds, long, tt) +{ + int code; + long mask = *readfds; + + if(tt & 0xc0000000) tt = 0x3fffffff;/* It does not like 0x7fffffff. */ + + code = select(DSIZE, &mask, (long *) 0, tt); + + *readfds = mask; + + return(code); +} + +int recvfrom PROTO6(int, s, char *, msg, int, len, int, flags, + struct sockaddr_in *, from, int *, fromlen) +{ + return(receive(s,from,msg,len)); +} + +int sendto PROTO6(int, s, char *, msg, int, len, int, flags, + struct sockaddr_in *, to, int *, tolen) +{ + to->sin_family = AF_INET; + return(send(s,to,msg,len)); +} + +#endif /* EXOS_IPC */ diff --git a/include/find.h b/include/find.h new file mode 100644 index 0000000..47f0cb8 --- /dev/null +++ b/include/find.h @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Cimarron D. Taylor of the University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)find.h 5.8 (Berkeley) 5/24/91 + */ + +#ifndef _FSP_FIND_H_ +#define _FSP_FIND_H_ 1 + +/* node type */ +enum ntype { + N_AND = 1, /* must start > 0 */ + N_TIME, N_CLOSEPAREN, N_EXEC, N_EXPR, + N_LS, N_NAME, N_NEWER, + N_NOT, N_OK, N_OPENPAREN, N_OR, N_PRINT, + N_PRUNE, N_SIZE, N_TYPE +}; + +/* node definition */ +typedef struct _plandata { + struct _plandata *next; /* next node */ + int (*eval) PROTO0((struct _plandata *, struct stat *, char *)); /* node evaluation function */ + int flags; /* private flags */ + enum ntype type; /* plan node type */ + union { + gid_t _g_data; /* gid */ + ino_t _i_data; /* inode */ + mode_t _m_data; /* mode mask */ + nlink_t _l_data; /* link count */ + off_t _o_data; /* file size */ + time_t _t_data; /* time value */ + uid_t _u_data; /* uid */ + struct _plandata *_p_data[2]; /* PLAN trees */ + struct _ex { + char **_e_argv; /* argv array */ + char **_e_orig; /* original strings */ + int *_e_len; /* allocated length */ + } ex; + char *_a_data[2]; /* array of char pointers */ + char *_c_data; /* char pointer */ + } p_un; +#define a_data p_un._a_data +#define c_data p_un._c_data +#define i_data p_un._i_data +#define g_data p_un._g_data +#define l_data p_un._l_data +#define m_data p_un._m_data +#define o_data p_un._o_data +#define p_data p_un._p_data +#define t_data p_un._t_data +#define u_data p_un._u_data +#define e_argv p_un.ex._e_argv +#define e_orig p_un.ex._e_orig +#define e_len p_un.ex._e_len +} PLAN; + +typedef struct _option { + const char *name; /* option name */ + enum ntype token; /* token type */ + PLAN *(*create)(); /* create function */ +#define O_NONE 0x01 /* no call required */ +#define O_ZERO 0x02 /* pass: nothing */ +#define O_ARGV 0x04 /* pass: argv, increment argv */ +#define O_ARGVP 0x08 /* pass: *argv, N_OK || N_EXEC */ + int flags; +} OPTION; + +/* find.c */ +void find_formplan PROTO0((char **)); + +/* fnmatch.c */ +int fnmatch PROTO0((register char *, register char *)); + +/* function.c */ +PLAN * c_time PROTO0((char *)); +PLAN *c_exec PROTO0((char ***, int)); +PLAN *c_ls PROTO0((void)); +PLAN *c_name PROTO0((char *)); +PLAN *c_newer PROTO0((char *)); +PLAN *c_print PROTO0((void)); +PLAN *c_prune PROTO0((void)); +PLAN *c_size PROTO0((char *)); +PLAN *c_type PROTO0((char *)); +int find_expr PROTO0((PLAN *, struct stat *, char *)); +PLAN *c_openparen PROTO0((void)); +PLAN *c_closeparen PROTO0((void)); +PLAN *c_not PROTO0((void)); +PLAN *c_or PROTO0((void)); + +/* operator.c */ +PLAN *paren_squish PROTO0((PLAN *)); +PLAN *not_squish PROTO0((PLAN *)); +PLAN *or_squish PROTO0((PLAN *)); + +/* options.c */ +PLAN *find_create PROTO0((char ***)); +OPTION *option PROTO0((char *)); + +#endif /* _FSP_FIND_H_ */