Initial revision

This commit is contained in:
hsn 2003-10-04 11:26:09 +00:00
parent 1c94496bd8
commit 21509ef941
5 changed files with 1492 additions and 0 deletions

629
bsd_src/function.c Normal file
View File

@ -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 <unistd.h>
#endif
#endif
#include <stdio.h>
#ifdef STDC_HEADERS
#include <stdlib.h>
#endif
#include "my-string.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#ifdef _POSIX_SOURCE
#include "limits.h"
#if !defined(MAXPATHLEN) && defined(PATH_MAX)
#define MAXPATHLEN PATH_MAX
#endif
#endif
#ifdef HAVE_TZFILE_H
#include <tzfile.h>
#endif
#include "common_def.h"
#include "client_def.h"
#include "c_extern.h"
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#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));
}

441
bsd_src/ls.c Normal file
View File

@ -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 <sys/ioctl.h>
#ifdef STDC_HEADERS
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#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);
}

127
bsd_src/option.c Normal file
View File

@ -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 <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#ifdef STDC_HEADERS
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#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));
}

164
common/udp_io.c Normal file
View File

@ -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 <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#define DSIZE (sizeof(int)*8)
#define SAVE_ERRNO(A) { int sav; sav = errno; A; errno = sav; }
#ifndef EXOS_IPC
#include <netdb.h>
#include <netinet/in.h>
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 */

131
include/find.h Normal file
View File

@ -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_ */