Home | History | Annotate | Download | only in sh
      1     0    stevel /*
      2     0    stevel  * CDDL HEADER START
      3     0    stevel  *
      4     0    stevel  * The contents of this file are subject to the terms of the
      5  2256  na195498  * Common Development and Distribution License (the "License").
      6  2256  na195498  * You may not use this file except in compliance with the License.
      7     0    stevel  *
      8     0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0    stevel  * or http://www.opensolaris.org/os/licensing.
     10     0    stevel  * See the License for the specific language governing permissions
     11     0    stevel  * and limitations under the License.
     12     0    stevel  *
     13     0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0    stevel  *
     19     0    stevel  * CDDL HEADER END
     20     0    stevel  */
     21     0    stevel 
     22     0    stevel /*
     23  5976   nakanon  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24     0    stevel  * Use is subject to license terms.
     25     0    stevel  */
     26     0    stevel 
     27   527      chin /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28   527      chin /*	  All Rights Reserved  	*/
     29   527      chin 
     30   527      chin #pragma ident	"%Z%%M%	%I%	%E% SMI"
     31     0    stevel 
     32     0    stevel /*
     33     0    stevel  * UNIX shell
     34     0    stevel  */
     35     0    stevel 
     36     0    stevel #include	"defs.h"
     37     0    stevel #include	<errno.h>
     38     0    stevel #include	<fcntl.h>
     39     0    stevel #include	"sh_policy.h"
     40     0    stevel 
     41     0    stevel #define	ARGMK	01
     42     0    stevel 
     43     0    stevel static unsigned char	*execs();
     44   527      chin static void	gsort();
     45     0    stevel static int	split();
     46   527      chin extern void makearg(struct argnod *);
     47     0    stevel extern short topfd;
     48     0    stevel 
     49     0    stevel 
     50     0    stevel /*
     51     0    stevel  * service routines for `execute'
     52     0    stevel  */
     53   527      chin short
     54   527      chin initio(struct ionod *iop, int save)
     55     0    stevel {
     56   527      chin 	unsigned char	*ion;
     57   527      chin 	int	iof, fd;
     58     0    stevel 	int		ioufd;
     59     0    stevel 	short	lastfd;
     60     0    stevel 	int	newmode;
     61     0    stevel 
     62     0    stevel 	lastfd = topfd;
     63     0    stevel 	while (iop) {
     64     0    stevel 		iof = iop->iofile;
     65     0    stevel 		ion = mactrim(iop->ioname);
     66     0    stevel 		ioufd = iof & IOUFD;
     67     0    stevel 
     68     0    stevel 		if (*ion && (flags&noexec) == 0) {
     69     0    stevel 			if (save) {
     70     0    stevel 				fdmap[topfd].org_fd = ioufd;
     71     0    stevel 				fdmap[topfd++].dup_fd = savefd(ioufd);
     72     0    stevel 			}
     73     0    stevel 
     74  5976   nakanon 			if (iof & IODOC_SUBST) {
     75     0    stevel 				struct tempblk tb;
     76     0    stevel 
     77     0    stevel 				subst(chkopen(ion, 0), (fd = tmpfil(&tb)));
     78     0    stevel 
     79     0    stevel 				/*
     80     0    stevel 				 * pushed in tmpfil() --
     81     0    stevel 				 * bug fix for problem with
     82     0    stevel 				 * in-line scripts
     83     0    stevel 				 */
     84     0    stevel 				poptemp();
     85     0    stevel 
     86     0    stevel 				fd = chkopen(tmpout, 0);
     87     0    stevel 				unlink((const char *)tmpout);
     88     0    stevel 			} else if (iof & IOMOV) {
     89     0    stevel 				if (eq(minus, ion)) {
     90     0    stevel 					fd = -1;
     91     0    stevel 					close(ioufd);
     92     0    stevel 				} else if ((fd = stoi(ion)) >= USERIO) {
     93     0    stevel 					failed(ion, badfile);
     94     0    stevel 				}
     95     0    stevel 				else
     96     0    stevel 					fd = dup(fd);
     97     0    stevel 			} else if (((iof & IOPUT) == 0) && ((iof & IORDW) == 0))
     98     0    stevel 				fd = chkopen(ion, 0);
     99     0    stevel 			else if (iof & IORDW) /* For <> */ {
    100     0    stevel 				newmode = O_RDWR|O_CREAT;
    101     0    stevel 				fd = chkopen(ion, newmode);
    102     0    stevel 			} else if (flags & rshflg) {
    103     0    stevel 				failed(ion, restricted);
    104     0    stevel 			} else if (iof & IOAPP &&
    105     0    stevel 			    (fd = open((char *)ion, 1)) >= 0) {
    106     0    stevel 				lseek(fd, (off_t)0, SEEK_END);
    107     0    stevel 			} else {
    108     0    stevel 				fd = create(ion);
    109     0    stevel 			}
    110     0    stevel 			if (fd >= 0)
    111     0    stevel 				renamef(fd, ioufd);
    112     0    stevel 		}
    113     0    stevel 
    114     0    stevel 		iop = iop->ionxt;
    115     0    stevel 	}
    116     0    stevel 	return (lastfd);
    117     0    stevel }
    118     0    stevel 
    119     0    stevel unsigned char *
    120     0    stevel simple(s)
    121     0    stevel unsigned char	*s;
    122     0    stevel {
    123     0    stevel 	unsigned char	*sname;
    124     0    stevel 
    125     0    stevel 	sname = s;
    126     0    stevel 	while (1) {
    127     0    stevel 		if (any('/', sname))
    128     0    stevel 			while (*sname++ != '/')
    129     0    stevel 				;
    130     0    stevel 		else
    131     0    stevel 			return (sname);
    132     0    stevel 	}
    133     0    stevel }
    134     0    stevel 
    135     0    stevel unsigned char *
    136     0    stevel getpath(s)
    137     0    stevel 	unsigned char	*s;
    138     0    stevel {
    139   527      chin 	unsigned char	*path, *newpath;
    140   527      chin 	int pathlen;
    141     0    stevel 
    142     0    stevel 	if (any('/', s))
    143     0    stevel 	{
    144     0    stevel 		if (flags & rshflg)
    145     0    stevel 			failed(s, restricted);
    146     0    stevel 		else
    147     0    stevel 			return ((unsigned char *)nullstr);
    148     0    stevel 	} else if ((path = pathnod.namval) == 0)
    149     0    stevel 		return ((unsigned char *)defpath);
    150     0    stevel 	else {
    151     0    stevel 		pathlen = length(path)-1;
    152     0    stevel 		/* Add extra ':' if PATH variable ends in ':' */
    153     0    stevel 		if (pathlen > 2 && path[pathlen - 1] == ':' &&
    154     0    stevel 				path[pathlen - 2] != ':') {
    155     0    stevel 			newpath = locstak();
    156     0    stevel 			(void) memcpystak(newpath, path, pathlen);
    157     0    stevel 			newpath[pathlen] = ':';
    158     0    stevel 			endstak(newpath + pathlen + 1);
    159     0    stevel 			return (newpath);
    160     0    stevel 		} else
    161     0    stevel 			return (cpystak(path));
    162     0    stevel 	}
    163     0    stevel }
    164     0    stevel 
    165   527      chin int
    166   527      chin pathopen(unsigned char *path, unsigned char *name)
    167     0    stevel {
    168   527      chin 	int	f;
    169     0    stevel 
    170     0    stevel 	do
    171     0    stevel 	{
    172     0    stevel 		path = catpath(path, name);
    173     0    stevel 	} while ((f = open((char *)curstak(), 0)) < 0 && path);
    174     0    stevel 	return (f);
    175     0    stevel }
    176     0    stevel 
    177     0    stevel unsigned char *
    178   527      chin catpath(unsigned char *path, unsigned char *name)
    179     0    stevel {
    180     0    stevel 	/*
    181     0    stevel 	 * leaves result on top of stack
    182     0    stevel 	 */
    183   527      chin 	unsigned char	*scanp = path;
    184   527      chin 	unsigned char	*argp = locstak();
    185     0    stevel 
    186   528      chin 	while (*scanp && *scanp != COLON) {
    187     0    stevel 		if (argp >= brkend)
    188     0    stevel 			growstak(argp);
    189     0    stevel 		*argp++ = *scanp++;
    190     0    stevel 	}
    191   528      chin 	if (scanp != path) {
    192     0    stevel 		if (argp >= brkend)
    193     0    stevel 			growstak(argp);
    194     0    stevel 		*argp++ = '/';
    195     0    stevel 	}
    196     0    stevel 	if (*scanp == COLON)
    197     0    stevel 		scanp++;
    198     0    stevel 	path = (*scanp ? scanp : 0);
    199     0    stevel 	scanp = name;
    200     0    stevel 	do
    201     0    stevel 	{
    202     0    stevel 		if (argp >= brkend)
    203     0    stevel 			growstak(argp);
    204     0    stevel 	}
    205     0    stevel 	while (*argp++ = *scanp++);
    206     0    stevel 	return (path);
    207     0    stevel }
    208     0    stevel 
    209     0    stevel unsigned char *
    210   527      chin nextpath(unsigned char *path)
    211     0    stevel {
    212   527      chin 	unsigned char	*scanp = path;
    213     0    stevel 
    214     0    stevel 	while (*scanp && *scanp != COLON)
    215     0    stevel 		scanp++;
    216     0    stevel 
    217     0    stevel 	if (*scanp == COLON)
    218     0    stevel 		scanp++;
    219     0    stevel 
    220     0    stevel 	return (*scanp ? scanp : 0);
    221     0    stevel }
    222     0    stevel 
    223   527      chin static const char	*xecmsg;
    224     0    stevel static unsigned char	**xecenv;
    225     0    stevel 
    226   527      chin void
    227   527      chin execa(unsigned char *at[], short pos)
    228     0    stevel {
    229   527      chin 	unsigned char	*path;
    230   527      chin 	unsigned char	**t = at;
    231     0    stevel 	int		cnt;
    232     0    stevel 
    233   528      chin 	if ((flags & noexec) == 0) {
    234   527      chin 		xecmsg = notfound;
    235     0    stevel 		path = getpath(*t);
    236     0    stevel 		xecenv = local_setenv();
    237     0    stevel 
    238   528      chin 		if (pos > 0) {
    239     0    stevel 			cnt = 1;
    240   528      chin 			while (cnt != pos) {
    241     0    stevel 				++cnt;
    242     0    stevel 				path = nextpath(path);
    243     0    stevel 			}
    244     0    stevel 			execs(path, t);
    245     0    stevel 			path = getpath(*t);
    246     0    stevel 		}
    247     0    stevel 		while (path = execs(path, t))
    248     0    stevel 			;
    249     0    stevel 		failed(*t, xecmsg);
    250     0    stevel 	}
    251     0    stevel }
    252     0    stevel 
    253     0    stevel static unsigned char *
    254   527      chin execs(unsigned char *ap, unsigned char *t[])
    255     0    stevel {
    256   527      chin 	int		pfstatus = NOATTRS;
    257   527      chin 	unsigned char	*p, *prefix;
    258   527      chin 	unsigned char	*savptr;
    259     0    stevel 
    260     0    stevel 	prefix = catpath(ap, t[0]);
    261     0    stevel 	trim(p = curstak());
    262     0    stevel 	sigchk();
    263     0    stevel 
    264     0    stevel 	if (flags & pfshflg) {
    265     0    stevel 		/*
    266     0    stevel 		 * Need to save the stack information, or the
    267     0    stevel 		 * first memory allocation in secpolicy_profile_lookup()
    268     0    stevel 		 * will clobber it.
    269     0    stevel 		 */
    270     0    stevel 		savptr = endstak(p + strlen((const char *)p) + 1);
    271     0    stevel 
    272     0    stevel 		pfstatus = secpolicy_pfexec((const char *)p,
    273     0    stevel 		    (char **)t, (const char **)xecenv);
    274     0    stevel 
    275     0    stevel 		if (pfstatus != NOATTRS) {
    276     0    stevel 			errno = pfstatus;
    277     0    stevel 		}
    278     0    stevel 
    279     0    stevel 		tdystak(savptr);
    280     0    stevel 	}
    281     0    stevel 
    282     0    stevel 	if (pfstatus == NOATTRS) {
    283     0    stevel 		execve((const char *)p, (char *const *)&t[0],
    284     0    stevel 		    (char *const *)xecenv);
    285     0    stevel 	}
    286     0    stevel 
    287   528      chin 	switch (errno) {
    288     0    stevel 	case ENOEXEC:		/* could be a shell script */
    289     0    stevel 		funcnt = 0;
    290     0    stevel 		flags = 0;
    291     0    stevel 		*flagadr = 0;
    292     0    stevel 		comdiv = 0;
    293     0    stevel 		ioset = 0;
    294     0    stevel 		clearup();	/* remove open files and for loop junk */
    295     0    stevel 		if (input)
    296     0    stevel 			close(input);
    297     0    stevel 		input = chkopen(p, 0);
    298     0    stevel 
    299     0    stevel #ifdef ACCT
    300     0    stevel 		preacct(p);	/* reset accounting */
    301     0    stevel #endif
    302     0    stevel 
    303     0    stevel 		/*
    304     0    stevel 		 * set up new args
    305     0    stevel 		 */
    306     0    stevel 
    307     0    stevel 		setargs(t);
    308     0    stevel 		longjmp(subshell, 1);
    309     0    stevel 
    310     0    stevel 	case ENOMEM:
    311     0    stevel 		failed(p, toobig);
    312     0    stevel 
    313     0    stevel 	case E2BIG:
    314     0    stevel 		failed(p, arglist);
    315     0    stevel 
    316     0    stevel 	case ETXTBSY:
    317     0    stevel 		failed(p, txtbsy);
    318     0    stevel 
    319     0    stevel 	case ELIBACC:
    320     0    stevel 		failed(p, libacc);
    321     0    stevel 
    322     0    stevel 	case ELIBBAD:
    323     0    stevel 		failed(p, libbad);
    324     0    stevel 
    325     0    stevel 	case ELIBSCN:
    326     0    stevel 		failed(p, libscn);
    327     0    stevel 
    328     0    stevel 	case ELIBMAX:
    329     0    stevel 		failed(p, libmax);
    330     0    stevel 
    331     0    stevel 	default:
    332   527      chin 		xecmsg = badexec;
    333     0    stevel 	case ENOENT:
    334     0    stevel 		return (prefix);
    335     0    stevel 	}
    336     0    stevel }
    337     0    stevel 
    338     0    stevel BOOL		nosubst;
    339     0    stevel 
    340   527      chin void
    341   527      chin trim(unsigned char *at)
    342     0    stevel {
    343   527      chin 	unsigned char	*last;
    344   527      chin 	unsigned char 	*current;
    345   527      chin 	unsigned char	c;
    346     0    stevel 	int	len;
    347     0    stevel 	wchar_t	wc;
    348     0    stevel 
    349     0    stevel 	nosubst = 0;
    350   528      chin 	if (current = at) {
    351     0    stevel 		last = at;
    352     0    stevel 		while (c = *current) {
    353     0    stevel 			if ((len = mbtowc(&wc, (char *)current,
    354     0    stevel 					MB_LEN_MAX)) <= 0) {
    355     0    stevel 				*last++ = c;
    356     0    stevel 				current++;
    357     0    stevel 				continue;
    358     0    stevel 			}
    359     0    stevel 
    360     0    stevel 			if (wc != '\\') {
    361     0    stevel 				memcpy(last, current, len);
    362     0    stevel 				last += len;
    363     0    stevel 				current += len;
    364     0    stevel 				continue;
    365     0    stevel 			}
    366     0    stevel 
    367     0    stevel 			/* remove \ and quoted nulls */
    368     0    stevel 			nosubst = 1;
    369     0    stevel 			current++;
    370     0    stevel 			if (c = *current) {
    371     0    stevel 				if ((len = mbtowc(&wc, (char *)current,
    372     0    stevel 						MB_LEN_MAX)) <= 0) {
    373     0    stevel 					*last++ = c;
    374     0    stevel 					current++;
    375     0    stevel 					continue;
    376     0    stevel 				}
    377     0    stevel 				memcpy(last, current, len);
    378     0    stevel 				last += len;
    379     0    stevel 				current += len;
    380     0    stevel 			} else
    381     0    stevel 				current++;
    382     0    stevel 		}
    383     0    stevel 
    384     0    stevel 		*last = 0;
    385     0    stevel 	}
    386     0    stevel }
    387     0    stevel 
    388     0    stevel /* Same as trim, but only removes backlashes before slashes */
    389   527      chin void
    390     0    stevel trims(at)
    391     0    stevel unsigned char	*at;
    392     0    stevel {
    393   527      chin 	unsigned char	*last;
    394   527      chin 	unsigned char 	*current;
    395   527      chin 	unsigned char	c;
    396     0    stevel 	int	len;
    397     0    stevel 	wchar_t	wc;
    398     0    stevel 
    399     0    stevel 	if (current = at)
    400     0    stevel 	{
    401     0    stevel 		last = at;
    402     0    stevel 		while (c = *current) {
    403     0    stevel 			if ((len = mbtowc(&wc, (char *)current,
    404     0    stevel 					MB_LEN_MAX)) <= 0) {
    405     0    stevel 				*last++ = c;
    406     0    stevel 				current++;
    407     0    stevel 				continue;
    408     0    stevel 			}
    409     0    stevel 
    410     0    stevel 			if (wc != '\\') {
    411     0    stevel 				memcpy(last, current, len);
    412     0    stevel 				last += len; current += len;
    413     0    stevel 				continue;
    414     0    stevel 			}
    415     0    stevel 
    416     0    stevel 			/* remove \ and quoted nulls */
    417     0    stevel 			current++;
    418     0    stevel 			if (!(c = *current)) {
    419     0    stevel 				current++;
    420     0    stevel 				continue;
    421     0    stevel 			}
    422     0    stevel 
    423     0    stevel 			if (c == '/') {
    424     0    stevel 				*last++ = c;
    425     0    stevel 				current++;
    426     0    stevel 				continue;
    427     0    stevel 			}
    428     0    stevel 
    429     0    stevel 			*last++ = '\\';
    430     0    stevel 			if ((len = mbtowc(&wc, (char *)current,
    431     0    stevel 					MB_LEN_MAX)) <= 0) {
    432     0    stevel 				*last++ = c;
    433     0    stevel 				current++;
    434     0    stevel 				continue;
    435     0    stevel 			}
    436     0    stevel 			memcpy(last, current, len);
    437     0    stevel 			last += len; current += len;
    438     0    stevel 		}
    439     0    stevel 		*last = 0;
    440     0    stevel 	}
    441     0    stevel }
    442     0    stevel 
    443     0    stevel unsigned char *
    444     0    stevel mactrim(s)
    445     0    stevel unsigned char	*s;
    446     0    stevel {
    447   527      chin 	unsigned char	*t = macro(s);
    448     0    stevel 
    449     0    stevel 	trim(t);
    450     0    stevel 	return (t);
    451     0    stevel }
    452     0    stevel 
    453     0    stevel unsigned char **
    454     0    stevel scan(argn)
    455     0    stevel int	argn;
    456     0    stevel {
    457   527      chin 	struct argnod *argp =
    458     0    stevel 			(struct argnod *)(Rcheat(gchain) & ~ARGMK);
    459   527      chin 	unsigned char **comargn, **comargm;
    460     0    stevel 
    461     0    stevel 	comargn = (unsigned char **)getstak(BYTESPERWORD * argn + BYTESPERWORD);
    462     0    stevel 	comargm = comargn += argn;
    463     0    stevel 	*comargn = ENDARGS;
    464     0    stevel 	while (argp)
    465     0    stevel 	{
    466     0    stevel 		*--comargn = argp->argval;
    467     0    stevel 
    468     0    stevel 		trim(*comargn);
    469     0    stevel 		argp = argp->argnxt;
    470     0    stevel 
    471     0    stevel 		if (argp == 0 || Rcheat(argp) & ARGMK)
    472     0    stevel 		{
    473     0    stevel 			gsort(comargn, comargm);
    474     0    stevel 			comargm = comargn;
    475     0    stevel 		}
    476     0    stevel 		argp = (struct argnod *)(Rcheat(argp) & ~ARGMK);
    477     0    stevel 	}
    478     0    stevel 	return (comargn);
    479     0    stevel }
    480     0    stevel 
    481   527      chin static void
    482     0    stevel gsort(from, to)
    483     0    stevel unsigned char	*from[], *to[];
    484     0    stevel {
    485     0    stevel 	int	k, m, n;
    486   527      chin 	int	i, j;
    487     0    stevel 
    488     0    stevel 	if ((n = to - from) <= 1)
    489     0    stevel 		return;
    490     0    stevel 	for (j = 1; j <= n; j *= 2)
    491     0    stevel 		;
    492     0    stevel 	for (m = 2 * j - 1; m /= 2; )
    493     0    stevel 	{
    494     0    stevel 		k = n - m;
    495     0    stevel 		for (j = 0; j < k; j++)
    496     0    stevel 		{
    497     0    stevel 			for (i = j; i >= 0; i -= m)
    498     0    stevel 			{
    499   527      chin 				unsigned char **fromi;
    500     0    stevel 
    501     0    stevel 				fromi = &from[i];
    502     0    stevel 				if (cf(fromi[m], fromi[0]) > 0)
    503     0    stevel 				{
    504     0    stevel 					break;
    505     0    stevel 				}
    506     0    stevel 				else
    507     0    stevel 				{
    508     0    stevel 					unsigned char *s;
    509     0    stevel 
    510     0    stevel 					s = fromi[m];
    511     0    stevel 					fromi[m] = fromi[0];
    512     0    stevel 					fromi[0] = s;
    513     0    stevel 				}
    514     0    stevel 			}
    515     0    stevel 		}
    516     0    stevel 	}
    517     0    stevel }
    518     0    stevel 
    519     0    stevel /*
    520     0    stevel  * Argument list generation
    521     0    stevel  */
    522   527      chin int
    523     0    stevel getarg(ac)
    524     0    stevel struct comnod	*ac;
    525     0    stevel {
    526   527      chin 	struct argnod	*argp;
    527   527      chin 	int		count = 0;
    528   527      chin 	struct comnod	*c;
    529     0    stevel 
    530     0    stevel 	if (c = ac)
    531     0    stevel 	{
    532     0    stevel 		argp = c->comarg;
    533     0    stevel 		while (argp)
    534     0    stevel 		{
    535     0    stevel 			count += split(macro(argp->argval), 1);
    536     0    stevel 			argp = argp->argnxt;
    537     0    stevel 		}
    538     0    stevel 	}
    539     0    stevel 	return (count);
    540     0    stevel }
    541     0    stevel 
    542     0    stevel static int
    543     0    stevel split(s)		/* blank interpretation routine */
    544     0    stevel unsigned char	*s;
    545     0    stevel {
    546   527      chin 	unsigned char	*argp;
    547   527      chin 	int		c;
    548     0    stevel 	int		count = 0;
    549     0    stevel 	for (;;)
    550     0    stevel 	{
    551   527      chin 		int length;
    552     0    stevel 		sigchk();
    553     0    stevel 		argp = locstak() + BYTESPERWORD;
    554     0    stevel 		while (c = *s) {
    555     0    stevel 			wchar_t wc;
    556     0    stevel 			if ((length = mbtowc(&wc, (char *)s,
    557     0    stevel 					MB_LEN_MAX)) <= 0) {
    558     0    stevel 				wc = (unsigned char)*s;
    559     0    stevel 				length = 1;
    560     0    stevel 			}
    561     0    stevel 
    562     0    stevel 			if (c == '\\') { /* skip over quoted characters */
    563     0    stevel 				if (argp >= brkend)
    564     0    stevel 					growstak(argp);
    565     0    stevel 				*argp++ = c;
    566     0    stevel 				s++;
    567     0    stevel 				/* get rest of multibyte character */
    568     0    stevel 				if ((length = mbtowc(&wc, (char *)s,
    569     0    stevel 						MB_LEN_MAX)) <= 0) {
    570     0    stevel 					wc = (unsigned char)*s;
    571     0    stevel 					length = 1;
    572     0    stevel 				}
    573     0    stevel 				if (argp >= brkend)
    574     0    stevel 					growstak(argp);
    575     0    stevel 				*argp++ = *s++;
    576     0    stevel 				while (--length > 0) {
    577     0    stevel 					if (argp >= brkend)
    578     0    stevel 						growstak(argp);
    579     0    stevel 					*argp++ = *s++;
    580     0    stevel 				}
    581     0    stevel 				continue;
    582     0    stevel 			}
    583     0    stevel 
    584     0    stevel 			if (anys(s, ifsnod.namval)) {
    585     0    stevel 				/* skip to next character position */
    586     0    stevel 				s += length;
    587     0    stevel 				break;
    588     0    stevel 			}
    589     0    stevel 
    590     0    stevel 			if (argp >= brkend)
    591     0    stevel 				growstak(argp);
    592     0    stevel 			*argp++ = c;
    593     0    stevel 			s++;
    594     0    stevel 			while (--length > 0) {
    595     0    stevel 				if (argp >= brkend)
    596     0    stevel 					growstak(argp);
    597     0    stevel 				*argp++ = *s++;
    598     0    stevel 			}
    599     0    stevel 		}
    600     0    stevel 		if (argp == staktop + BYTESPERWORD)
    601     0    stevel 		{
    602     0    stevel 			if (c)
    603     0    stevel 			{
    604     0    stevel 				continue;
    605     0    stevel 			}
    606     0    stevel 			else
    607     0    stevel 			{
    608     0    stevel 				return (count);
    609     0    stevel 			}
    610     0    stevel 		}
    611     0    stevel 		/*
    612     0    stevel 		 * file name generation
    613     0    stevel 		 */
    614     0    stevel 
    615     0    stevel 		argp = endstak(argp);
    616     0    stevel 		trims(((struct argnod *)argp)->argval);
    617     0    stevel 		if ((flags & nofngflg) == 0 &&
    618     0    stevel 			(c = expand(((struct argnod *)argp)->argval, 0)))
    619     0    stevel 			count += c;
    620     0    stevel 		else
    621     0    stevel 		{
    622   527      chin 			makearg((struct argnod *)argp);
    623     0    stevel 			count++;
    624     0    stevel 		}
    625     0    stevel 		gchain = (struct argnod *)((int)gchain | ARGMK);
    626     0    stevel 	}
    627     0    stevel }
    628     0    stevel 
    629     0    stevel #ifdef ACCT
    630     0    stevel #include	<sys/types.h>
    631     0    stevel #include	<sys/acct.h>
    632     0    stevel #include 	<sys/times.h>
    633     0    stevel 
    634     0    stevel struct acct sabuf;
    635     0    stevel struct tms buffer;
    636     0    stevel static clock_t before;
    637     0    stevel static int shaccton;	/* 0 implies do not write record on exit */
    638     0    stevel 			/* 1 implies write acct record on exit */
    639   527      chin static comp_t compress(clock_t);
    640     0    stevel 
    641     0    stevel 
    642     0    stevel /*
    643     0    stevel  *	suspend accounting until turned on by preacct()
    644     0    stevel  */
    645   527      chin void
    646   527      chin suspacct(void)
    647     0    stevel {
    648     0    stevel 	shaccton = 0;
    649     0    stevel }
    650     0    stevel 
    651   527      chin void
    652   527      chin preacct(unsigned char *cmdadr)
    653     0    stevel {
    654     0    stevel 	unsigned char *simple();
    655     0    stevel 
    656   528      chin 	if (acctnod.namval && *acctnod.namval) {
    657     0    stevel 		sabuf.ac_btime = time((time_t *)0);
    658     0    stevel 		before = times(&buffer);
    659     0    stevel 		sabuf.ac_uid = getuid();
    660     0    stevel 		sabuf.ac_gid = getgid();
    661     0    stevel 		movstrn(simple(cmdadr), sabuf.ac_comm, sizeof (sabuf.ac_comm));
    662     0    stevel 		shaccton = 1;
    663     0    stevel 	}
    664     0    stevel }
    665     0    stevel 
    666   527      chin void
    667   527      chin doacct(void)
    668     0    stevel {
    669     0    stevel 	int fd;
    670     0    stevel 	clock_t after;
    671     0    stevel 
    672     0    stevel 	if (shaccton) {
    673     0    stevel 		after = times(&buffer);
    674     0    stevel 		sabuf.ac_utime = compress(buffer.tms_utime + buffer.tms_cutime);
    675     0    stevel 		sabuf.ac_stime = compress(buffer.tms_stime + buffer.tms_cstime);
    676     0    stevel 		sabuf.ac_etime = compress(after - before);
    677     0    stevel 
    678     0    stevel 		if ((fd = open((char *)acctnod.namval,
    679     0    stevel 				O_WRONLY | O_APPEND | O_CREAT, 0666)) != -1) {
    680     0    stevel 			write(fd, &sabuf, sizeof (sabuf));
    681     0    stevel 			close(fd);
    682     0    stevel 		}
    683     0    stevel 	}
    684     0    stevel }
    685     0    stevel 
    686     0    stevel /*
    687     0    stevel  *	Produce a pseudo-floating point representation
    688     0    stevel  *	with 3 bits base-8 exponent, 13 bits fraction
    689     0    stevel  */
    690     0    stevel 
    691   527      chin static comp_t
    692   527      chin compress(clock_t t)
    693     0    stevel {
    694   527      chin 	int exp = 0;
    695   527      chin 	int rund = 0;
    696     0    stevel 
    697   528      chin 	while (t >= 8192) {
    698     0    stevel 		exp++;
    699     0    stevel 		rund = t & 04;
    700     0    stevel 		t >>= 3;
    701     0    stevel 	}
    702     0    stevel 
    703   528      chin 	if (rund) {
    704     0    stevel 		t++;
    705   528      chin 		if (t >= 8192) {
    706     0    stevel 			t >>= 3;
    707     0    stevel 			exp++;
    708     0    stevel 		}
    709     0    stevel 	}
    710     0    stevel 	return ((exp << 13) + t);
    711     0    stevel }
    712     0    stevel #endif
    713