From pa.dec.com!decwrl!olivea!uunet!sparky!kent Mon Apr 15 18:30:38 PDT 1991 Article: 2188 of comp.sources.misc Path: pa.dec.com!decwrl!olivea!uunet!sparky!kent From: lwall@netlabs.com (Larry Wall) Newsgroups: comp.sources.misc Subject: v18i021: perl - The perl programming language, Part03/36 Message-ID: <1991Apr15.015255.6606@sparky.IMD.Sterling.COM> Date: 15 Apr 91 01:52:55 GMT Sender: kent@sparky.IMD.Sterling.COM (Kent Landfield) Organization: NetLabs, Inc. Lines: 2355 Approved: kent@sparky.imd.sterling.com X-Checksum-Snefru: da963dae 59afafe5 01ae7e75 426ec3bc Submitted-by: Larry Wall Posting-number: Volume 18, Issue 21 Archive-name: perl/part03 [There are 36 kits for perl version 4.0.] #! /bin/sh # Make a new directory for the perl sources, cd to it, and run kits 1 # thru 36 through sh. When all 36 kits have been run, read README. echo "This is perl 4.0 kit 3 (of 36). If kit 3 is complete, the line" echo '"'"End of kit 3 (of 36)"'" will echo at the end.' echo "" export PATH || (echo "You didn't use sh, you clunch." ; kill $$) mkdir 2>/dev/null echo Extracting doio.c:AA sed >doio.c:AA <<'!STUFFY!FUNK!' -e 's/X//' X/* $RCSfile: doio.c,v $$Revision: 4.0.1.1 $$Date: 91/04/11 17:41:06 $ X * X * Copyright (c) 1989, Larry Wall X * X * You may distribute under the terms of the GNU General Public License X * as specified in the README file that comes with the perl 3.0 kit. X * X * $Log: doio.c,v $ X * Revision 4.0.1.1 91/04/11 17:41:06 lwall X * patch1: hopefully straightened out some of the Xenix mess X * X * Revision 4.0 91/03/20 01:07:06 lwall X * 4.0 baseline. X * X */ X X#include "EXTERN.h" X#include "perl.h" X X#ifdef HAS_SOCKET X#include X#include X#endif X X#ifdef HAS_SELECT X#ifdef I_SYS_SELECT X#ifndef I_SYS_TIME X#include X#endif X#endif X#endif X X#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM) X#include X#ifdef HAS_MSG X#include X#endif X#ifdef HAS_SEM X#include X#endif X#ifdef HAS_SHM X#include X#endif X#endif X X#ifdef I_PWD X#include X#endif X#ifdef I_GRP X#include X#endif X#ifdef I_UTIME X#include X#endif X#ifdef I_FCNTL X#include X#endif X#ifdef I_SYS_FILE X#include X#endif X Xint laststatval = -1; Xint laststype = O_STAT; X Xbool Xdo_open(stab,name,len) XSTAB *stab; Xregister char *name; Xint len; X{ X FILE *fp; X register STIO *stio = stab_io(stab); X char *myname = savestr(name); X int result; X int fd; X int writing = 0; X char mode[3]; /* stdio file mode ("r\0" or "r+\0") */ X X name = myname; X forkprocess = 1; /* assume true if no fork */ X while (len && isspace(name[len-1])) X name[--len] = '\0'; X if (!stio) X stio = stab_io(stab) = stio_new(); X else if (stio->ifp) { X fd = fileno(stio->ifp); X if (stio->type == '|') X result = mypclose(stio->ifp); X else if (stio->type == '-') X result = 0; X else if (stio->ifp != stio->ofp) { X if (stio->ofp) { X result = fclose(stio->ofp); X fclose(stio->ifp); /* clear stdio, fd already closed */ X } X else X result = fclose(stio->ifp); X } X else X result = fclose(stio->ifp); X if (result == EOF && fd > 2) X fprintf(stderr,"Warning: unable to close filehandle %s properly.\n", X stab_name(stab)); X stio->ofp = stio->ifp = Nullfp; X } X if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */ X mode[1] = *name++; X mode[2] = '\0'; X --len; X writing = 1; X } X else { X mode[1] = '\0'; X } X stio->type = *name; X if (*name == '|') { X for (name++; isspace(*name); name++) ; X#ifdef TAINT X taintenv(); X taintproper("Insecure dependency in piped open"); X#endif X fp = mypopen(name,"w"); X writing = 1; X } X else if (*name == '>') { X#ifdef TAINT X taintproper("Insecure dependency in open"); X#endif X name++; X if (*name == '>') { X mode[0] = stio->type = 'a'; X name++; X } X else X mode[0] = 'w'; X writing = 1; X if (*name == '&') { X duplicity: X name++; X while (isspace(*name)) X name++; X if (isdigit(*name)) X fd = atoi(name); X else { X stab = stabent(name,FALSE); X if (!stab || !stab_io(stab)) X return FALSE; X if (stab_io(stab) && stab_io(stab)->ifp) { X fd = fileno(stab_io(stab)->ifp); X if (stab_io(stab)->type == 's') X stio->type = 's'; X } X else X fd = -1; X } X if (!(fp = fdopen(fd = dup(fd),mode))) { X close(fd); X } X } X else { X while (isspace(*name)) X name++; X if (strEQ(name,"-")) { X fp = stdout; X stio->type = '-'; X } X else { X fp = fopen(name,mode); X } X } X } X else { X if (*name == '<') { X mode[0] = 'r'; X name++; X while (isspace(*name)) X name++; X if (*name == '&') X goto duplicity; X if (strEQ(name,"-")) { X fp = stdin; X stio->type = '-'; X } X else X fp = fopen(name,mode); X } X else if (name[len-1] == '|') { X#ifdef TAINT X taintenv(); X taintproper("Insecure dependency in piped open"); X#endif X name[--len] = '\0'; X while (len && isspace(name[len-1])) X name[--len] = '\0'; X for (; isspace(*name); name++) ; X fp = mypopen(name,"r"); X stio->type = '|'; X } X else { X stio->type = '<'; X for (; isspace(*name); name++) ; X if (strEQ(name,"-")) { X fp = stdin; X stio->type = '-'; X } X else X fp = fopen(name,"r"); X } X } X Safefree(myname); X if (!fp) X return FALSE; X if (stio->type && X stio->type != '|' && stio->type != '-') { X if (fstat(fileno(fp),&statbuf) < 0) { X (void)fclose(fp); X return FALSE; X } X if (S_ISSOCK(statbuf.st_mode)) X stio->type = 's'; /* in case a socket was passed in to us */ X#ifdef S_IFMT X else if (!(statbuf.st_mode & S_IFMT)) X stio->type = 's'; /* some OS's return 0 on fstat()ed socket */ X#endif X } X#if defined(HAS_FCNTL) && defined(F_SETFD) X fd = fileno(fp); X fcntl(fd,F_SETFD,fd >= 3); X#endif X stio->ifp = fp; X if (writing) { X if (stio->type != 's') X stio->ofp = fp; X else X if (!(stio->ofp = fdopen(fileno(fp),"w"))) { X fclose(fp); X stio->ifp = Nullfp; X } X } X return TRUE; X} X XFILE * Xnextargv(stab) Xregister STAB *stab; X{ X register STR *str; X int filedev; X int fileino; X int fileuid; X int filegid; X static int filemode = 0; X static int lastfd; X static char *oldname; X X if (!argvoutstab) X argvoutstab = stabent("ARGVOUT",TRUE); X if (filemode & (S_ISUID|S_ISGID)) { X fflush(stab_io(argvoutstab)->ifp); /* chmod must follow last write */ X#ifdef HAS_FCHMOD X (void)fchmod(lastfd,filemode); X#else X (void)chmod(oldname,filemode); X#endif X } X filemode = 0; X while (alen(stab_xarray(stab)) >= 0) { X str = ashift(stab_xarray(stab)); X str_sset(stab_val(stab),str); X STABSET(stab_val(stab)); X oldname = str_get(stab_val(stab)); X if (do_open(stab,oldname,stab_val(stab)->str_cur)) { X if (inplace) { X#ifdef TAINT X taintproper("Insecure dependency in inplace open"); X#endif X if (strEQ(oldname,"-")) { X str_free(str); X defoutstab = stabent("STDOUT",TRUE); X return stab_io(stab)->ifp; X } X filedev = statbuf.st_dev; X fileino = statbuf.st_ino; X filemode = statbuf.st_mode; X fileuid = statbuf.st_uid; X filegid = statbuf.st_gid; X if (!S_ISREG(filemode)) { X warn("Can't do inplace edit: %s is not a regular file", X oldname ); X do_close(stab,FALSE); X str_free(str); X continue; X } X if (*inplace) { X#ifdef SUFFIX X add_suffix(str,inplace); X#else X str_cat(str,inplace); X#endif X#ifndef FLEXFILENAMES X if (stat(str->str_ptr,&statbuf) >= 0 X && statbuf.st_dev == filedev X && statbuf.st_ino == fileino ) { X warn("Can't do inplace edit: %s > 14 characters", X str->str_ptr ); X do_close(stab,FALSE); X str_free(str); X continue; X } X#endif X#ifdef HAS_RENAME X#ifndef MSDOS X if (rename(oldname,str->str_ptr) < 0) { X warn("Can't rename %s to %s: %s, skipping file", X oldname, str->str_ptr, strerror(errno) ); X do_close(stab,FALSE); X str_free(str); X continue; X } X#else X do_close(stab,FALSE); X (void)unlink(str->str_ptr); X (void)rename(oldname,str->str_ptr); X do_open(stab,str->str_ptr,stab_val(stab)->str_cur); X#endif /* MSDOS */ X#else X (void)UNLINK(str->str_ptr); X if (link(oldname,str->str_ptr) < 0) { X warn("Can't rename %s to %s: %s, skipping file", X oldname, str->str_ptr, strerror(errno) ); X do_close(stab,FALSE); X str_free(str); X continue; X } X (void)UNLINK(oldname); X#endif X } X else { X#ifndef MSDOS X if (UNLINK(oldname) < 0) { X warn("Can't rename %s to %s: %s, skipping file", X oldname, str->str_ptr, strerror(errno) ); X do_close(stab,FALSE); X str_free(str); X continue; X } X#else X fatal("Can't do inplace edit without backup"); X#endif X } X X str_nset(str,">",1); X str_cat(str,oldname); X errno = 0; /* in case sprintf set errno */ X if (!do_open(argvoutstab,str->str_ptr,str->str_cur)) { X warn("Can't do inplace edit on %s: %s", X oldname, strerror(errno) ); X do_close(stab,FALSE); X str_free(str); X continue; X } X defoutstab = argvoutstab; X lastfd = fileno(stab_io(argvoutstab)->ifp); X (void)fstat(lastfd,&statbuf); X#ifdef HAS_FCHMOD X (void)fchmod(lastfd,filemode); X#else X (void)chmod(oldname,filemode); X#endif X if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) { X#ifdef HAS_FCHOWN X (void)fchown(lastfd,fileuid,filegid); X#else X#ifdef HAS_CHOWN X (void)chown(oldname,fileuid,filegid); X#endif X#endif X } X } X str_free(str); X return stab_io(stab)->ifp; X } X else X fprintf(stderr,"Can't open %s: %s\n",str_get(str), strerror(errno)); X str_free(str); X } X if (inplace) { X (void)do_close(argvoutstab,FALSE); X defoutstab = stabent("STDOUT",TRUE); X } X return Nullfp; X} X X#ifdef HAS_PIPE Xvoid Xdo_pipe(str, rstab, wstab) XSTR *str; XSTAB *rstab; XSTAB *wstab; X{ X register STIO *rstio; X register STIO *wstio; X int fd[2]; X X if (!rstab) X goto badexit; X if (!wstab) X goto badexit; X X rstio = stab_io(rstab); X wstio = stab_io(wstab); X X if (!rstio) X rstio = stab_io(rstab) = stio_new(); X else if (rstio->ifp) X do_close(rstab,FALSE); X if (!wstio) X wstio = stab_io(wstab) = stio_new(); X else if (wstio->ifp) X do_close(wstab,FALSE); X X if (pipe(fd) < 0) X goto badexit; X rstio->ifp = fdopen(fd[0], "r"); X wstio->ofp = fdopen(fd[1], "w"); X wstio->ifp = wstio->ofp; X rstio->type = '<'; X wstio->type = '>'; X if (!rstio->ifp || !wstio->ofp) { X if (rstio->ifp) fclose(rstio->ifp); X else close(fd[0]); X if (wstio->ofp) fclose(wstio->ofp); X else close(fd[1]); X goto badexit; X } X X str_sset(str,&str_yes); X return; X Xbadexit: X str_sset(str,&str_undef); X return; X} X#endif X Xbool Xdo_close(stab,explicit) XSTAB *stab; Xbool explicit; X{ X bool retval = FALSE; X register STIO *stio; X int status; X X if (!stab) X stab = argvstab; X if (!stab) X return FALSE; X stio = stab_io(stab); X if (!stio) { /* never opened */ X if (dowarn && explicit) X warn("Close on unopened file <%s>",stab_name(stab)); X return FALSE; X } X if (stio->ifp) { X if (stio->type == '|') { X status = mypclose(stio->ifp); X retval = (status == 0); X statusvalue = (unsigned short)status & 0xffff; X } X else if (stio->type == '-') X retval = TRUE; X else { X if (stio->ofp && stio->ofp != stio->ifp) { /* a socket */ X retval = (fclose(stio->ofp) != EOF); X fclose(stio->ifp); /* clear stdio, fd already closed */ X } X else X retval = (fclose(stio->ifp) != EOF); X } X stio->ofp = stio->ifp = Nullfp; X } X if (explicit) X stio->lines = 0; X stio->type = ' '; X return retval; X} X Xbool Xdo_eof(stab) XSTAB *stab; X{ X register STIO *stio; X int ch; X X if (!stab) { /* eof() */ X if (argvstab) X stio = stab_io(argvstab); X else X return TRUE; X } X else X stio = stab_io(stab); X X if (!stio) X return TRUE; X X while (stio->ifp) { X X#ifdef STDSTDIO /* (the code works without this) */ X if (stio->ifp->_cnt > 0) /* cheat a little, since */ X return FALSE; /* this is the most usual case */ X#endif X X ch = getc(stio->ifp); X if (ch != EOF) { X (void)ungetc(ch, stio->ifp); X return FALSE; X } X#ifdef STDSTDIO X if (stio->ifp->_cnt < -1) X stio->ifp->_cnt = -1; X#endif X if (!stab) { /* not necessarily a real EOF yet? */ X if (!nextargv(argvstab)) /* get another fp handy */ X return TRUE; X } X else X return TRUE; /* normal fp, definitely end of file */ X } X return TRUE; X} X Xlong Xdo_tell(stab) XSTAB *stab; X{ X register STIO *stio; X X if (!stab) X goto phooey; X X stio = stab_io(stab); X if (!stio || !stio->ifp) X goto phooey; X X if (feof(stio->ifp)) X (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */ X X return ftell(stio->ifp); X Xphooey: X if (dowarn) X warn("tell() on unopened file"); X return -1L; X} X Xbool Xdo_seek(stab, pos, whence) XSTAB *stab; Xlong pos; Xint whence; X{ X register STIO *stio; X X if (!stab) X goto nuts; X X stio = stab_io(stab); X if (!stio || !stio->ifp) X goto nuts; X X if (feof(stio->ifp)) X (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */ X X return fseek(stio->ifp, pos, whence) >= 0; X Xnuts: X if (dowarn) X warn("seek() on unopened file"); X return FALSE; X} X Xint Xdo_ctl(optype,stab,func,argstr) Xint optype; XSTAB *stab; Xint func; XSTR *argstr; X{ X register STIO *stio; X register char *s; X int retval; X X if (!stab || !argstr) X return -1; X stio = stab_io(stab); X if (!stio) X return -1; X X if (argstr->str_pok || !argstr->str_nok) { X if (!argstr->str_pok) X s = str_get(argstr); X X#ifdef IOCPARM_MASK X#ifndef IOCPARM_LEN X#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK) X#endif X#endif X#ifdef IOCPARM_LEN X retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */ X#else X retval = 256; /* otherwise guess at what's safe */ X#endif X if (argstr->str_cur < retval) { X Str_Grow(argstr,retval+1); X argstr->str_cur = retval; X } X X s = argstr->str_ptr; X s[argstr->str_cur] = 17; /* a little sanity check here */ X } X else { X retval = (int)str_gnum(argstr); X#ifdef MSDOS X s = (char*)(long)retval; /* ouch */ X#else X s = (char*)retval; /* ouch */ X#endif X } X X#ifndef lint X if (optype == O_IOCTL) X retval = ioctl(fileno(stio->ifp), func, s); X else X#ifdef MSDOS X fatal("fcntl is not implemented"); X#else X#ifdef HAS_FCNTL X retval = fcntl(fileno(stio->ifp), func, s); X#else X fatal("fcntl is not implemented"); X#endif X#endif X#else /* lint */ X retval = 0; X#endif /* lint */ X X if (argstr->str_pok) { X if (s[argstr->str_cur] != 17) X fatal("Return value overflowed string"); X s[argstr->str_cur] = 0; /* put our null back */ X } X return retval; X} X Xint Xdo_stat(str,arg,gimme,arglast) XSTR *str; Xregister ARG *arg; Xint gimme; Xint *arglast; X{ X register ARRAY *ary = stack; X register int sp = arglast[0] + 1; X int max = 13; X X if ((arg[1].arg_type & A_MASK) == A_WORD) { X tmpstab = arg[1].arg_ptr.arg_stab; X if (tmpstab != defstab) { X laststype = O_STAT; X statstab = tmpstab; X str_set(statname,""); X if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp || X fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) { X max = 0; X laststatval = -1; X } X } X else if (laststatval < 0) X max = 0; X } X else { X str_set(statname,str_get(ary->ary_array[sp])); X statstab = Nullstab; X#ifdef HAS_LSTAT X laststype = arg->arg_type; X if (arg->arg_type == O_LSTAT) X laststatval = lstat(str_get(statname),&statcache); X else X#endif X laststatval = stat(str_get(statname),&statcache); X if (laststatval < 0) X max = 0; X } X X if (gimme != G_ARRAY) { X if (max) X str_sset(str,&str_yes); X else X str_sset(str,&str_undef); X STABSET(str); X ary->ary_array[sp] = str; X return sp; X } X sp--; X if (max) { X#ifndef lint X (void)astore(ary,++sp, X str_2mortal(str_nmake((double)statcache.st_dev))); X (void)astore(ary,++sp, X str_2mortal(str_nmake((double)statcache.st_ino))); X (void)astore(ary,++sp, X str_2mortal(str_nmake((double)statcache.st_mode))); X (void)astore(ary,++sp, X str_2mortal(str_nmake((double)statcache.st_nlink))); X (void)astore(ary,++sp, X str_2mortal(str_nmake((double)statcache.st_uid))); X (void)astore(ary,++sp, X str_2mortal(str_nmake((double)statcache.st_gid))); X (void)astore(ary,++sp, X str_2mortal(str_nmake((double)statcache.st_rdev))); X (void)astore(ary,++sp, X str_2mortal(str_nmake((double)statcache.st_size))); X (void)astore(ary,++sp, X str_2mortal(str_nmake((double)statcache.st_atime))); X (void)astore(ary,++sp, X str_2mortal(str_nmake((double)statcache.st_mtime))); X (void)astore(ary,++sp, X str_2mortal(str_nmake((double)statcache.st_ctime))); X#ifdef STATBLOCKS X (void)astore(ary,++sp, X str_2mortal(str_nmake((double)statcache.st_blksize))); X (void)astore(ary,++sp, X str_2mortal(str_nmake((double)statcache.st_blocks))); X#else X (void)astore(ary,++sp, X str_2mortal(str_make("",0))); X (void)astore(ary,++sp, X str_2mortal(str_make("",0))); X#endif X#else /* lint */ X (void)astore(ary,++sp,str_nmake(0.0)); X#endif /* lint */ X } X return sp; X} X X#if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP) X /* code courtesy of William Kucharski */ X#define HAS_CHSIZE X Xint chsize(fd, length) Xint fd; /* file descriptor */ Xoff_t length; /* length to set file to */ X{ X extern long lseek(); X struct flock fl; X struct stat filebuf; X X if (fstat(fd, &filebuf) < 0) X return -1; X X if (filebuf.st_size < length) { X X /* extend file length */ X X if ((lseek(fd, (length - 1), 0)) < 0) X return -1; X X /* write a "0" byte */ X X if ((write(fd, "", 1)) != 1) X return -1; X } X else { X /* truncate length */ X X fl.l_whence = 0; X fl.l_len = 0; X fl.l_start = length; X fl.l_type = F_WRLCK; /* write lock on file space */ X X /* X * This relies on the UNDOCUMENTED F_FREESP argument to X * fcntl(2), which truncates the file so that it ends at the X * position indicated by fl.l_start. X * X * Will minor miracles never cease? X */ X X if (fcntl(fd, F_FREESP, &fl) < 0) X return -1; X X } X X return 0; X} X#endif /* F_FREESP */ X Xint Xdo_truncate(str,arg,gimme,arglast) XSTR *str; Xregister ARG *arg; Xint gimme; Xint *arglast; X{ X register ARRAY *ary = stack; X register int sp = arglast[0] + 1; X off_t len = (off_t)str_gnum(ary->ary_array[sp+1]); X int result = 1; X STAB *tmpstab; X X#if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE) X#ifdef HAS_TRUNCATE X if ((arg[1].arg_type & A_MASK) == A_WORD) { X tmpstab = arg[1].arg_ptr.arg_stab; X if (!stab_io(tmpstab) || X ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0) X result = 0; X } X else if (truncate(str_get(ary->ary_array[sp]), len) < 0) X result = 0; X#else X if ((arg[1].arg_type & A_MASK) == A_WORD) { X tmpstab = arg[1].arg_ptr.arg_stab; X if (!stab_io(tmpstab) || X chsize(fileno(stab_io(tmpstab)->ifp), len) < 0) X result = 0; X } X else { X int tmpfd; X X if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0) X result = 0; X else { X if (chsize(tmpfd, len) < 0) X result = 0; X close(tmpfd); X } X } X#endif X X if (result) X str_sset(str,&str_yes); X else X str_sset(str,&str_undef); X STABSET(str); X ary->ary_array[sp] = str; X return sp; X#else X fatal("truncate not implemented"); X#endif X} X Xint Xlooks_like_number(str) XSTR *str; X{ X register char *s; X register char *send; X X if (!str->str_pok) X return TRUE; X s = str->str_ptr; X send = s + str->str_cur; X while (isspace(*s)) X s++; X if (s >= send) X return FALSE; X if (*s == '+' || *s == '-') X s++; X while (isdigit(*s)) X s++; X if (s == send) X return TRUE; X if (*s == '.') X s++; X else if (s == str->str_ptr) X return FALSE; X while (isdigit(*s)) X s++; X if (s == send) X return TRUE; X if (*s == 'e' || *s == 'E') { X s++; X if (*s == '+' || *s == '-') X s++; X while (isdigit(*s)) X s++; X } X while (isspace(*s)) X s++; X if (s >= send) X return TRUE; X return FALSE; X} X Xbool Xdo_print(str,fp) Xregister STR *str; XFILE *fp; X{ X register char *tmps; X X if (!fp) { X if (dowarn) X warn("print to unopened file"); X return FALSE; X } X if (!str) X return TRUE; X if (ofmt && X ((str->str_nok && str->str_u.str_nval != 0.0) X || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) { X fprintf(fp, ofmt, str->str_u.str_nval); X return !ferror(fp); X } X else { X tmps = str_get(str); X if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0' X && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) { X STR *tmpstr = str_mortal(&str_undef); X stab_fullname(tmpstr,((STAB*)str));/* a stab value, be nice */ X str = tmpstr; X tmps = str->str_ptr; X putc('*',fp); X } X if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp))) X return FALSE; X } X return TRUE; X} X Xbool Xdo_aprint(arg,fp,arglast) Xregister ARG *arg; Xregister FILE *fp; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[1]; X register int retval; X register int items = arglast[2] - sp; X X if (!fp) { X if (dowarn) X warn("print to unopened file"); X return FALSE; X } X st += ++sp; X if (arg->arg_type == O_PRTF) { X do_sprintf(arg->arg_ptr.arg_str,items,st); X retval = do_print(arg->arg_ptr.arg_str,fp); X } X else { X retval = (items <= 0); X for (; items > 0; items--,st++) { X if (retval && ofslen) { X if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) { X retval = FALSE; X break; X } X } X if (!(retval = do_print(*st, fp))) X break; X } X if (retval && orslen) X if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp)) X retval = FALSE; X } X return retval; X} X Xint Xmystat(arg,str) XARG *arg; XSTR *str; X{ X STIO *stio; X X laststype = O_STAT; X if (arg[1].arg_type & A_DONT) { X stio = stab_io(arg[1].arg_ptr.arg_stab); X if (stio && stio->ifp) { X statstab = arg[1].arg_ptr.arg_stab; X str_set(statname,""); X return (laststatval = fstat(fileno(stio->ifp), &statcache)); X } X else { X if (arg[1].arg_ptr.arg_stab == defstab) X return laststatval; X if (dowarn) X warn("Stat on unopened file <%s>", X stab_name(arg[1].arg_ptr.arg_stab)); X statstab = Nullstab; X str_set(statname,""); X return (laststatval = -1); X } X } X else { X statstab = Nullstab; X str_set(statname,str_get(str)); X return (laststatval = stat(str_get(str),&statcache)); X } X} X Xint Xmylstat(arg,str) XARG *arg; XSTR *str; X{ X if (arg[1].arg_type & A_DONT) { X if (arg[1].arg_ptr.arg_stab == defstab) { X if (laststype != O_LSTAT) X fatal("The stat preceding -l _ wasn't an lstat"); X return laststatval; X } X fatal("You can't use -l on a filehandle"); X } X X laststype = O_LSTAT; X statstab = Nullstab; X str_set(statname,str_get(str)); X#ifdef HAS_LSTAT X return (laststatval = lstat(str_get(str),&statcache)); X#else X return (laststatval = stat(str_get(str),&statcache)); X#endif X} X XSTR * Xdo_fttext(arg,str) Xregister ARG *arg; XSTR *str; X{ X int i; X int len; X int odd = 0; X STDCHAR tbuf[512]; X register STDCHAR *s; X register STIO *stio; X X if (arg[1].arg_type & A_DONT) { X if (arg[1].arg_ptr.arg_stab == defstab) { X if (statstab) X stio = stab_io(statstab); X else { X str = statname; X goto really_filename; X } X } X else { X statstab = arg[1].arg_ptr.arg_stab; X str_set(statname,""); X stio = stab_io(statstab); X } X if (stio && stio->ifp) { X#ifdef STDSTDIO X fstat(fileno(stio->ifp),&statcache); X if (stio->ifp->_cnt <= 0) { X i = getc(stio->ifp); X if (i != EOF) X (void)ungetc(i,stio->ifp); X } X if (stio->ifp->_cnt <= 0) /* null file is anything */ X return &str_yes; X len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base); X s = stio->ifp->_base; X#else X fatal("-T and -B not implemented on filehandles\n"); X#endif X } X else { X if (dowarn) X warn("Test on unopened file <%s>", X stab_name(arg[1].arg_ptr.arg_stab)); X return &str_undef; X } X } X else { X statstab = Nullstab; X str_set(statname,str_get(str)); X really_filename: X i = open(str_get(str),0); X if (i < 0) X return &str_undef; X fstat(i,&statcache); X len = read(i,tbuf,512); X (void)close(i); X if (len <= 0) /* null file is anything */ X return &str_yes; X s = tbuf; X } X X /* now scan s to look for textiness */ X X for (i = 0; i < len; i++,s++) { X if (!*s) { /* null never allowed in text */ X odd += len; X break; X } X else if (*s & 128) X odd++; X else if (*s < 32 && X *s != '\n' && *s != '\r' && *s != '\b' && X *s != '\t' && *s != '\f' && *s != 27) X odd++; X } X X if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */ X return &str_no; X else X return &str_yes; X} X Xbool Xdo_aexec(really,arglast) XSTR *really; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[1]; X register int items = arglast[2] - sp; X register char **a; X char **argv; X char *tmps; X X if (items) { X New(401,argv, items+1, char*); X a = argv; X for (st += ++sp; items > 0; items--,st++) { X if (*st) X *a++ = str_get(*st); X else X *a++ = ""; X } X *a = Nullch; X#ifdef TAINT X if (*argv[0] != '/') /* will execvp use PATH? */ X taintenv(); /* testing IFS here is overkill, probably */ X#endif X if (really && *(tmps = str_get(really))) X execvp(tmps,argv); X else X execvp(argv[0],argv); X Safefree(argv); X } X return FALSE; X} X Xstatic char **Argv = Null(char **); Xstatic char *Cmd = Nullch; X Xvoid Xdo_execfree() X{ X if (Argv) { X Safefree(Argv); X Argv = Null(char **); X } X if (Cmd) { X Safefree(Cmd); X Cmd = Nullch; X } X} X Xbool Xdo_exec(cmd) Xchar *cmd; X{ X register char **a; X register char *s; X char flags[10]; X X#ifdef TAINT X taintenv(); X taintproper("Insecure dependency in exec"); X#endif X X /* save an extra exec if possible */ X X#ifdef CSH X if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) { X strcpy(flags,"-c"); X s = cmd+cshlen+3; X if (*s == 'f') { X s++; X strcat(flags,"f"); X } X if (*s == ' ') X s++; X if (*s++ == '\'') { X char *ncmd = s; X X while (*s) X s++; X if (s[-1] == '\n') X *--s = '\0'; X if (s[-1] == '\'') { X *--s = '\0'; X execl(cshname,"csh", flags,ncmd,(char*)0); X *s = '\''; X return FALSE; X } X } X } X#endif /* CSH */ X X /* see if there are shell metacharacters in it */ X X for (s = cmd; *s && isalpha(*s); s++) ; /* catch VAR=val gizmo */ X if (*s == '=') X goto doshell; X for (s = cmd; *s; s++) { X if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) { X if (*s == '\n' && !s[1]) { X *s = '\0'; X break; X } X doshell: X execl("/bin/sh","sh","-c",cmd,(char*)0); X return FALSE; X } X } X New(402,Argv, (s - cmd) / 2 + 2, char*); X Cmd = nsavestr(cmd, s-cmd); X a = Argv; X for (s = Cmd; *s;) { X while (*s && isspace(*s)) s++; X if (*s) X *(a++) = s; X while (*s && !isspace(*s)) s++; X if (*s) X *s++ = '\0'; X } X *a = Nullch; X if (Argv[0]) { X execvp(Argv[0],Argv); X if (errno == ENOEXEC) { /* for system V NIH syndrome */ X do_execfree(); X goto doshell; X } X } X do_execfree(); X return FALSE; X} X X#ifdef HAS_SOCKET Xint Xdo_socket(stab, arglast) XSTAB *stab; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[1]; X register STIO *stio; X int domain, type, protocol, fd; X X if (!stab) X return FALSE; X X stio = stab_io(stab); X if (!stio) X stio = stab_io(stab) = stio_new(); X else if (stio->ifp) X do_close(stab,FALSE); X X domain = (int)str_gnum(st[++sp]); X type = (int)str_gnum(st[++sp]); X protocol = (int)str_gnum(st[++sp]); X#ifdef TAINT X taintproper("Insecure dependency in socket"); X#endif X fd = socket(domain,type,protocol); X if (fd < 0) X return FALSE; X stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */ X stio->ofp = fdopen(fd, "w"); X stio->type = 's'; X if (!stio->ifp || !stio->ofp) { X if (stio->ifp) fclose(stio->ifp); X if (stio->ofp) fclose(stio->ofp); X if (!stio->ifp && !stio->ofp) close(fd); X return FALSE; X } X X return TRUE; X} X Xint Xdo_bind(stab, arglast) XSTAB *stab; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[1]; X register STIO *stio; X char *addr; X X if (!stab) X goto nuts; X X stio = stab_io(stab); X if (!stio || !stio->ifp) X goto nuts; X X addr = str_get(st[++sp]); X#ifdef TAINT X taintproper("Insecure dependency in bind"); X#endif X return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0; X Xnuts: X if (dowarn) X warn("bind() on closed fd"); X return FALSE; X X} X Xint Xdo_connect(stab, arglast) XSTAB *stab; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[1]; X register STIO *stio; X char *addr; X X if (!stab) X goto nuts; X X stio = stab_io(stab); X if (!stio || !stio->ifp) X goto nuts; X X addr = str_get(st[++sp]); X#ifdef TAINT X taintproper("Insecure dependency in connect"); X#endif X return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0; X Xnuts: X if (dowarn) X warn("connect() on closed fd"); X return FALSE; X X} X Xint Xdo_listen(stab, arglast) XSTAB *stab; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[1]; X register STIO *stio; X int backlog; X X if (!stab) X goto nuts; X X stio = stab_io(stab); X if (!stio || !stio->ifp) X goto nuts; X X backlog = (int)str_gnum(st[++sp]); X return listen(fileno(stio->ifp), backlog) >= 0; X Xnuts: X if (dowarn) X warn("listen() on closed fd"); X return FALSE; X} X Xvoid Xdo_accept(str, nstab, gstab) XSTR *str; XSTAB *nstab; XSTAB *gstab; X{ X register STIO *nstio; X register STIO *gstio; X int len = sizeof buf; X int fd; X X if (!nstab) X goto badexit; X if (!gstab) X goto nuts; X X gstio = stab_io(gstab); X nstio = stab_io(nstab); X X if (!gstio || !gstio->ifp) X goto nuts; X if (!nstio) X nstio = stab_io(nstab) = stio_new(); X else if (nstio->ifp) X do_close(nstab,FALSE); X X fd = accept(fileno(gstio->ifp),buf,&len); X if (fd < 0) X goto badexit; X nstio->ifp = fdopen(fd, "r"); X nstio->ofp = fdopen(fd, "w"); X nstio->type = 's'; X if (!nstio->ifp || !nstio->ofp) { X if (nstio->ifp) fclose(nstio->ifp); X if (nstio->ofp) fclose(nstio->ofp); X if (!nstio->ifp && !nstio->ofp) close(fd); X goto badexit; X } X X str_nset(str, buf, len); X return; X Xnuts: X if (dowarn) X warn("accept() on closed fd"); Xbadexit: X str_sset(str,&str_undef); X return; X} X Xint Xdo_shutdown(stab, arglast) XSTAB *stab; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[1]; X register STIO *stio; X int how; X X if (!stab) X goto nuts; X X stio = stab_io(stab); X if (!stio || !stio->ifp) X goto nuts; X X how = (int)str_gnum(st[++sp]); X return shutdown(fileno(stio->ifp), how) >= 0; X Xnuts: X if (dowarn) X warn("shutdown() on closed fd"); X return FALSE; X X} X Xint Xdo_sopt(optype, stab, arglast) Xint optype; XSTAB *stab; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[1]; X register STIO *stio; X int fd; X int lvl; X int optname; X X if (!stab) X goto nuts; X X stio = stab_io(stab); X if (!stio || !stio->ifp) X goto nuts; X X fd = fileno(stio->ifp); X lvl = (int)str_gnum(st[sp+1]); X optname = (int)str_gnum(st[sp+2]); X switch (optype) { X case O_GSOCKOPT: X st[sp] = str_2mortal(str_new(257)); X st[sp]->str_cur = 256; X st[sp]->str_pok = 1; X if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0) X goto nuts; X break; X case O_SSOCKOPT: X st[sp] = st[sp+3]; X if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0) X goto nuts; X st[sp] = &str_yes; X break; X } X X return sp; X Xnuts: X if (dowarn) X warn("[gs]etsockopt() on closed fd"); X st[sp] = &str_undef; X return sp; X X} X Xint Xdo_getsockname(optype, stab, arglast) Xint optype; XSTAB *stab; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[1]; X register STIO *stio; X int fd; X X if (!stab) X goto nuts; X X stio = stab_io(stab); X if (!stio || !stio->ifp) X goto nuts; X X st[sp] = str_2mortal(str_new(257)); X st[sp]->str_cur = 256; X st[sp]->str_pok = 1; X fd = fileno(stio->ifp); X switch (optype) { X case O_GETSOCKNAME: X if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0) X goto nuts2; X break; X case O_GETPEERNAME: X if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0) X goto nuts2; X break; X } X X return sp; X Xnuts: X if (dowarn) X warn("get{sock,peer}name() on closed fd"); Xnuts2: X st[sp] = &str_undef; X return sp; X X} X Xint Xdo_ghent(which,gimme,arglast) Xint which; Xint gimme; Xint *arglast; X{ X register ARRAY *ary = stack; X register int sp = arglast[0]; X register char **elem; X register STR *str; X struct hostent *gethostbyname(); X struct hostent *gethostbyaddr(); X#ifdef HAS_GETHOSTENT X struct hostent *gethostent(); X#endif X struct hostent *hent; X unsigned long len; X X if (gimme != G_ARRAY) { X astore(ary, ++sp, str_mortal(&str_undef)); X return sp; X } X X if (which == O_GHBYNAME) { X char *name = str_get(ary->ary_array[sp+1]); X X hent = gethostbyname(name); X } X else if (which == O_GHBYADDR) { X STR *addrstr = ary->ary_array[sp+1]; X int addrtype = (int)str_gnum(ary->ary_array[sp+2]); X char *addr = str_get(addrstr); X X hent = gethostbyaddr(addr,addrstr->str_cur,addrtype); X } X else X#ifdef HAS_GETHOSTENT X hent = gethostent(); X#else X fatal("gethostent not implemented"); X#endif X if (hent) { X#ifndef lint X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_set(str, hent->h_name); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X for (elem = hent->h_aliases; *elem; elem++) { X str_cat(str, *elem); X if (elem[1]) X str_ncat(str," ",1); X } X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_numset(str, (double)hent->h_addrtype); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X len = hent->h_length; X str_numset(str, (double)len); X#ifdef h_addr X for (elem = hent->h_addr_list; *elem; elem++) { X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_nset(str, *elem, len); X } X#else X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_nset(str, hent->h_addr, len); X#endif /* h_addr */ X#else /* lint */ X elem = Nullch; X elem = elem; X (void)astore(ary, ++sp, str_mortal(&str_no)); X#endif /* lint */ X } X X return sp; X} X Xint Xdo_gnent(which,gimme,arglast) Xint which; Xint gimme; Xint *arglast; X{ X register ARRAY *ary = stack; X register int sp = arglast[0]; X register char **elem; X register STR *str; X struct netent *getnetbyname(); X struct netent *getnetbyaddr(); X struct netent *getnetent(); X struct netent *nent; X X if (gimme != G_ARRAY) { X astore(ary, ++sp, str_mortal(&str_undef)); X return sp; X } X X if (which == O_GNBYNAME) { X char *name = str_get(ary->ary_array[sp+1]); X X nent = getnetbyname(name); X } X else if (which == O_GNBYADDR) { X unsigned long addr = U_L(str_gnum(ary->ary_array[sp+1])); X int addrtype = (int)str_gnum(ary->ary_array[sp+2]); X X nent = getnetbyaddr((long)addr,addrtype); X } X else X nent = getnetent(); X X if (nent) { X#ifndef lint X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_set(str, nent->n_name); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X for (elem = nent->n_aliases; *elem; elem++) { X str_cat(str, *elem); X if (elem[1]) X str_ncat(str," ",1); X } X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_numset(str, (double)nent->n_addrtype); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_numset(str, (double)nent->n_net); X#else /* lint */ X elem = Nullch; X elem = elem; X (void)astore(ary, ++sp, str_mortal(&str_no)); X#endif /* lint */ X } X X return sp; X} X Xint Xdo_gpent(which,gimme,arglast) Xint which; Xint gimme; Xint *arglast; X{ X register ARRAY *ary = stack; X register int sp = arglast[0]; X register char **elem; X register STR *str; X struct protoent *getprotobyname(); X struct protoent *getprotobynumber(); X struct protoent *getprotoent(); X struct protoent *pent; X X if (gimme != G_ARRAY) { X astore(ary, ++sp, str_mortal(&str_undef)); X return sp; X } X X if (which == O_GPBYNAME) { X char *name = str_get(ary->ary_array[sp+1]); X X pent = getprotobyname(name); X } X else if (which == O_GPBYNUMBER) { X int proto = (int)str_gnum(ary->ary_array[sp+1]); X X pent = getprotobynumber(proto); X } X else X pent = getprotoent(); X X if (pent) { X#ifndef lint X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_set(str, pent->p_name); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X for (elem = pent->p_aliases; *elem; elem++) { X str_cat(str, *elem); X if (elem[1]) X str_ncat(str," ",1); X } X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_numset(str, (double)pent->p_proto); X#else /* lint */ X elem = Nullch; X elem = elem; X (void)astore(ary, ++sp, str_mortal(&str_no)); X#endif /* lint */ X } X X return sp; X} X Xint Xdo_gsent(which,gimme,arglast) Xint which; Xint gimme; Xint *arglast; X{ X register ARRAY *ary = stack; X register int sp = arglast[0]; X register char **elem; X register STR *str; X struct servent *getservbyname(); X struct servent *getservbynumber(); X struct servent *getservent(); X struct servent *sent; X X if (gimme != G_ARRAY) { X astore(ary, ++sp, str_mortal(&str_undef)); X return sp; X } X X if (which == O_GSBYNAME) { X char *name = str_get(ary->ary_array[sp+1]); X char *proto = str_get(ary->ary_array[sp+2]); X X if (proto && !*proto) X proto = Nullch; X X sent = getservbyname(name,proto); X } X else if (which == O_GSBYPORT) { X int port = (int)str_gnum(ary->ary_array[sp+1]); X char *proto = str_get(ary->ary_array[sp+2]); X X sent = getservbyport(port,proto); X } X else X sent = getservent(); X if (sent) { X#ifndef lint X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_set(str, sent->s_name); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X for (elem = sent->s_aliases; *elem; elem++) { X str_cat(str, *elem); X if (elem[1]) X str_ncat(str," ",1); X } X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X#ifdef HAS_NTOHS X str_numset(str, (double)ntohs(sent->s_port)); X#else X str_numset(str, (double)(sent->s_port)); X#endif X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_set(str, sent->s_proto); X#else /* lint */ X elem = Nullch; X elem = elem; X (void)astore(ary, ++sp, str_mortal(&str_no)); X#endif /* lint */ X } X X return sp; X} X X#endif /* HAS_SOCKET */ X X#ifdef HAS_SELECT Xint Xdo_select(gimme,arglast) Xint gimme; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[0]; X register int i; X register int j; X register char *s; X register STR *str; X double value; X int maxlen = 0; X int nfound; X struct timeval timebuf; X struct timeval *tbuf = &timebuf; X int growsize; X#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678 X int masksize; X int offset; X char *fd_sets[4]; X int k; X X#if BYTEORDER & 0xf0000 X#define ORDERBYTE (0x88888888 - BYTEORDER) X#else X#define ORDERBYTE (0x4444 - BYTEORDER) X#endif X X#endif X X for (i = 1; i <= 3; i++) { X j = st[sp+i]->str_cur; X if (maxlen < j) X maxlen = j; X } X X#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678 X growsize = maxlen; /* little endians can use vecs directly */ X#else X#ifdef NFDBITS X X#ifndef NBBY X#define NBBY 8 X#endif X X masksize = NFDBITS / NBBY; X#else X masksize = sizeof(long); /* documented int, everyone seems to use long */ X#endif X growsize = maxlen + (masksize - (maxlen % masksize)); X Zero(&fd_sets[0], 4, char*); X#endif X X for (i = 1; i <= 3; i++) { X str = st[sp+i]; X j = str->str_len; X if (j < growsize) { X if (str->str_pok) { X Str_Grow(str,growsize); X s = str_get(str) + j; X while (++j <= growsize) { X *s++ = '\0'; X } X } X else if (str->str_ptr) { X Safefree(str->str_ptr); X str->str_ptr = Nullch; X } X } X#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678 X s = str->str_ptr; X if (s) { X New(403, fd_sets[i], growsize, char); X for (offset = 0; offset < growsize; offset += masksize) { X for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4)) X fd_sets[i][j+offset] = s[(k % masksize) + offset]; X } X } X#endif X } X str = st[sp+4]; X if (str->str_nok || str->str_pok) { X value = str_gnum(str); X if (value < 0.0) X value = 0.0; X timebuf.tv_sec = (long)value; X value -= (double)timebuf.tv_sec; X timebuf.tv_usec = (long)(value * 1000000.0); X } X else X tbuf = Null(struct timeval*); X X#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678 X nfound = select( X maxlen * 8, X st[sp+1]->str_ptr, X st[sp+2]->str_ptr, X st[sp+3]->str_ptr, X tbuf); X#else X nfound = select( X maxlen * 8, X fd_sets[1], X fd_sets[2], X fd_sets[3], X tbuf); X for (i = 1; i <= 3; i++) { X if (fd_sets[i]) { X str = st[sp+i]; X s = str->str_ptr; X for (offset = 0; offset < growsize; offset += masksize) { X for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4)) X s[(k % masksize) + offset] = fd_sets[i][j+offset]; X } X } X } X#endif X X st[++sp] = str_mortal(&str_no); X str_numset(st[sp], (double)nfound); X if (gimme == G_ARRAY && tbuf) { X value = (double)(timebuf.tv_sec) + X (double)(timebuf.tv_usec) / 1000000.0; X st[++sp] = str_mortal(&str_no); X str_numset(st[sp], value); X } X return sp; X} X#endif /* SELECT */ X X#ifdef HAS_SOCKET Xint Xdo_spair(stab1, stab2, arglast) XSTAB *stab1; XSTAB *stab2; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[2]; X register STIO *stio1; X register STIO *stio2; X int domain, type, protocol, fd[2]; X X if (!stab1 || !stab2) X return FALSE; X X stio1 = stab_io(stab1); X stio2 = stab_io(stab2); X if (!stio1) X stio1 = stab_io(stab1) = stio_new(); X else if (stio1->ifp) X do_close(stab1,FALSE); X if (!stio2) X stio2 = stab_io(stab2) = stio_new(); X else if (stio2->ifp) X do_close(stab2,FALSE); X X domain = (int)str_gnum(st[++sp]); X type = (int)str_gnum(st[++sp]); X protocol = (int)str_gnum(st[++sp]); X#ifdef TAINT X taintproper("Insecure dependency in socketpair"); X#endif X#ifdef HAS_SOCKETPAIR X if (socketpair(domain,type,protocol,fd) < 0) X return FALSE; X#else X fatal("Socketpair unimplemented"); X#endif X stio1->ifp = fdopen(fd[0], "r"); X stio1->ofp = fdopen(fd[0], "w"); X stio1->type = 's'; X stio2->ifp = fdopen(fd[1], "r"); X stio2->ofp = fdopen(fd[1], "w"); X stio2->type = 's'; X if (!stio1->ifp || !stio1->ofp || !stio2->ifp || !stio2->ofp) { X if (stio1->ifp) fclose(stio1->ifp); X if (stio1->ofp) fclose(stio1->ofp); X if (!stio1->ifp && !stio1->ofp) close(fd[0]); X if (stio2->ifp) fclose(stio2->ifp); X if (stio2->ofp) fclose(stio2->ofp); X if (!stio2->ifp && !stio2->ofp) close(fd[1]); X return FALSE; X } X X return TRUE; X} X X#endif /* HAS_SOCKET */ X Xint Xdo_gpwent(which,gimme,arglast) Xint which; Xint gimme; Xint *arglast; X{ X#ifdef I_PWD X register ARRAY *ary = stack; X register int sp = arglast[0]; X register STR *str; X struct passwd *getpwnam(); X struct passwd *getpwuid(); X struct passwd *getpwent(); X struct passwd *pwent; X X if (gimme != G_ARRAY) { X astore(ary, ++sp, str_mortal(&str_undef)); X return sp; X } X X if (which == O_GPWNAM) { X char *name = str_get(ary->ary_array[sp+1]); X X pwent = getpwnam(name); X } X else if (which == O_GPWUID) { X int uid = (int)str_gnum(ary->ary_array[sp+1]); X X pwent = getpwuid(uid); X } X else X pwent = getpwent(); X X if (pwent) { X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_set(str, pwent->pw_name); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_set(str, pwent->pw_passwd); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_numset(str, (double)pwent->pw_uid); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_numset(str, (double)pwent->pw_gid); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X#ifdef PWCHANGE X str_numset(str, (double)pwent->pw_change); X#else X#ifdef PWQUOTA X str_numset(str, (double)pwent->pw_quota); X#else X#ifdef PWAGE X str_set(str, pwent->pw_age); X#endif X#endif X#endif X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X#ifdef PWCLASS X str_set(str,pwent->pw_class); X#else X#ifdef PWCOMMENT X str_set(str, pwent->pw_comment); X#endif X#endif X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_set(str, pwent->pw_gecos); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_set(str, pwent->pw_dir); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_set(str, pwent->pw_shell); X#ifdef PWEXPIRE X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_numset(str, (double)pwent->pw_expire); X#endif X } X X return sp; X#else X fatal("password routines not implemented"); X#endif X} X Xint Xdo_ggrent(which,gimme,arglast) Xint which; Xint gimme; Xint *arglast; X{ X#ifdef I_GRP X register ARRAY *ary = stack; X register int sp = arglast[0]; X register char **elem; X register STR *str; X struct group *getgrnam(); X struct group *getgrgid(); X struct group *getgrent(); X struct group *grent; X X if (gimme != G_ARRAY) { X astore(ary, ++sp, str_mortal(&str_undef)); X return sp; X } X X if (which == O_GGRNAM) { X char *name = str_get(ary->ary_array[sp+1]); X X grent = getgrnam(name); X } X else if (which == O_GGRGID) { X int gid = (int)str_gnum(ary->ary_array[sp+1]); X X grent = getgrgid(gid); X } X else X grent = getgrent(); X X if (grent) { X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_set(str, grent->gr_name); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_set(str, grent->gr_passwd); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_numset(str, (double)grent->gr_gid); X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X for (elem = grent->gr_mem; *elem; elem++) { X str_cat(str, *elem); X if (elem[1]) X str_ncat(str," ",1); X } X } X X return sp; X#else X fatal("group routines not implemented"); X#endif X} X Xint Xdo_dirop(optype,stab,gimme,arglast) Xint optype; XSTAB *stab; Xint gimme; Xint *arglast; X{ X#if defined(DIRENT) && defined(HAS_READDIR) X register ARRAY *ary = stack; X register STR **st = ary->ary_array; X register int sp = arglast[1]; X register STIO *stio; X long along; X#ifndef telldir X long telldir(); X#endif X struct DIRENT *readdir(); X register struct DIRENT *dp; X X if (!stab) X goto nope; X if (!(stio = stab_io(stab))) X stio = stab_io(stab) = stio_new(); X if (!stio->dirp && optype != O_OPENDIR) X goto nope; X st[sp] = &str_yes; X switch (optype) { X case O_OPENDIR: X if (stio->dirp) X closedir(stio->dirp); X if (!(stio->dirp = opendir(str_get(st[sp+1])))) X goto nope; X break; X case O_READDIR: X if (gimme == G_ARRAY) { X --sp; X while (dp = readdir(stio->dirp)) { X#ifdef DIRNAMLEN X (void)astore(ary,++sp, X str_2mortal(str_make(dp->d_name,dp->d_namlen))); X#else X (void)astore(ary,++sp, X str_2mortal(str_make(dp->d_name,0))); X#endif X } X } X else { X if (!(dp = readdir(stio->dirp))) X goto nope; X st[sp] = str_mortal(&str_undef); X#ifdef DIRNAMLEN X str_nset(st[sp], dp->d_name, dp->d_namlen); X#else X str_set(st[sp], dp->d_name); X#endif X } X break; X#if MACH X case O_TELLDIR: X case O_SEEKDIR: X goto nope; X#else X case O_TELLDIR: X st[sp] = str_mortal(&str_undef); X str_numset(st[sp], (double)telldir(stio->dirp)); X break; X case O_SEEKDIR: X st[sp] = str_mortal(&str_undef); X along = (long)str_gnum(st[sp+1]); X (void)seekdir(stio->dirp,along); X break; X#endif X case O_REWINDDIR: X st[sp] = str_mortal(&str_undef); X (void)rewinddir(stio->dirp); X break; X case O_CLOSEDIR: X st[sp] = str_mortal(&str_undef); X (void)closedir(stio->dirp); X stio->dirp = 0; X break; X } X return sp; X Xnope: X st[sp] = &str_undef; X return sp; X X#else X fatal("Unimplemented directory operation"); X#endif X} X Xapply(type,arglast) Xint type; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[1]; X register int items = arglast[2] - sp; X register int val; X register int val2; X register int tot = 0; X char *s; X X#ifdef TAINT X for (st += ++sp; items--; st++) X tainted |= (*st)->str_tainted; X st = stack->ary_array; X sp = arglast[1]; X items = arglast[2] - sp; X#endif X switch (type) { X case O_CHMOD: X#ifdef TAINT X taintproper("Insecure dependency in chmod"); X#endif X if (--items > 0) { X tot = items; X val = (int)str_gnum(st[++sp]); X while (items--) { X if (chmod(str_get(st[++sp]),val)) X tot--; X } X } X break; X#ifdef HAS_CHOWN X case O_CHOWN: X#ifdef TAINT X taintproper("Insecure dependency in chown"); X#endif X if (items > 2) { X items -= 2; X tot = items; X val = (int)str_gnum(st[++sp]); X val2 = (int)str_gnum(st[++sp]); X while (items--) { X if (chown(str_get(st[++sp]),val,val2)) X tot--; X } X } X break; X#endif X#ifdef HAS_KILL X case O_KILL: X#ifdef TAINT X taintproper("Insecure dependency in kill"); X#endif X if (--items > 0) { X tot = items; X s = str_get(st[++sp]); X if (isupper(*s)) { X if (*s == 'S' && s[1] == 'I' && s[2] == 'G') X s += 3; X if (!(val = whichsig(s))) X fatal("Unrecognized signal name \"%s\"",s); X } X else X val = (int)str_gnum(st[sp]); X if (val < 0) { X val = -val; X while (items--) { X int proc = (int)str_gnum(st[++sp]); X#ifdef HAS_KILLPG X if (killpg(proc,val)) /* BSD */ X#else X if (kill(-proc,val)) /* SYSV */ X#endif X tot--; X } !STUFFY!FUNK! echo " " echo "End of kit 3 (of 36)" cat /dev/null >kit3isdone run='' config='' for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36; 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." for combo in *:AA; do if test -f "$combo"; then realfile=`basename $combo :AA` cat $realfile:[A-Z][A-Z] >$realfile rm -rf $realfile:[A-Z][A-Z] fi done rm -rf kit*isdone chmod 755 Configure ;; *) echo "You have run$run." echo "You still need to run$todo." ;; esac : Someone might mail this, so... exit exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.