v15i097: Perl, release 2, Part08/15
Rich Salz
rsalz at uunet.uu.net
Tue Jul 12 07:55:23 AEST 1988
Submitted-by: Larry Wall <lwall at jpl-devvax.jpl.nasa.gov>
Posting-number: Volume 15, Issue 97
Archive-name: perl2/part08
#! /bin/sh
# Make a new directory for the perl sources, cd to it, and run kits 1
# thru 15 through sh. When all 15 kits have been run, read README.
echo "This is perl 2.0 kit 8 (of 15). If kit 8 is complete, the line"
echo '"'"End of kit 8 (of 15)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
mkdir eg eg/scan 2>/dev/null
echo Extracting eval.c
sed >eval.c <<'!STUFFY!FUNK!' -e 's/X//'
X/* $Header: eval.c,v 2.0 88/06/05 00:08:48 root Exp $
X *
X * $Log: eval.c,v $
X * Revision 2.0 88/06/05 00:08:48 root
X * Baseline version 2.0.
X *
X */
X
X#include "EXTERN.h"
X#include "perl.h"
X
X#include <signal.h>
X#include <errno.h>
X
Xextern int errno;
X
X#ifdef VOIDSIG
Xstatic void (*ihand)();
Xstatic void (*qhand)();
X#else
Xstatic int (*ihand)();
Xstatic int (*qhand)();
X#endif
X
XARG *debarg;
XSTR str_args;
X
XSTR *
Xeval(arg,retary,sargoff)
Xregister ARG *arg;
XSTR ***retary; /* where to return an array to, null if nowhere */
Xint sargoff; /* how many elements in sarg are already assigned */
X{
X register STR *str;
X register int anum;
X register int optype;
X int maxarg;
X int maxsarg;
X double value;
X STR *quicksarg[5];
X register STR **sarg = quicksarg;
X register char *tmps;
X char *tmps2;
X int argflags;
X int argtype;
X union argptr argptr;
X int cushion;
X unsigned long tmplong;
X long when;
X FILE *fp;
X STR *tmpstr;
X FCMD *form;
X STAB *stab;
X ARRAY *ary;
X bool assigning = FALSE;
X double exp(), log(), sqrt(), modf();
X char *crypt(), *getenv();
X
X if (!arg)
X return &str_no;
X str = arg->arg_ptr.arg_str;
X optype = arg->arg_type;
X maxsarg = maxarg = arg->arg_len;
X if (maxsarg > 3 || retary) {
X if (sargoff >= 0) { /* array already exists, just append to it */
X cushion = 10;
X sarg = (STR **)saferealloc((char*)*retary,
X (maxsarg+sargoff+2+cushion) * sizeof(STR*)) + sargoff;
X /* Note that sarg points into the middle of the array */
X }
X else {
X sargoff = cushion = 0;
X sarg = (STR **)safemalloc((maxsarg+2) * sizeof(STR*));
X }
X }
X else
X sargoff = 0;
X#ifdef DEBUGGING
X if (debug) {
X if (debug & 8) {
X deb("%s (%lx) %d args:\n",opname[optype],arg,maxarg);
X }
X debname[dlevel] = opname[optype][0];
X debdelim[dlevel++] = ':';
X }
X#endif
X for (anum = 1; anum <= maxarg; anum++) {
X argflags = arg[anum].arg_flags;
X if (argflags & AF_SPECIAL)
X continue;
X argtype = arg[anum].arg_type;
X argptr = arg[anum].arg_ptr;
X re_eval:
X switch (argtype) {
X default:
X sarg[anum] = &str_no;
X#ifdef DEBUGGING
X tmps = "NULL";
X#endif
X break;
X case A_EXPR:
X#ifdef DEBUGGING
X if (debug & 8) {
X tmps = "EXPR";
X deb("%d.EXPR =>\n",anum);
X }
X#endif
X if (retary &&
X (optype == O_LIST || optype == O_ITEM2 || optype == O_ITEM3)) {
X *retary = sarg - sargoff;
X eval(argptr.arg_arg, retary, anum - 1 + sargoff);
X sarg = *retary; /* they do realloc it... */
X argtype = maxarg - anum; /* how many left? */
X maxsarg = (int)(str_gnum(sarg[0])) + argtype;
X sargoff = maxsarg - maxarg;
X if (argtype > 9 - cushion) { /* we don't have room left */
X sarg = (STR **)saferealloc((char*)sarg,
X (maxsarg+2+cushion) * sizeof(STR*));
X }
X sarg += sargoff;
X }
X else
X sarg[anum] = eval(argptr.arg_arg, Null(STR***),-1);
X break;
X case A_CMD:
X#ifdef DEBUGGING
X if (debug & 8) {
X tmps = "CMD";
X deb("%d.CMD (%lx) =>\n",anum,argptr.arg_cmd);
X }
X#endif
X sarg[anum] = cmd_exec(argptr.arg_cmd);
X break;
X case A_STAB:
X sarg[anum] = STAB_STR(argptr.arg_stab);
X#ifdef DEBUGGING
X if (debug & 8) {
X sprintf(buf,"STAB $%s",argptr.arg_stab->stab_name);
X tmps = buf;
X }
X#endif
X break;
X case A_LEXPR:
X#ifdef DEBUGGING
X if (debug & 8) {
X tmps = "LEXPR";
X deb("%d.LEXPR =>\n",anum);
X }
X#endif
X str = eval(argptr.arg_arg,Null(STR***),-1);
X if (!str)
X fatal("panic: A_LEXPR");
X goto do_crement;
X case A_LVAL:
X#ifdef DEBUGGING
X if (debug & 8) {
X sprintf(buf,"LVAL $%s",argptr.arg_stab->stab_name);
X tmps = buf;
X }
X#endif
X str = STAB_STR(argptr.arg_stab);
X if (!str)
X fatal("panic: A_LVAL");
X do_crement:
X assigning = TRUE;
X if (argflags & AF_PRE) {
X if (argflags & AF_UP)
X str_inc(str);
X else
X str_dec(str);
X STABSET(str);
X sarg[anum] = str;
X str = arg->arg_ptr.arg_str;
X }
X else if (argflags & AF_POST) {
X sarg[anum] = str_static(str);
X if (argflags & AF_UP)
X str_inc(str);
X else
X str_dec(str);
X STABSET(str);
X str = arg->arg_ptr.arg_str;
X }
X else {
X sarg[anum] = str;
X }
X break;
X case A_LARYLEN:
X str = sarg[anum] =
X argptr.arg_stab->stab_array->ary_magic;
X#ifdef DEBUGGING
X tmps = "LARYLEN";
X#endif
X if (!str)
X fatal("panic: A_LEXPR");
X goto do_crement;
X case A_ARYLEN:
X stab = argptr.arg_stab;
X sarg[anum] = stab->stab_array->ary_magic;
X str_numset(sarg[anum],(double)(stab->stab_array->ary_fill+arybase));
X#ifdef DEBUGGING
X tmps = "ARYLEN";
X#endif
X break;
X case A_SINGLE:
X sarg[anum] = argptr.arg_str;
X#ifdef DEBUGGING
X tmps = "SINGLE";
X#endif
X break;
X case A_DOUBLE:
X (void) interp(str,str_get(argptr.arg_str));
X sarg[anum] = str;
X#ifdef DEBUGGING
X tmps = "DOUBLE";
X#endif
X break;
X case A_BACKTICK:
X tmps = str_get(argptr.arg_str);
X fp = popen(str_get(interp(str,tmps)),"r");
X tmpstr = str_new(80);
X str_set(str,"");
X if (fp) {
X while (str_gets(tmpstr,fp) != Nullch) {
X str_scat(str,tmpstr);
X }
X statusvalue = pclose(fp);
X }
X else
X statusvalue = -1;
X str_free(tmpstr);
X
X sarg[anum] = str;
X#ifdef DEBUGGING
X tmps = "BACK";
X#endif
X break;
X case A_INDREAD:
X last_in_stab = stabent(str_get(STAB_STR(argptr.arg_stab)),TRUE);
X goto do_read;
X case A_GLOB:
X argflags |= AF_POST; /* enable newline chopping */
X case A_READ:
X last_in_stab = argptr.arg_stab;
X do_read:
X fp = Nullfp;
X if (last_in_stab->stab_io) {
X fp = last_in_stab->stab_io->fp;
X if (!fp) {
X if (last_in_stab->stab_io->flags & IOF_ARGV) {
X if (last_in_stab->stab_io->flags & IOF_START) {
X last_in_stab->stab_io->flags &= ~IOF_START;
X last_in_stab->stab_io->lines = 0;
X if (alen(last_in_stab->stab_array) < 0) {
X tmpstr = str_make("-"); /* assume stdin */
X apush(last_in_stab->stab_array, tmpstr);
X }
X }
X fp = nextargv(last_in_stab);
X if (!fp) /* Note: fp != last_in_stab->stab_io->fp */
X do_close(last_in_stab,FALSE); /* now it does */
X }
X else if (argtype == A_GLOB) {
X (void) interp(str,str_get(last_in_stab->stab_val));
X tmps = str->str_ptr;
X if (*tmps == '!')
X sprintf(tokenbuf,"%s|",tmps+1);
X else {
X if (*tmps == ';')
X sprintf(tokenbuf, "%s", tmps+1);
X else
X sprintf(tokenbuf, "echo %s", tmps);
X strcat(tokenbuf,
X "|tr -s ' \t\f\r' '\\012\\012\\012\\012'|");
X }
X do_open(last_in_stab,tokenbuf);
X fp = last_in_stab->stab_io->fp;
X }
X }
X }
X if (!fp && dowarn)
X warn("Read on closed filehandle <%s>",last_in_stab->stab_name);
X keepgoing:
X if (!fp)
X sarg[anum] = &str_no;
X else if (!str_gets(str,fp)) {
X if (last_in_stab->stab_io->flags & IOF_ARGV) {
X fp = nextargv(last_in_stab);
X if (fp)
X goto keepgoing;
X do_close(last_in_stab,FALSE);
X last_in_stab->stab_io->flags |= IOF_START;
X }
X else if (argflags & AF_POST) {
X do_close(last_in_stab,FALSE);
X }
X if (fp == stdin) {
X clearerr(fp);
X }
X sarg[anum] = &str_no;
X if (retary) {
X maxarg = anum - 1;
X maxsarg = maxarg + sargoff;
X }
X break;
X }
X else {
X last_in_stab->stab_io->lines++;
X sarg[anum] = str;
X if (argflags & AF_POST) {
X if (str->str_cur > 0)
X str->str_cur--;
X str->str_ptr[str->str_cur] = '\0';
X }
X if (retary) {
X sarg[anum] = str_static(sarg[anum]);
X anum++;
X if (anum > maxarg) {
X maxarg = anum + anum;
X maxsarg = maxarg + sargoff;
X sarg = (STR **)saferealloc((char*)(sarg-sargoff),
X (maxsarg+2+cushion) * sizeof(STR*)) + sargoff;
X }
X goto keepgoing;
X }
X }
X if (retary) {
X maxarg = anum - 1;
X maxsarg = maxarg + sargoff;
X }
X#ifdef DEBUGGING
X tmps = "READ";
X#endif
X break;
X }
X#ifdef DEBUGGING
X if (debug & 8)
X deb("%d.%s = '%s'\n",anum,tmps,str_peek(sarg[anum]));
X#endif
X }
X switch (optype) {
X case O_ITEM:
X if (maxarg > arg->arg_len)
X goto array_return;
X if (str != sarg[1])
X str_sset(str,sarg[1]);
X STABSET(str);
X break;
X case O_ITEM2:
X if (str != sarg[--anum])
X str_sset(str,sarg[anum]);
X STABSET(str);
X break;
X case O_ITEM3:
X if (str != sarg[--anum])
X str_sset(str,sarg[anum]);
X STABSET(str);
X break;
X case O_CONCAT:
X if (str != sarg[1])
X str_sset(str,sarg[1]);
X str_scat(str,sarg[2]);
X STABSET(str);
X break;
X case O_REPEAT:
X if (str != sarg[1])
X str_sset(str,sarg[1]);
X anum = (int)str_gnum(sarg[2]);
X if (anum >= 1) {
X tmpstr = str_new(0);
X str_sset(tmpstr,str);
X while (--anum > 0)
X str_scat(str,tmpstr);
X }
X else
X str_sset(str,&str_no);
X STABSET(str);
X break;
X case O_MATCH:
X str_sset(str, do_match(arg,
X retary,sarg,&maxsarg,sargoff,cushion));
X if (retary) {
X sarg = *retary; /* they realloc it */
X goto array_return;
X }
X STABSET(str);
X break;
X case O_NMATCH:
X str_sset(str, do_match(arg,
X retary,sarg,&maxsarg,sargoff,cushion));
X if (retary) {
X sarg = *retary; /* they realloc it */
X goto array_return; /* ignore negation */
X }
X str_set(str, str_true(str) ? No : Yes);
X STABSET(str);
X break;
X case O_SUBST:
X value = (double) do_subst(str, arg);
X str = arg->arg_ptr.arg_str;
X goto donumset;
X case O_NSUBST:
X str_set(arg->arg_ptr.arg_str, do_subst(str, arg) ? No : Yes);
X str = arg->arg_ptr.arg_str;
X break;
X case O_ASSIGN:
X if (arg[1].arg_flags & AF_SPECIAL)
X do_assign(str,arg,sarg);
X else {
X if (str != sarg[2])
X str_sset(str, sarg[2]);
X STABSET(str);
X }
X break;
X case O_CHOP:
X tmps = str_get(str);
X tmps += str->str_cur - (str->str_cur != 0);
X str_set(arg->arg_ptr.arg_str,tmps); /* remember last char */
X *tmps = '\0'; /* wipe it out */
X str->str_cur = tmps - str->str_ptr;
X str->str_nok = 0;
X str = arg->arg_ptr.arg_str;
X break;
X case O_STUDY:
X value = (double)do_study(str);
X str = arg->arg_ptr.arg_str;
X goto donumset;
X case O_MULTIPLY:
X value = str_gnum(sarg[1]);
X value *= str_gnum(sarg[2]);
X goto donumset;
X case O_DIVIDE:
X if ((value = str_gnum(sarg[2])) == 0.0)
X fatal("Illegal division by zero");
X value = str_gnum(sarg[1]) / value;
X goto donumset;
X case O_MODULO:
X if ((tmplong = (unsigned long) str_gnum(sarg[2])) == 0L)
X fatal("Illegal modulus zero");
X value = str_gnum(sarg[1]);
X value = (double)(((unsigned long)value) % tmplong);
X goto donumset;
X case O_ADD:
X value = str_gnum(sarg[1]);
X value += str_gnum(sarg[2]);
X goto donumset;
X case O_SUBTRACT:
X value = str_gnum(sarg[1]);
X value -= str_gnum(sarg[2]);
X goto donumset;
X case O_LEFT_SHIFT:
X value = str_gnum(sarg[1]);
X anum = (int)str_gnum(sarg[2]);
X value = (double)(((unsigned long)value) << anum);
X goto donumset;
X case O_RIGHT_SHIFT:
X value = str_gnum(sarg[1]);
X anum = (int)str_gnum(sarg[2]);
X value = (double)(((unsigned long)value) >> anum);
X goto donumset;
X case O_LT:
X value = str_gnum(sarg[1]);
X value = (double)(value < str_gnum(sarg[2]));
X goto donumset;
X case O_GT:
X value = str_gnum(sarg[1]);
X value = (double)(value > str_gnum(sarg[2]));
X goto donumset;
X case O_LE:
X value = str_gnum(sarg[1]);
X value = (double)(value <= str_gnum(sarg[2]));
X goto donumset;
X case O_GE:
X value = str_gnum(sarg[1]);
X value = (double)(value >= str_gnum(sarg[2]));
X goto donumset;
X case O_EQ:
X value = str_gnum(sarg[1]);
X value = (double)(value == str_gnum(sarg[2]));
X goto donumset;
X case O_NE:
X value = str_gnum(sarg[1]);
X value = (double)(value != str_gnum(sarg[2]));
X goto donumset;
X case O_BIT_AND:
X value = str_gnum(sarg[1]);
X value = (double)(((unsigned long)value) &
X (unsigned long)str_gnum(sarg[2]));
X goto donumset;
X case O_XOR:
X value = str_gnum(sarg[1]);
X value = (double)(((unsigned long)value) ^
X (unsigned long)str_gnum(sarg[2]));
X goto donumset;
X case O_BIT_OR:
X value = str_gnum(sarg[1]);
X value = (double)(((unsigned long)value) |
X (unsigned long)str_gnum(sarg[2]));
X goto donumset;
X case O_AND:
X if (str_true(sarg[1])) {
X anum = 2;
X optype = O_ITEM2;
X argflags = arg[anum].arg_flags;
X argtype = arg[anum].arg_type;
X argptr = arg[anum].arg_ptr;
X maxarg = anum = 1;
X goto re_eval;
X }
X else {
X if (assigning) {
X str_sset(str, sarg[1]);
X STABSET(str);
X }
X else
X str = sarg[1];
X break;
X }
X case O_OR:
X if (str_true(sarg[1])) {
X if (assigning) {
X str_sset(str, sarg[1]);
X STABSET(str);
X }
X else
X str = sarg[1];
X break;
X }
X else {
X anum = 2;
X optype = O_ITEM2;
X argflags = arg[anum].arg_flags;
X argtype = arg[anum].arg_type;
X argptr = arg[anum].arg_ptr;
X maxarg = anum = 1;
X goto re_eval;
X }
X case O_COND_EXPR:
X anum = (str_true(sarg[1]) ? 2 : 3);
X optype = (anum == 2 ? O_ITEM2 : O_ITEM3);
X argflags = arg[anum].arg_flags;
X argtype = arg[anum].arg_type;
X argptr = arg[anum].arg_ptr;
X maxarg = anum = 1;
X goto re_eval;
X case O_COMMA:
X str = sarg[2];
X break;
X case O_NEGATE:
X value = -str_gnum(sarg[1]);
X goto donumset;
X case O_NOT:
X value = (double) !str_true(sarg[1]);
X goto donumset;
X case O_COMPLEMENT:
X value = (double) ~(long)str_gnum(sarg[1]);
X goto donumset;
X case O_SELECT:
X if (arg[1].arg_type == A_LVAL)
X defoutstab = arg[1].arg_ptr.arg_stab;
X else
X defoutstab = stabent(str_get(sarg[1]),TRUE);
X if (!defoutstab->stab_io)
X defoutstab->stab_io = stio_new();
X curoutstab = defoutstab;
X str_set(str,curoutstab->stab_io->fp ? Yes : No);
X STABSET(str);
X break;
X case O_WRITE:
X if (maxarg == 0)
X stab = defoutstab;
X else if (arg[1].arg_type == A_LVAL)
X stab = arg[1].arg_ptr.arg_stab;
X else
X stab = stabent(str_get(sarg[1]),TRUE);
X if (!stab->stab_io) {
X str_set(str, No);
X STABSET(str);
X break;
X }
X curoutstab = stab;
X fp = stab->stab_io->fp;
X debarg = arg;
X if (stab->stab_io->fmt_stab)
X form = stab->stab_io->fmt_stab->stab_form;
X else
X form = stab->stab_form;
X if (!form || !fp) {
X str_set(str, No);
X STABSET(str);
X break;
X }
X format(&outrec,form);
X do_write(&outrec,stab->stab_io);
X if (stab->stab_io->flags & IOF_FLUSH)
X fflush(fp);
X str_set(str, Yes);
X STABSET(str);
X break;
X case O_OPEN:
X if (arg[1].arg_type == A_WORD)
X stab = arg[1].arg_ptr.arg_stab;
X else
X stab = stabent(str_get(sarg[1]),TRUE);
X if (do_open(stab,str_get(sarg[2]))) {
X value = (double)forkprocess;
X stab->stab_io->lines = 0;
X goto donumset;
X }
X else
X str_set(str, No);
X STABSET(str);
X break;
X case O_TRANS:
X value = (double) do_trans(str,arg);
X str = arg->arg_ptr.arg_str;
X goto donumset;
X case O_NTRANS:
X str_set(arg->arg_ptr.arg_str, do_trans(str,arg) == 0 ? Yes : No);
X str = arg->arg_ptr.arg_str;
X break;
X case O_CLOSE:
X if (arg[1].arg_type == A_WORD)
X stab = arg[1].arg_ptr.arg_stab;
X else
X stab = stabent(str_get(sarg[1]),TRUE);
X str_set(str, do_close(stab,TRUE) ? Yes : No );
X STABSET(str);
X break;
X case O_EACH:
X str_sset(str,do_each(arg[1].arg_ptr.arg_stab->stab_hash,
X retary,sarg,&maxsarg,sargoff,cushion));
X if (retary) {
X sarg = *retary; /* they realloc it */
X goto array_return;
X }
X STABSET(str);
X break;
X case O_VALUES:
X case O_KEYS:
X value = (double) do_kv(arg[1].arg_ptr.arg_stab->stab_hash, optype,
X retary,sarg,&maxsarg,sargoff,cushion);
X if (retary) {
X sarg = *retary; /* they realloc it */
X goto array_return;
X }
X goto donumset;
X case O_ARRAY:
X if (maxarg == 1) {
X ary = arg[1].arg_ptr.arg_stab->stab_array;
X maxarg = ary->ary_fill;
X maxsarg = maxarg + sargoff;
X if (retary) { /* array wanted */
X sarg = (STR **)saferealloc((char*)(sarg-sargoff),
X (maxsarg+3+cushion)*sizeof(STR*)) + sargoff;
X for (anum = 0; anum <= maxarg; anum++) {
X sarg[anum+1] = str = afetch(ary,anum);
X }
X maxarg++;
X maxsarg++;
X goto array_return;
X }
X else
X str = afetch(ary,maxarg);
X }
X else
X str = afetch(arg[2].arg_ptr.arg_stab->stab_array,
X ((int)str_gnum(sarg[1])) - arybase);
X if (!str)
X str = &str_no;
X break;
X case O_DELETE:
X tmpstab = arg[2].arg_ptr.arg_stab; /* XXX */
X str = hdelete(tmpstab->stab_hash,str_get(sarg[1]));
X if (!str)
X str = &str_no;
X break;
X case O_HASH:
X tmpstab = arg[2].arg_ptr.arg_stab; /* XXX */
X str = hfetch(tmpstab->stab_hash,str_get(sarg[1]));
X if (!str)
X str = &str_no;
X break;
X case O_LARRAY:
X anum = ((int)str_gnum(sarg[1])) - arybase;
X str = afetch(arg[2].arg_ptr.arg_stab->stab_array,anum);
X if (!str || str == &str_no) {
X str = str_new(0);
X astore(arg[2].arg_ptr.arg_stab->stab_array,anum,str);
X }
X break;
X case O_LHASH:
X tmpstab = arg[2].arg_ptr.arg_stab;
X str = hfetch(tmpstab->stab_hash,str_get(sarg[1]));
X if (!str) {
X str = str_new(0);
X hstore(tmpstab->stab_hash,str_get(sarg[1]),str);
X }
X if (tmpstab == envstab) { /* heavy wizardry going on here */
X str->str_link.str_magic = tmpstab;/* str is now magic */
X envname = savestr(str_get(sarg[1]));
X /* he threw the brick up into the air */
X }
X else if (tmpstab == sigstab) { /* same thing, only different */
X str->str_link.str_magic = tmpstab;
X signame = savestr(str_get(sarg[1]));
X }
X break;
X case O_PUSH:
X if (arg[1].arg_flags & AF_SPECIAL)
X str = do_push(arg,arg[2].arg_ptr.arg_stab->stab_array);
X else {
X str = str_new(0); /* must copy the STR */
X str_sset(str,sarg[1]);
X apush(arg[2].arg_ptr.arg_stab->stab_array,str);
X }
X break;
X case O_POP:
X str = apop(arg[1].arg_ptr.arg_stab->stab_array);
X if (!str) {
X str = &str_no;
X break;
X }
X#ifdef STRUCTCOPY
X *(arg->arg_ptr.arg_str) = *str;
X#else
X bcopy((char*)str, (char*)arg->arg_ptr.arg_str, sizeof *str);
X#endif
X safefree((char*)str);
X str = arg->arg_ptr.arg_str;
X break;
X case O_SHIFT:
X str = ashift(arg[1].arg_ptr.arg_stab->stab_array);
X if (!str) {
X str = &str_no;
X break;
X }
X#ifdef STRUCTCOPY
X *(arg->arg_ptr.arg_str) = *str;
X#else
X bcopy((char*)str, (char*)arg->arg_ptr.arg_str, sizeof *str);
X#endif
X safefree((char*)str);
X str = arg->arg_ptr.arg_str;
X break;
X case O_SPLIT:
X value = (double) do_split(arg[2].arg_ptr.arg_spat,
X retary,sarg,&maxsarg,sargoff,cushion);
X if (retary) {
X sarg = *retary; /* they realloc it */
X goto array_return;
X }
X goto donumset;
X case O_LENGTH:
X value = (double) str_len(sarg[1]);
X goto donumset;
X case O_SPRINTF:
X sarg[maxsarg+1] = Nullstr;
X do_sprintf(str,arg->arg_len,sarg);
X break;
X case O_SUBSTR:
X anum = ((int)str_gnum(sarg[2])) - arybase;
X for (tmps = str_get(sarg[1]); *tmps && anum > 0; tmps++,anum--) ;
X anum = (int)str_gnum(sarg[3]);
X if (anum >= 0 && strlen(tmps) > anum)
X str_nset(str, tmps, anum);
X else
X str_set(str, tmps);
X break;
X case O_JOIN:
X if (arg[2].arg_flags & AF_SPECIAL && arg[2].arg_type == A_EXPR)
X do_join(arg,str_get(sarg[1]),str);
X else
X ajoin(arg[2].arg_ptr.arg_stab->stab_array,str_get(sarg[1]),str);
X break;
X case O_SLT:
X tmps = str_get(sarg[1]);
X value = (double) strLT(tmps,str_get(sarg[2]));
X goto donumset;
X case O_SGT:
X tmps = str_get(sarg[1]);
X value = (double) strGT(tmps,str_get(sarg[2]));
X goto donumset;
X case O_SLE:
X tmps = str_get(sarg[1]);
X value = (double) strLE(tmps,str_get(sarg[2]));
X goto donumset;
X case O_SGE:
X tmps = str_get(sarg[1]);
X value = (double) strGE(tmps,str_get(sarg[2]));
X goto donumset;
X case O_SEQ:
X tmps = str_get(sarg[1]);
X value = (double) strEQ(tmps,str_get(sarg[2]));
X goto donumset;
X case O_SNE:
X tmps = str_get(sarg[1]);
X value = (double) strNE(tmps,str_get(sarg[2]));
X goto donumset;
X case O_SUBR:
X str_sset(str,do_subr(arg,sarg));
X STABSET(str);
X break;
X case O_SORT:
X if (maxarg <= 1)
X stab = defoutstab;
X else {
X if (arg[2].arg_type == A_WORD)
X stab = arg[2].arg_ptr.arg_stab;
X else
X stab = stabent(str_get(sarg[2]),TRUE);
X if (!stab)
X stab = defoutstab;
X }
X value = (double)do_sort(arg,stab,
X retary,sarg,&maxsarg,sargoff,cushion);
X if (retary) {
X sarg = *retary; /* they realloc it */
X goto array_return;
X }
X goto donumset;
X case O_PRTF:
X case O_PRINT:
X if (maxarg <= 1)
X stab = defoutstab;
X else {
X if (arg[2].arg_type == A_WORD)
X stab = arg[2].arg_ptr.arg_stab;
X else
X stab = stabent(str_get(sarg[2]),TRUE);
X if (!stab)
X stab = defoutstab;
X }
X if (!stab->stab_io || !(fp = stab->stab_io->fp))
X value = 0.0;
X else {
X if (arg[1].arg_flags & AF_SPECIAL)
X value = (double)do_aprint(arg,fp);
X else {
X value = (double)do_print(sarg[1],fp);
X if (ors && optype == O_PRINT)
X fputs(ors, fp);
X }
X if (stab->stab_io->flags & IOF_FLUSH)
X fflush(fp);
X }
X goto donumset;
X case O_CHDIR:
X tmps = str_get(sarg[1]);
X if (!tmps || !*tmps)
X tmps = getenv("HOME");
X if (!tmps || !*tmps)
X tmps = getenv("LOGDIR");
X value = (double)(chdir(tmps) >= 0);
X goto donumset;
X case O_DIE:
X tmps = str_get(sarg[1]);
X if (!tmps || !*tmps)
X exit(1);
X fatal("%s",str_get(sarg[1]));
X value = 0.0;
X goto donumset;
X case O_EXIT:
X exit((int)str_gnum(sarg[1]));
X value = 0.0;
X goto donumset;
X case O_RESET:
X str_reset(str_get(sarg[1]));
X value = 1.0;
X goto donumset;
X case O_LIST:
X if (arg->arg_flags & AF_LOCAL)
X savelist(sarg,maxsarg);
X if (maxarg > 0)
X str = sarg[maxsarg]; /* unwanted list, return last item */
X else
X str = &str_no;
X if (retary)
X goto array_return;
X break;
X case O_EOF:
X if (maxarg <= 0)
X stab = last_in_stab;
X else if (arg[1].arg_type == A_WORD)
X stab = arg[1].arg_ptr.arg_stab;
X else
X stab = stabent(str_get(sarg[1]),TRUE);
X str_set(str, do_eof(stab) ? Yes : No);
X STABSET(str);
X break;
X case O_TELL:
X if (maxarg <= 0)
X stab = last_in_stab;
X else if (arg[1].arg_type == A_WORD)
X stab = arg[1].arg_ptr.arg_stab;
X else
X stab = stabent(str_get(sarg[1]),TRUE);
X value = (double)do_tell(stab);
X goto donumset;
X case O_SEEK:
X if (arg[1].arg_type == A_WORD)
X stab = arg[1].arg_ptr.arg_stab;
X else
X stab = stabent(str_get(sarg[1]),TRUE);
X value = str_gnum(sarg[2]);
X str_set(str, do_seek(stab,
X (long)value, (int)str_gnum(sarg[3]) ) ? Yes : No);
X STABSET(str);
X break;
X case O_REDO:
X case O_NEXT:
X case O_LAST:
X if (maxarg > 0) {
X tmps = str_get(sarg[1]);
X while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
X strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
X#ifdef DEBUGGING
X if (debug & 4) {
X deb("(Skipping label #%d %s)\n",loop_ptr,
X loop_stack[loop_ptr].loop_label);
X }
X#endif
X loop_ptr--;
X }
X#ifdef DEBUGGING
X if (debug & 4) {
X deb("(Found label #%d %s)\n",loop_ptr,
X loop_stack[loop_ptr].loop_label);
X }
X#endif
X }
X if (loop_ptr < 0)
X fatal("Bad label: %s", maxarg > 0 ? tmps : "<null>");
X longjmp(loop_stack[loop_ptr].loop_env, optype);
X case O_GOTO:/* shudder */
X goto_targ = str_get(sarg[1]);
X longjmp(top_env, 1);
X case O_INDEX:
X tmps = str_get(sarg[1]);
X if (!(tmps2 = fbminstr(tmps, tmps + sarg[1]->str_cur, sarg[2])))
X value = (double)(-1 + arybase);
X else
X value = (double)(tmps2 - tmps + arybase);
X goto donumset;
X case O_TIME:
X value = (double) time(Null(long*));
X goto donumset;
X case O_TMS:
X value = (double) do_tms(retary,sarg,&maxsarg,sargoff,cushion);
X if (retary) {
X sarg = *retary; /* they realloc it */
X goto array_return;
X }
X goto donumset;
X case O_LOCALTIME:
X when = (long)str_gnum(sarg[1]);
X value = (double)do_time(localtime(&when),
X retary,sarg,&maxsarg,sargoff,cushion);
X if (retary) {
X sarg = *retary; /* they realloc it */
X goto array_return;
X }
X goto donumset;
X case O_GMTIME:
X when = (long)str_gnum(sarg[1]);
X value = (double)do_time(gmtime(&when),
X retary,sarg,&maxsarg,sargoff,cushion);
X if (retary) {
X sarg = *retary; /* they realloc it */
X goto array_return;
X }
X goto donumset;
X case O_STAT:
X value = (double) do_stat(arg,
X retary,sarg,&maxsarg,sargoff,cushion);
X if (retary) {
X sarg = *retary; /* they realloc it */
X goto array_return;
X }
X goto donumset;
X case O_CRYPT:
X#ifdef CRYPT
X tmps = str_get(sarg[1]);
X str_set(str,crypt(tmps,str_get(sarg[2])));
X#else
X fatal(
X "The crypt() function is unimplemented due to excessive paranoia.");
X#endif
X break;
X case O_EXP:
X value = exp(str_gnum(sarg[1]));
X goto donumset;
X case O_LOG:
X value = log(str_gnum(sarg[1]));
X goto donumset;
X case O_SQRT:
X value = sqrt(str_gnum(sarg[1]));
X goto donumset;
X case O_INT:
X value = str_gnum(sarg[1]);
X if (value >= 0.0)
X modf(value,&value);
X else {
X modf(-value,&value);
X value = -value;
X }
X goto donumset;
X case O_ORD:
X value = (double) *str_get(sarg[1]);
X goto donumset;
X case O_SLEEP:
X tmps = str_get(sarg[1]);
X time(&when);
X if (!tmps || !*tmps)
X sleep((32767<<16)+32767);
X else
X sleep((unsigned)atoi(tmps));
X value = (double)when;
X time(&when);
X value = ((double)when) - value;
X goto donumset;
X case O_FLIP:
X if (str_true(sarg[1])) {
X str_numset(str,0.0);
X anum = 2;
X arg->arg_type = optype = O_FLOP;
X arg[2].arg_flags &= ~AF_SPECIAL;
X arg[1].arg_flags |= AF_SPECIAL;
X argflags = arg[2].arg_flags;
X argtype = arg[2].arg_type;
X argptr = arg[2].arg_ptr;
X goto re_eval;
X }
X str_set(str,"");
X break;
X case O_FLOP:
X str_inc(str);
X if (str_true(sarg[2])) {
X arg->arg_type = O_FLIP;
X arg[1].arg_flags &= ~AF_SPECIAL;
X arg[2].arg_flags |= AF_SPECIAL;
X str_cat(str,"E0");
X }
X break;
X case O_FORK:
X value = (double)fork();
X goto donumset;
X case O_WAIT:
X ihand = signal(SIGINT, SIG_IGN);
X qhand = signal(SIGQUIT, SIG_IGN);
X value = (double)wait(&argflags);
X signal(SIGINT, ihand);
X signal(SIGQUIT, qhand);
X statusvalue = (unsigned short)argflags;
X goto donumset;
X case O_SYSTEM:
X while ((anum = vfork()) == -1) {
X if (errno != EAGAIN) {
X value = -1.0;
X goto donumset;
X }
X sleep(5);
X }
X if (anum > 0) {
X ihand = signal(SIGINT, SIG_IGN);
X qhand = signal(SIGQUIT, SIG_IGN);
X while ((argtype = wait(&argflags)) != anum && argtype != -1)
X ;
X signal(SIGINT, ihand);
X signal(SIGQUIT, qhand);
X statusvalue = (unsigned short)argflags;
X if (argtype == -1)
X value = -1.0;
X else {
X value = (double)((unsigned int)argflags & 0xffff);
X }
X goto donumset;
X }
X if (arg[1].arg_flags & AF_SPECIAL)
X value = (double)do_aexec(arg);
X else {
X value = (double)do_exec(str_static(sarg[1]));
X }
X _exit(-1);
X case O_EXEC:
X if (arg[1].arg_flags & AF_SPECIAL)
X value = (double)do_aexec(arg);
X else {
X value = (double)do_exec(str_static(sarg[1]));
X }
X goto donumset;
X case O_HEX:
X argtype = 4;
X goto snarfnum;
X
X case O_OCT:
X argtype = 3;
X
X snarfnum:
X anum = 0;
X tmps = str_get(sarg[1]);
X for (;;) {
X switch (*tmps) {
X default:
X goto out;
X case '8': case '9':
X if (argtype != 4)
X goto out;
X /* FALL THROUGH */
X case '0': case '1': case '2': case '3': case '4':
X case '5': case '6': case '7':
X anum <<= argtype;
X anum += *tmps++ & 15;
X break;
X case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
X case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
X if (argtype != 4)
X goto out;
X anum <<= 4;
X anum += (*tmps++ & 7) + 9;
X break;
X case 'x':
X argtype = 4;
X tmps++;
X break;
X }
X }
X out:
X value = (double)anum;
X goto donumset;
X case O_CHMOD:
X case O_CHOWN:
X case O_KILL:
X case O_UNLINK:
X case O_UTIME:
X if (arg[1].arg_flags & AF_SPECIAL)
X value = (double)apply(optype,arg,Null(STR**));
X else {
X sarg[2] = Nullstr;
X value = (double)apply(optype,arg,sarg);
X }
X goto donumset;
X case O_UMASK:
X value = (double)umask((int)str_gnum(sarg[1]));
X goto donumset;
X case O_RENAME:
X tmps = str_get(sarg[1]);
X#ifdef RENAME
X value = (double)(rename(tmps,str_get(sarg[2])) >= 0);
X#else
X tmps2 = str_get(sarg[2]);
X if (euid || stat(tmps2,&statbuf) < 0 ||
X (statbuf.st_mode & S_IFMT) != S_IFDIR )
X UNLINK(tmps2); /* avoid unlinking a directory */
X if (!(anum = link(tmps,tmps2)))
X anum = UNLINK(tmps);
X value = (double)(anum >= 0);
X#endif
X goto donumset;
X case O_LINK:
X tmps = str_get(sarg[1]);
X value = (double)(link(tmps,str_get(sarg[2])) >= 0);
X goto donumset;
X case O_UNSHIFT:
X ary = arg[2].arg_ptr.arg_stab->stab_array;
X if (arg[1].arg_flags & AF_SPECIAL)
X do_unshift(arg,ary);
X else {
X str = str_new(0); /* must copy the STR */
X str_sset(str,sarg[1]);
X aunshift(ary,1);
X astore(ary,0,str);
X }
X value = (double)(ary->ary_fill + 1);
X break;
X case O_DOFILE:
X case O_EVAL:
X str_sset(str,
X do_eval(arg[1].arg_type != A_NULL ? sarg[1] : defstab->stab_val,
X optype) );
X STABSET(str);
X break;
X
X case O_FTRREAD:
X argtype = 0;
X anum = S_IREAD;
X goto check_perm;
X case O_FTRWRITE:
X argtype = 0;
X anum = S_IWRITE;
X goto check_perm;
X case O_FTREXEC:
X argtype = 0;
X anum = S_IEXEC;
X goto check_perm;
X case O_FTEREAD:
X argtype = 1;
X anum = S_IREAD;
X goto check_perm;
X case O_FTEWRITE:
X argtype = 1;
X anum = S_IWRITE;
X goto check_perm;
X case O_FTEEXEC:
X argtype = 1;
X anum = S_IEXEC;
X check_perm:
X str = &str_no;
X if (mystat(arg,sarg[1]) < 0)
X break;
X if (cando(anum,argtype))
X str = &str_yes;
X break;
X
X case O_FTIS:
X if (mystat(arg,sarg[1]) >= 0)
X str = &str_yes;
X else
X str = &str_no;
X break;
X case O_FTEOWNED:
X case O_FTROWNED:
X if (mystat(arg,sarg[1]) >= 0 &&
X statbuf.st_uid == (optype == O_FTEOWNED ? euid : uid) )
X str = &str_yes;
X else
X str = &str_no;
X break;
X case O_FTZERO:
X if (mystat(arg,sarg[1]) >= 0 && !statbuf.st_size)
X str = &str_yes;
X else
X str = &str_no;
X break;
X case O_FTSIZE:
X if (mystat(arg,sarg[1]) >= 0 && statbuf.st_size)
X str = &str_yes;
X else
X str = &str_no;
X break;
X
X case O_FTSOCK:
X#ifdef S_IFSOCK
X anum = S_IFSOCK;
X goto check_file_type;
X#else
X str = &str_no;
X break;
X#endif
X case O_FTCHR:
X anum = S_IFCHR;
X goto check_file_type;
X case O_FTBLK:
X anum = S_IFBLK;
X goto check_file_type;
X case O_FTFILE:
X anum = S_IFREG;
X goto check_file_type;
X case O_FTDIR:
X anum = S_IFDIR;
X check_file_type:
X if (mystat(arg,sarg[1]) >= 0 &&
X (statbuf.st_mode & S_IFMT) == anum )
X str = &str_yes;
X else
X str = &str_no;
X break;
X case O_FTPIPE:
X#ifdef S_IFIFO
X anum = S_IFIFO;
X goto check_file_type;
X#else
X str = &str_no;
X break;
X#endif
X case O_FTLINK:
X#ifdef S_IFLNK
X if (lstat(str_get(sarg[1]),&statbuf) >= 0 &&
X (statbuf.st_mode & S_IFMT) == S_IFLNK )
X str = &str_yes;
X else
X#endif
X str = &str_no;
X break;
X case O_SYMLINK:
X#ifdef SYMLINK
X tmps = str_get(sarg[1]);
X value = (double)(symlink(tmps,str_get(sarg[2])) >= 0);
X goto donumset;
X#else
X fatal("Unsupported function symlink()");
X#endif
X case O_FTSUID:
X anum = S_ISUID;
X goto check_xid;
X case O_FTSGID:
X anum = S_ISGID;
X goto check_xid;
X case O_FTSVTX:
X anum = S_ISVTX;
X check_xid:
X if (mystat(arg,sarg[1]) >= 0 && statbuf.st_mode & anum)
X str = &str_yes;
X else
X str = &str_no;
X break;
X case O_FTTTY:
X if (arg[1].arg_flags & AF_SPECIAL) {
X stab = arg[1].arg_ptr.arg_stab;
X tmps = "";
X }
X else
X stab = stabent(tmps = str_get(sarg[1]),FALSE);
X if (stab && stab->stab_io && stab->stab_io->fp)
X anum = fileno(stab->stab_io->fp);
X else if (isdigit(*tmps))
X anum = atoi(tmps);
X else
X anum = -1;
X if (isatty(anum))
X str = &str_yes;
X else
X str = &str_no;
X break;
X case O_FTTEXT:
X case O_FTBINARY:
X str = do_fttext(arg,sarg[1]);
X break;
X }
X if (retary) {
X sarg[1] = str;
X maxsarg = sargoff + 1;
X }
X#ifdef DEBUGGING
X if (debug) {
X dlevel--;
X if (debug & 8)
X deb("%s RETURNS \"%s\"\n",opname[optype],str_get(str));
X }
X#endif
X goto freeargs;
X
Xarray_return:
X#ifdef DEBUGGING
X if (debug) {
X dlevel--;
X if (debug & 8)
X deb("%s RETURNS ARRAY OF %d ARGS\n",opname[optype],maxsarg-sargoff);
X }
X#endif
X goto freeargs;
X
Xdonumset:
X str_numset(str,value);
X STABSET(str);
X if (retary) {
X sarg[1] = str;
X maxsarg = sargoff + 1;
X }
X#ifdef DEBUGGING
X if (debug) {
X dlevel--;
X if (debug & 8)
X deb("%s RETURNS \"%f\"\n",opname[optype],value);
X }
X#endif
X
Xfreeargs:
X sarg -= sargoff;
X if (sarg != quicksarg) {
X if (retary) {
X sarg[0] = &str_args;
X str_numset(sarg[0], (double)(maxsarg));
X sarg[maxsarg+1] = Nullstr;
X *retary = sarg; /* up to them to free it */
X }
X else
X safefree((char*)sarg);
X }
X return str;
X}
X
Xint
Xingroup(gid,effective)
Xint gid;
Xint effective;
X{
X if (gid == (effective ? getegid() : getgid()))
X return TRUE;
X#ifdef GETGROUPS
X#ifndef NGROUPS
X#define NGROUPS 32
X#endif
X {
X GIDTYPE gary[NGROUPS];
X int anum;
X
X anum = getgroups(NGROUPS,gary);
X while (--anum >= 0)
X if (gary[anum] == gid)
X return TRUE;
X }
X#endif
X return FALSE;
X}
X
X/* Do the permissions allow some operation? Assumes statbuf already set. */
X
Xint
Xcando(bit, effective)
Xint bit;
Xint effective;
X{
X if ((effective ? euid : uid) == 0) { /* root is special */
X if (bit == S_IEXEC) {
X if (statbuf.st_mode & 0111 ||
X (statbuf.st_mode & S_IFMT) == S_IFDIR )
X return TRUE;
X }
X else
X return TRUE; /* root reads and writes anything */
X return FALSE;
X }
X if (statbuf.st_uid == (effective ? euid : uid) ) {
X if (statbuf.st_mode & bit)
X return TRUE; /* ok as "user" */
X }
X else if (ingroup((int)statbuf.st_gid,effective)) {
X if (statbuf.st_mode & bit >> 3)
X return TRUE; /* ok as "group" */
X }
X else if (statbuf.st_mode & bit >> 6)
X return TRUE; /* ok as "other" */
X return FALSE;
X}
!STUFFY!FUNK!
echo Extracting util.c
sed >util.c <<'!STUFFY!FUNK!' -e 's/X//'
X/* $Header: util.c,v 2.0 88/06/05 00:15:11 root Exp $
X *
X * $Log: util.c,v $
X * Revision 2.0 88/06/05 00:15:11 root
X * Baseline version 2.0.
X *
X */
X
X#include "EXTERN.h"
X#include "perl.h"
X
X#define FLUSH
X
Xstatic char nomem[] = "Out of memory!\n";
X
X/* paranoid version of malloc */
X
X#ifdef DEBUGGING
Xstatic int an = 0;
X#endif
X
Xchar *
Xsafemalloc(size)
XMEM_SIZE size;
X{
X char *ptr;
X char *malloc();
X
X ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
X#ifdef DEBUGGING
X if (debug & 128)
X fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
X#endif
X if (ptr != Nullch)
X return ptr;
X else {
X fputs(nomem,stdout) FLUSH;
X exit(1);
X }
X /*NOTREACHED*/
X}
X
X/* paranoid version of realloc */
X
Xchar *
Xsaferealloc(where,size)
Xchar *where;
XMEM_SIZE size;
X{
X char *ptr;
X char *realloc();
X
X if (!where)
X fatal("Null realloc");
X ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
X#ifdef DEBUGGING
X if (debug & 128) {
X fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
X fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
X }
X#endif
X if (ptr != Nullch)
X return ptr;
X else {
X fputs(nomem,stdout) FLUSH;
X exit(1);
X }
X /*NOTREACHED*/
X}
X
X/* safe version of free */
X
Xsafefree(where)
Xchar *where;
X{
X#ifdef DEBUGGING
X if (debug & 128)
X fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
X#endif
X if (where) {
X free(where);
X }
X}
X
X#ifdef NOTDEF
X/* safe version of string copy */
X
Xchar *
Xsafecpy(to,from,len)
Xchar *to;
Xregister char *from;
Xregister int len;
X{
X register char *dest = to;
X
X if (from != Nullch)
X for (len--; len && (*dest++ = *from++); len--) ;
X *dest = '\0';
X return to;
X}
X#endif /*NOTDEF*/
X
X#ifdef undef
X/* safe version of string concatenate, with \n deletion and space padding */
X
Xchar *
Xsafecat(to,from,len)
Xchar *to;
Xregister char *from;
Xregister int len;
X{
X register char *dest = to;
X
X len--; /* leave room for null */
X if (*dest) {
X while (len && *dest++) len--;
X if (len) {
X len--;
X *(dest-1) = ' ';
X }
X }
X if (from != Nullch)
X while (len && (*dest++ = *from++)) len--;
X if (len)
X dest--;
X if (*(dest-1) == '\n')
X dest--;
X *dest = '\0';
X return to;
X}
X#endif
X
X/* copy a string up to some (non-backslashed) delimiter, if any */
X
Xchar *
Xcpytill(to,from,delim)
Xregister char *to, *from;
Xregister int delim;
X{
X for (; *from; from++,to++) {
X if (*from == '\\') {
X if (from[1] == delim)
X from++;
X else if (from[1] == '\\')
X *to++ = *from++;
X }
X else if (*from == delim)
X break;
X *to = *from;
X }
X *to = '\0';
X return from;
X}
X
X/* return ptr to little string in big string, NULL if not found */
X/* This routine was donated by Corey Satten. */
X
Xchar *
Xinstr(big, little)
Xregister char *big;
Xregister char *little;
X{
X register char *s, *x;
X register int first = *little++;
X
X if (!first)
X return big;
X while (*big) {
X if (*big++ != first)
X continue;
X for (x=big,s=little; *s; /**/ ) {
X if (!*x)
X return Nullch;
X if (*s++ != *x++) {
X s--;
X break;
X }
X }
X if (!*s)
X return big-1;
X }
X return Nullch;
X}
X
X#ifdef NOTDEF
Xvoid
Xbmcompile(str)
XSTR *str;
X{
X register char *s;
X register char *table;
X register int i;
X register int len = str->str_cur;
X
X str_grow(str,len+128);
X s = str->str_ptr;
X table = s + len;
X for (i = 1; i < 128; i++) {
X table[i] = len;
X }
X i = 0;
X while (*s) {
X if (!isascii(*s))
X return;
X if (table[*s] == len)
X table[*s] = i;
X s++,i++;
X }
X str->str_pok |= 2; /* deep magic */
X}
X#endif /* NOTDEF */
X
Xstatic unsigned char freq[] = {
X 1, 2, 84, 151, 154, 155, 156, 157,
X 165, 246, 250, 3, 158, 7, 18, 29,
X 40, 51, 62, 73, 85, 96, 107, 118,
X 129, 140, 147, 148, 149, 150, 152, 153,
X 255, 182, 224, 205, 174, 176, 180, 217,
X 233, 232, 236, 187, 235, 228, 234, 226,
X 222, 219, 211, 195, 188, 193, 185, 184,
X 191, 183, 201, 229, 181, 220, 194, 162,
X 163, 208, 186, 202, 200, 218, 198, 179,
X 178, 214, 166, 170, 207, 199, 209, 206,
X 204, 160, 212, 216, 215, 192, 175, 173,
X 243, 172, 161, 190, 203, 189, 164, 230,
X 167, 248, 227, 244, 242, 255, 241, 231,
X 240, 253, 169, 210, 245, 237, 249, 247,
X 239, 168, 252, 251, 254, 238, 223, 221,
X 213, 225, 177, 197, 171, 196, 159, 4,
X 5, 6, 8, 9, 10, 11, 12, 13,
X 14, 15, 16, 17, 19, 20, 21, 22,
X 23, 24, 25, 26, 27, 28, 30, 31,
X 32, 33, 34, 35, 36, 37, 38, 39,
X 41, 42, 43, 44, 45, 46, 47, 48,
X 49, 50, 52, 53, 54, 55, 56, 57,
X 58, 59, 60, 61, 63, 64, 65, 66,
X 67, 68, 69, 70, 71, 72, 74, 75,
X 76, 77, 78, 79, 80, 81, 82, 83,
X 86, 87, 88, 89, 90, 91, 92, 93,
X 94, 95, 97, 98, 99, 100, 101, 102,
X 103, 104, 105, 106, 108, 109, 110, 111,
X 112, 113, 114, 115, 116, 117, 119, 120,
X 121, 122, 123, 124, 125, 126, 127, 128,
X 130, 131, 132, 133, 134, 135, 136, 137,
X 138, 139, 141, 142, 143, 144, 145, 146
X};
X
Xvoid
Xfbmcompile(str)
XSTR *str;
X{
X register char *s;
X register char *table;
X register int i;
X register int len = str->str_cur;
X int rarest = 0;
X int frequency = 256;
X
X str_grow(str,len+128);
X table = str->str_ptr + len; /* actually points at final '\0' */
X s = table - 1;
X for (i = 1; i < 128; i++) {
X table[i] = len;
X }
X i = 0;
X while (s >= str->str_ptr) {
X if (!isascii(*s))
X return;
X if (table[*s] == len)
X table[*s] = i;
X s--,i++;
X }
X str->str_pok |= 2; /* deep magic */
X
X s = str->str_ptr; /* deeper magic */
X for (i = 0; i < len; i++) {
X if (freq[s[i]] < frequency) {
X rarest = i;
X frequency = freq[s[i]];
X }
X }
X str->str_rare = s[rarest];
X str->str_prev = rarest;
X#ifdef DEBUGGING
X if (debug & 512)
X fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_prev);
X#endif
X}
X
X#ifdef NOTDEF
Xchar *
Xbminstr(big, biglen, littlestr)
Xregister char *big;
Xint biglen;
XSTR *littlestr;
X{
X register char *s;
X register int tmp;
X register char *little = littlestr->str_ptr;
X int littlelen = littlestr->str_cur;
X register char *table = little + littlelen;
X
X s = big + biglen - littlelen;
X while (s >= big) {
X if (tmp = table[*s]) {
X s -= tmp;
X }
X else {
X if (strnEQ(s,little,littlelen))
X return s;
X s--;
X }
X }
X return Nullch;
X}
X#endif /* NOTDEF */
X
Xchar *
Xfbminstr(big, bigend, littlestr)
Xchar *big;
Xregister char *bigend;
XSTR *littlestr;
X{
X register char *s;
X register int tmp;
X register int littlelen;
X register char *little;
X register char *table;
X register char *olds;
X register char *oldlittle;
X register int min;
X char *screaminstr();
X
X if (littlestr->str_pok != 3)
X return instr(big,littlestr->str_ptr);
X
X littlelen = littlestr->str_cur;
X table = littlestr->str_ptr + littlelen;
X s = big + --littlelen;
X oldlittle = little = table - 1;
X while (s < bigend) {
X top:
X if (tmp = table[*s]) {
X s += tmp;
X }
X else {
X tmp = littlelen; /* less expensive than calling strncmp() */
X olds = s;
X while (tmp--) {
X if (*--s == *--little)
X continue;
X s = olds + 1; /* here we pay the price for failure */
X little = oldlittle;
X if (s < bigend) /* fake up continue to outer loop */
X goto top;
X return Nullch;
X }
X return s;
X }
X }
X return Nullch;
X}
X
Xchar *
Xscreaminstr(bigstr, littlestr)
XSTR *bigstr;
XSTR *littlestr;
X{
X register char *s, *x;
X register char *big = bigstr->str_ptr;
X register int pos;
X register int previous;
X register int first;
X register char *little;
X
X if ((pos = screamfirst[littlestr->str_rare]) < 0)
X return Nullch;
X little = littlestr->str_ptr;
X first = *little++;
X previous = littlestr->str_prev;
X big -= previous;
X while (pos < previous) {
X if (!(pos += screamnext[pos]))
X return Nullch;
X }
X do {
X if (big[pos] != first)
X continue;
X for (x=big+pos+1,s=little; *s; /**/ ) {
X if (!*x)
X return Nullch;
X if (*s++ != *x++) {
X s--;
X break;
X }
X }
X if (!*s)
X return big+pos;
X } while (pos += screamnext[pos]);
X return Nullch;
X}
X
X/* copy a string to a safe spot */
X
Xchar *
Xsavestr(str)
Xchar *str;
X{
X register char *newaddr = safemalloc((MEM_SIZE)(strlen(str)+1));
X
X (void)strcpy(newaddr,str);
X return newaddr;
X}
X
X/* grow a static string to at least a certain length */
X
Xvoid
Xgrowstr(strptr,curlen,newlen)
Xchar **strptr;
Xint *curlen;
Xint newlen;
X{
X if (newlen > *curlen) { /* need more room? */
X if (*curlen)
X *strptr = saferealloc(*strptr,(MEM_SIZE)newlen);
X else
X *strptr = safemalloc((MEM_SIZE)newlen);
X *curlen = newlen;
X }
X}
X
Xextern int errno;
X
X/*VARARGS1*/
Xmess(pat,a1,a2,a3,a4)
Xchar *pat;
X{
X char *s;
X
X s = tokenbuf;
X sprintf(s,pat,a1,a2,a3,a4);
X s += strlen(s);
X if (s[-1] != '\n') {
X if (line) {
X sprintf(s," at %s line %ld",
X in_eval?filename:origfilename, (long)line);
X s += strlen(s);
X }
X if (last_in_stab &&
X last_in_stab->stab_io &&
X last_in_stab->stab_io->lines ) {
X sprintf(s,", <%s> line %ld",
X last_in_stab == argvstab ? "" : last_in_stab->stab_name,
X (long)last_in_stab->stab_io->lines);
X s += strlen(s);
X }
X strcpy(s,".\n");
X }
X}
X
X/*VARARGS1*/
Xfatal(pat,a1,a2,a3,a4)
Xchar *pat;
X{
X extern FILE *e_fp;
X extern char *e_tmpname;
X
X mess(pat,a1,a2,a3,a4);
X if (in_eval) {
X str_set(stabent("@",TRUE)->stab_val,tokenbuf);
X longjmp(eval_env,1);
X }
X fputs(tokenbuf,stderr);
X fflush(stderr);
X if (e_fp)
X UNLINK(e_tmpname);
X statusvalue >>= 8;
X exit(errno?errno:(statusvalue?statusvalue:255));
X}
X
X/*VARARGS1*/
Xwarn(pat,a1,a2,a3,a4)
Xchar *pat;
X{
X mess(pat,a1,a2,a3,a4);
X fputs(tokenbuf,stderr);
X fflush(stderr);
X}
X
Xstatic bool firstsetenv = TRUE;
Xextern char **environ;
X
Xvoid
Xsetenv(nam,val)
Xchar *nam, *val;
X{
X register int i=envix(nam); /* where does it go? */
X
X if (!environ[i]) { /* does not exist yet */
X if (firstsetenv) { /* need we copy environment? */
X int j;
X#ifndef lint
X char **tmpenv = (char**) /* point our wand at memory */
X safemalloc((i+2) * sizeof(char*));
X#else
X char **tmpenv = Null(char **);
X#endif /* lint */
X
X firstsetenv = FALSE;
X for (j=0; j<i; j++) /* copy environment */
X tmpenv[j] = environ[j];
X environ = tmpenv; /* tell exec where it is now */
X }
X#ifndef lint
X else
X environ = (char**) saferealloc((char*) environ,
X (i+2) * sizeof(char*));
X /* just expand it a bit */
X#endif /* lint */
X environ[i+1] = Nullch; /* make sure it's null terminated */
X }
X environ[i] = safemalloc((MEM_SIZE)(strlen(nam) + strlen(val) + 2));
X /* this may or may not be in */
X /* the old environ structure */
X sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
X}
X
Xint
Xenvix(nam)
Xchar *nam;
X{
X register int i, len = strlen(nam);
X
X for (i = 0; environ[i]; i++) {
X if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
X break; /* strnEQ must come first to avoid */
X } /* potential SEGV's */
X return i;
X}
X
X#ifdef EUNICE
Xunlnk(f) /* unlink all versions of a file */
Xchar *f;
X{
X int i;
X
X for (i = 0; unlink(f) >= 0; i++) ;
X return i ? 0 : -1;
X}
X#endif
X
X#ifndef BCOPY
X#ifndef MEMCPY
Xchar *
Xbcopy(from,to,len)
Xregister char *from;
Xregister char *to;
Xregister int len;
X{
X char *retval = to;
X
X while (len--)
X *to++ = *from++;
X return retval;
X}
X
Xchar *
Xbzero(loc,len)
Xregister char *loc;
Xregister int len;
X{
X char *retval = loc;
X
X while (len--)
X *loc++ = 0;
X return retval;
X}
X#endif
X#endif
!STUFFY!FUNK!
echo Extracting eg/scan/scan_suid
sed >eg/scan/scan_suid <<'!STUFFY!FUNK!' -e 's/X//'
X#!/usr/bin/perl -P
X
X# $Header: scan_suid,v 2.0 88/06/05 00:17:54 root Exp $
X
X# Look for new setuid root files.
X
Xchdir '/usr/adm/private/memories' || die "Can't cd.";
X
X($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
X $blksize,$blocks) = stat('oldsuid');
Xif ($nlink) {
X $lasttime = $mtime;
X $tmp = $ctime - $atime;
X if ($tmp <= 0 || $tmp >= 10) {
X print "WARNING: somebody has read oldsuid!\n";
X }
X $tmp = $ctime - $mtime;
X if ($tmp <= 0 || $tmp >= 10) {
X print "WARNING: somebody has modified oldsuid!!!\n";
X }
X} else {
X $lasttime = time - 60 * 60 * 24; # one day ago
X}
X$thistime = time;
X
X#if defined(mc300) || defined(mc500) || defined(mc700)
Xopen(Find, 'find / -perm -04000 -print |') ||
X die "scan_find: can't run find";
X#else
Xopen(Find, 'find / \( -fstype nfs -prune \) -o -perm -04000 -ls |') ||
X die "scan_find: can't run find";
X#endif
X
Xopen(suid, '>newsuid.tmp');
X
Xwhile (<Find>) {
X
X#if defined(mc300) || defined(mc500) || defined(mc700)
X $x = `/bin/ls -il $_`;
X $_ = $x;
X s/^ *//;
X ($inode,$perm,$links,$owner,$group,$size,$month,$day,$time,$name)
X = split;
X#else
X s/^ *//;
X ($inode,$blocks,$perm,$links,$owner,$group,$size,$month,$day,$time,$name)
X = split;
X#endif
X
X if ($perm =~ /[sS]/ && $owner eq 'root') {
X ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
X $blksize,$blocks) = stat($name);
X $foo = sprintf("%10s%3s %-8s %-8s%9s %3s %2s %s %s\n",
X $perm,$links,$owner,$group,$size,$month,$day,$name,$inode);
X print suid $foo;
X if ($ctime > $lasttime) {
X if ($ctime > $thistime) {
X print "Future file: $foo";
X }
X else {
X $ct .= $foo;
X }
X }
X }
X}
Xclose(suid);
X
Xprint `sort +7 -8 newsuid.tmp >newsuid 2>&1`;
X$foo = `/bin/diff oldsuid newsuid 2>&1`;
Xprint "Differences in suid info:\n",$foo if $foo;
Xprint `mv oldsuid oldoldsuid 2>&1; mv newsuid oldsuid 2>&1`;
Xprint `touch oldsuid 2>&1;sleep 2 2>&1;chmod o+w oldsuid 2>&1`;
Xprint `rm -f newsuid.tmp 2>&1`;
X
X at ct = split(/\n/,$ct);
X$ct = '';
X$* = 1;
Xwhile ($#ct >= 0) {
X $tmp = shift(@ct);
X unless ($foo =~ "^>.*$tmp\n") { $ct .= "$tmp\n"; }
X}
X
Xprint "Inode changed since last time:\n",$ct if $ct;
X
!STUFFY!FUNK!
echo ""
echo "End of kit 8 (of 15)"
cat /dev/null >kit8isdone
run=''
config=''
for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
if test -f kit${iskit}isdone; then
run="$run $iskit"
else
todo="$todo $iskit"
fi
done
case $todo in
'')
echo "You have run all your kits. Please read README and then type Configure."
chmod 755 Configure
;;
*) echo "You have run$run."
echo "You still need to run$todo."
;;
esac
: Someone might mail this, so...
exit
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Comp.sources.unix
mailing list