xref: /onnv-gate/usr/src/cmd/sh/service.c (revision 12273:63678502e95e)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52256Sna195498  * Common Development and Distribution License (the "License").
62256Sna195498  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate 
220Sstevel@tonic-gate /*
23*12273SCasper.Dik@Sun.COM  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
26527Schin /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27527Schin /*	  All Rights Reserved  	*/
28527Schin 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * UNIX shell
310Sstevel@tonic-gate  */
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include	"defs.h"
340Sstevel@tonic-gate #include	<errno.h>
350Sstevel@tonic-gate #include	<fcntl.h>
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #define	ARGMK	01
380Sstevel@tonic-gate 
390Sstevel@tonic-gate static unsigned char	*execs();
40527Schin static void	gsort();
410Sstevel@tonic-gate static int	split();
42527Schin extern void makearg(struct argnod *);
430Sstevel@tonic-gate extern short topfd;
440Sstevel@tonic-gate 
450Sstevel@tonic-gate 
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate  * service routines for `execute'
480Sstevel@tonic-gate  */
49527Schin short
initio(struct ionod * iop,int save)50527Schin initio(struct ionod *iop, int save)
510Sstevel@tonic-gate {
52527Schin 	unsigned char	*ion;
53527Schin 	int	iof, fd;
540Sstevel@tonic-gate 	int		ioufd;
550Sstevel@tonic-gate 	short	lastfd;
560Sstevel@tonic-gate 	int	newmode;
570Sstevel@tonic-gate 
580Sstevel@tonic-gate 	lastfd = topfd;
590Sstevel@tonic-gate 	while (iop) {
600Sstevel@tonic-gate 		iof = iop->iofile;
610Sstevel@tonic-gate 		ion = mactrim(iop->ioname);
620Sstevel@tonic-gate 		ioufd = iof & IOUFD;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 		if (*ion && (flags&noexec) == 0) {
650Sstevel@tonic-gate 			if (save) {
660Sstevel@tonic-gate 				fdmap[topfd].org_fd = ioufd;
670Sstevel@tonic-gate 				fdmap[topfd++].dup_fd = savefd(ioufd);
680Sstevel@tonic-gate 			}
690Sstevel@tonic-gate 
705976Snakanon 			if (iof & IODOC_SUBST) {
710Sstevel@tonic-gate 				struct tempblk tb;
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 				subst(chkopen(ion, 0), (fd = tmpfil(&tb)));
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 				/*
760Sstevel@tonic-gate 				 * pushed in tmpfil() --
770Sstevel@tonic-gate 				 * bug fix for problem with
780Sstevel@tonic-gate 				 * in-line scripts
790Sstevel@tonic-gate 				 */
800Sstevel@tonic-gate 				poptemp();
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 				fd = chkopen(tmpout, 0);
830Sstevel@tonic-gate 				unlink((const char *)tmpout);
840Sstevel@tonic-gate 			} else if (iof & IOMOV) {
850Sstevel@tonic-gate 				if (eq(minus, ion)) {
860Sstevel@tonic-gate 					fd = -1;
870Sstevel@tonic-gate 					close(ioufd);
880Sstevel@tonic-gate 				} else if ((fd = stoi(ion)) >= USERIO) {
890Sstevel@tonic-gate 					failed(ion, badfile);
900Sstevel@tonic-gate 				}
910Sstevel@tonic-gate 				else
920Sstevel@tonic-gate 					fd = dup(fd);
930Sstevel@tonic-gate 			} else if (((iof & IOPUT) == 0) && ((iof & IORDW) == 0))
940Sstevel@tonic-gate 				fd = chkopen(ion, 0);
950Sstevel@tonic-gate 			else if (iof & IORDW) /* For <> */ {
960Sstevel@tonic-gate 				newmode = O_RDWR|O_CREAT;
970Sstevel@tonic-gate 				fd = chkopen(ion, newmode);
980Sstevel@tonic-gate 			} else if (flags & rshflg) {
990Sstevel@tonic-gate 				failed(ion, restricted);
1000Sstevel@tonic-gate 			} else if (iof & IOAPP &&
1010Sstevel@tonic-gate 			    (fd = open((char *)ion, 1)) >= 0) {
1020Sstevel@tonic-gate 				lseek(fd, (off_t)0, SEEK_END);
1030Sstevel@tonic-gate 			} else {
1040Sstevel@tonic-gate 				fd = create(ion);
1050Sstevel@tonic-gate 			}
1060Sstevel@tonic-gate 			if (fd >= 0)
1070Sstevel@tonic-gate 				renamef(fd, ioufd);
1080Sstevel@tonic-gate 		}
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 		iop = iop->ionxt;
1110Sstevel@tonic-gate 	}
1120Sstevel@tonic-gate 	return (lastfd);
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate unsigned char *
simple(s)1160Sstevel@tonic-gate simple(s)
1170Sstevel@tonic-gate unsigned char	*s;
1180Sstevel@tonic-gate {
1190Sstevel@tonic-gate 	unsigned char	*sname;
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 	sname = s;
1220Sstevel@tonic-gate 	while (1) {
1230Sstevel@tonic-gate 		if (any('/', sname))
1240Sstevel@tonic-gate 			while (*sname++ != '/')
1250Sstevel@tonic-gate 				;
1260Sstevel@tonic-gate 		else
1270Sstevel@tonic-gate 			return (sname);
1280Sstevel@tonic-gate 	}
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate unsigned char *
getpath(s)1320Sstevel@tonic-gate getpath(s)
1330Sstevel@tonic-gate 	unsigned char	*s;
1340Sstevel@tonic-gate {
135527Schin 	unsigned char	*path, *newpath;
136527Schin 	int pathlen;
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	if (any('/', s))
1390Sstevel@tonic-gate 	{
1400Sstevel@tonic-gate 		if (flags & rshflg)
1410Sstevel@tonic-gate 			failed(s, restricted);
1420Sstevel@tonic-gate 		else
1430Sstevel@tonic-gate 			return ((unsigned char *)nullstr);
1440Sstevel@tonic-gate 	} else if ((path = pathnod.namval) == 0)
1450Sstevel@tonic-gate 		return ((unsigned char *)defpath);
1460Sstevel@tonic-gate 	else {
1470Sstevel@tonic-gate 		pathlen = length(path)-1;
1480Sstevel@tonic-gate 		/* Add extra ':' if PATH variable ends in ':' */
1490Sstevel@tonic-gate 		if (pathlen > 2 && path[pathlen - 1] == ':' &&
1500Sstevel@tonic-gate 				path[pathlen - 2] != ':') {
1510Sstevel@tonic-gate 			newpath = locstak();
1520Sstevel@tonic-gate 			(void) memcpystak(newpath, path, pathlen);
1530Sstevel@tonic-gate 			newpath[pathlen] = ':';
1540Sstevel@tonic-gate 			endstak(newpath + pathlen + 1);
1550Sstevel@tonic-gate 			return (newpath);
1560Sstevel@tonic-gate 		} else
1570Sstevel@tonic-gate 			return (cpystak(path));
1580Sstevel@tonic-gate 	}
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate 
161527Schin int
pathopen(unsigned char * path,unsigned char * name)162527Schin pathopen(unsigned char *path, unsigned char *name)
1630Sstevel@tonic-gate {
164527Schin 	int	f;
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	do
1670Sstevel@tonic-gate 	{
1680Sstevel@tonic-gate 		path = catpath(path, name);
1690Sstevel@tonic-gate 	} while ((f = open((char *)curstak(), 0)) < 0 && path);
1700Sstevel@tonic-gate 	return (f);
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate unsigned char *
catpath(unsigned char * path,unsigned char * name)174527Schin catpath(unsigned char *path, unsigned char *name)
1750Sstevel@tonic-gate {
1760Sstevel@tonic-gate 	/*
1770Sstevel@tonic-gate 	 * leaves result on top of stack
1780Sstevel@tonic-gate 	 */
179527Schin 	unsigned char	*scanp = path;
180527Schin 	unsigned char	*argp = locstak();
1810Sstevel@tonic-gate 
182528Schin 	while (*scanp && *scanp != COLON) {
1830Sstevel@tonic-gate 		if (argp >= brkend)
1840Sstevel@tonic-gate 			growstak(argp);
1850Sstevel@tonic-gate 		*argp++ = *scanp++;
1860Sstevel@tonic-gate 	}
187528Schin 	if (scanp != path) {
1880Sstevel@tonic-gate 		if (argp >= brkend)
1890Sstevel@tonic-gate 			growstak(argp);
1900Sstevel@tonic-gate 		*argp++ = '/';
1910Sstevel@tonic-gate 	}
1920Sstevel@tonic-gate 	if (*scanp == COLON)
1930Sstevel@tonic-gate 		scanp++;
1940Sstevel@tonic-gate 	path = (*scanp ? scanp : 0);
1950Sstevel@tonic-gate 	scanp = name;
1960Sstevel@tonic-gate 	do
1970Sstevel@tonic-gate 	{
1980Sstevel@tonic-gate 		if (argp >= brkend)
1990Sstevel@tonic-gate 			growstak(argp);
2000Sstevel@tonic-gate 	}
201*12273SCasper.Dik@Sun.COM 	while (*argp++ = *scanp++)
202*12273SCasper.Dik@Sun.COM 		;
2030Sstevel@tonic-gate 	return (path);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate unsigned char *
nextpath(unsigned char * path)207527Schin nextpath(unsigned char *path)
2080Sstevel@tonic-gate {
209527Schin 	unsigned char	*scanp = path;
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	while (*scanp && *scanp != COLON)
2120Sstevel@tonic-gate 		scanp++;
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 	if (*scanp == COLON)
2150Sstevel@tonic-gate 		scanp++;
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 	return (*scanp ? scanp : 0);
2180Sstevel@tonic-gate }
2190Sstevel@tonic-gate 
220527Schin static const char	*xecmsg;
2210Sstevel@tonic-gate static unsigned char	**xecenv;
2220Sstevel@tonic-gate 
223527Schin void
execa(unsigned char * at[],short pos)224527Schin execa(unsigned char *at[], short pos)
2250Sstevel@tonic-gate {
226527Schin 	unsigned char	*path;
227527Schin 	unsigned char	**t = at;
2280Sstevel@tonic-gate 	int		cnt;
2290Sstevel@tonic-gate 
230528Schin 	if ((flags & noexec) == 0) {
231527Schin 		xecmsg = notfound;
2320Sstevel@tonic-gate 		path = getpath(*t);
2330Sstevel@tonic-gate 		xecenv = local_setenv();
2340Sstevel@tonic-gate 
235528Schin 		if (pos > 0) {
2360Sstevel@tonic-gate 			cnt = 1;
237528Schin 			while (cnt != pos) {
2380Sstevel@tonic-gate 				++cnt;
2390Sstevel@tonic-gate 				path = nextpath(path);
2400Sstevel@tonic-gate 			}
2410Sstevel@tonic-gate 			execs(path, t);
2420Sstevel@tonic-gate 			path = getpath(*t);
2430Sstevel@tonic-gate 		}
2440Sstevel@tonic-gate 		while (path = execs(path, t))
2450Sstevel@tonic-gate 			;
2460Sstevel@tonic-gate 		failed(*t, xecmsg);
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate static unsigned char *
execs(unsigned char * ap,unsigned char * t[])251527Schin execs(unsigned char *ap, unsigned char *t[])
2520Sstevel@tonic-gate {
253527Schin 	unsigned char	*p, *prefix;
254527Schin 	unsigned char	*savptr;
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	prefix = catpath(ap, t[0]);
2570Sstevel@tonic-gate 	trim(p = curstak());
2580Sstevel@tonic-gate 	sigchk();
2590Sstevel@tonic-gate 
260*12273SCasper.Dik@Sun.COM 	execve((const char *)p, (char *const *)&t[0],
261*12273SCasper.Dik@Sun.COM 	    (char *const *)xecenv);
2620Sstevel@tonic-gate 
263528Schin 	switch (errno) {
2640Sstevel@tonic-gate 	case ENOEXEC:		/* could be a shell script */
2650Sstevel@tonic-gate 		funcnt = 0;
2660Sstevel@tonic-gate 		flags = 0;
2670Sstevel@tonic-gate 		*flagadr = 0;
2680Sstevel@tonic-gate 		comdiv = 0;
2690Sstevel@tonic-gate 		ioset = 0;
2700Sstevel@tonic-gate 		clearup();	/* remove open files and for loop junk */
2710Sstevel@tonic-gate 		if (input)
2720Sstevel@tonic-gate 			close(input);
2730Sstevel@tonic-gate 		input = chkopen(p, 0);
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate #ifdef ACCT
2760Sstevel@tonic-gate 		preacct(p);	/* reset accounting */
2770Sstevel@tonic-gate #endif
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 		/*
2800Sstevel@tonic-gate 		 * set up new args
2810Sstevel@tonic-gate 		 */
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 		setargs(t);
2840Sstevel@tonic-gate 		longjmp(subshell, 1);
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	case ENOMEM:
2870Sstevel@tonic-gate 		failed(p, toobig);
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	case E2BIG:
2900Sstevel@tonic-gate 		failed(p, arglist);
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	case ETXTBSY:
2930Sstevel@tonic-gate 		failed(p, txtbsy);
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	case ELIBACC:
2960Sstevel@tonic-gate 		failed(p, libacc);
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	case ELIBBAD:
2990Sstevel@tonic-gate 		failed(p, libbad);
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	case ELIBSCN:
3020Sstevel@tonic-gate 		failed(p, libscn);
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	case ELIBMAX:
3050Sstevel@tonic-gate 		failed(p, libmax);
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 	default:
308527Schin 		xecmsg = badexec;
3090Sstevel@tonic-gate 	case ENOENT:
3100Sstevel@tonic-gate 		return (prefix);
3110Sstevel@tonic-gate 	}
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate BOOL		nosubst;
3150Sstevel@tonic-gate 
316527Schin void
trim(unsigned char * at)317527Schin trim(unsigned char *at)
3180Sstevel@tonic-gate {
319527Schin 	unsigned char	*last;
320527Schin 	unsigned char 	*current;
321527Schin 	unsigned char	c;
3220Sstevel@tonic-gate 	int	len;
3230Sstevel@tonic-gate 	wchar_t	wc;
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	nosubst = 0;
326528Schin 	if (current = at) {
3270Sstevel@tonic-gate 		last = at;
3280Sstevel@tonic-gate 		while (c = *current) {
3290Sstevel@tonic-gate 			if ((len = mbtowc(&wc, (char *)current,
330*12273SCasper.Dik@Sun.COM 			    MB_LEN_MAX)) <= 0) {
3310Sstevel@tonic-gate 				*last++ = c;
3320Sstevel@tonic-gate 				current++;
3330Sstevel@tonic-gate 				continue;
3340Sstevel@tonic-gate 			}
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 			if (wc != '\\') {
3370Sstevel@tonic-gate 				memcpy(last, current, len);
3380Sstevel@tonic-gate 				last += len;
3390Sstevel@tonic-gate 				current += len;
3400Sstevel@tonic-gate 				continue;
3410Sstevel@tonic-gate 			}
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 			/* remove \ and quoted nulls */
3440Sstevel@tonic-gate 			nosubst = 1;
3450Sstevel@tonic-gate 			current++;
3460Sstevel@tonic-gate 			if (c = *current) {
3470Sstevel@tonic-gate 				if ((len = mbtowc(&wc, (char *)current,
348*12273SCasper.Dik@Sun.COM 				    MB_LEN_MAX)) <= 0) {
3490Sstevel@tonic-gate 					*last++ = c;
3500Sstevel@tonic-gate 					current++;
3510Sstevel@tonic-gate 					continue;
3520Sstevel@tonic-gate 				}
3530Sstevel@tonic-gate 				memcpy(last, current, len);
3540Sstevel@tonic-gate 				last += len;
3550Sstevel@tonic-gate 				current += len;
3560Sstevel@tonic-gate 			} else
3570Sstevel@tonic-gate 				current++;
3580Sstevel@tonic-gate 		}
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 		*last = 0;
3610Sstevel@tonic-gate 	}
3620Sstevel@tonic-gate }
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate /* Same as trim, but only removes backlashes before slashes */
365527Schin void
trims(at)3660Sstevel@tonic-gate trims(at)
3670Sstevel@tonic-gate unsigned char	*at;
3680Sstevel@tonic-gate {
369527Schin 	unsigned char	*last;
370527Schin 	unsigned char 	*current;
371527Schin 	unsigned char	c;
3720Sstevel@tonic-gate 	int	len;
3730Sstevel@tonic-gate 	wchar_t	wc;
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	if (current = at)
3760Sstevel@tonic-gate 	{
3770Sstevel@tonic-gate 		last = at;
3780Sstevel@tonic-gate 		while (c = *current) {
3790Sstevel@tonic-gate 			if ((len = mbtowc(&wc, (char *)current,
3800Sstevel@tonic-gate 					MB_LEN_MAX)) <= 0) {
3810Sstevel@tonic-gate 				*last++ = c;
3820Sstevel@tonic-gate 				current++;
3830Sstevel@tonic-gate 				continue;
3840Sstevel@tonic-gate 			}
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 			if (wc != '\\') {
3870Sstevel@tonic-gate 				memcpy(last, current, len);
3880Sstevel@tonic-gate 				last += len; current += len;
3890Sstevel@tonic-gate 				continue;
3900Sstevel@tonic-gate 			}
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 			/* remove \ and quoted nulls */
3930Sstevel@tonic-gate 			current++;
3940Sstevel@tonic-gate 			if (!(c = *current)) {
3950Sstevel@tonic-gate 				current++;
3960Sstevel@tonic-gate 				continue;
3970Sstevel@tonic-gate 			}
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 			if (c == '/') {
4000Sstevel@tonic-gate 				*last++ = c;
4010Sstevel@tonic-gate 				current++;
4020Sstevel@tonic-gate 				continue;
4030Sstevel@tonic-gate 			}
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 			*last++ = '\\';
4060Sstevel@tonic-gate 			if ((len = mbtowc(&wc, (char *)current,
4070Sstevel@tonic-gate 					MB_LEN_MAX)) <= 0) {
4080Sstevel@tonic-gate 				*last++ = c;
4090Sstevel@tonic-gate 				current++;
4100Sstevel@tonic-gate 				continue;
4110Sstevel@tonic-gate 			}
4120Sstevel@tonic-gate 			memcpy(last, current, len);
4130Sstevel@tonic-gate 			last += len; current += len;
4140Sstevel@tonic-gate 		}
4150Sstevel@tonic-gate 		*last = 0;
4160Sstevel@tonic-gate 	}
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate unsigned char *
mactrim(s)4200Sstevel@tonic-gate mactrim(s)
4210Sstevel@tonic-gate unsigned char	*s;
4220Sstevel@tonic-gate {
423527Schin 	unsigned char	*t = macro(s);
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 	trim(t);
4260Sstevel@tonic-gate 	return (t);
4270Sstevel@tonic-gate }
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate unsigned char **
scan(argn)4300Sstevel@tonic-gate scan(argn)
4310Sstevel@tonic-gate int	argn;
4320Sstevel@tonic-gate {
433527Schin 	struct argnod *argp =
4340Sstevel@tonic-gate 			(struct argnod *)(Rcheat(gchain) & ~ARGMK);
435527Schin 	unsigned char **comargn, **comargm;
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	comargn = (unsigned char **)getstak(BYTESPERWORD * argn + BYTESPERWORD);
4380Sstevel@tonic-gate 	comargm = comargn += argn;
4390Sstevel@tonic-gate 	*comargn = ENDARGS;
4400Sstevel@tonic-gate 	while (argp)
4410Sstevel@tonic-gate 	{
4420Sstevel@tonic-gate 		*--comargn = argp->argval;
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 		trim(*comargn);
4450Sstevel@tonic-gate 		argp = argp->argnxt;
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate 		if (argp == 0 || Rcheat(argp) & ARGMK)
4480Sstevel@tonic-gate 		{
4490Sstevel@tonic-gate 			gsort(comargn, comargm);
4500Sstevel@tonic-gate 			comargm = comargn;
4510Sstevel@tonic-gate 		}
4520Sstevel@tonic-gate 		argp = (struct argnod *)(Rcheat(argp) & ~ARGMK);
4530Sstevel@tonic-gate 	}
4540Sstevel@tonic-gate 	return (comargn);
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate 
457527Schin static void
gsort(from,to)4580Sstevel@tonic-gate gsort(from, to)
4590Sstevel@tonic-gate unsigned char	*from[], *to[];
4600Sstevel@tonic-gate {
4610Sstevel@tonic-gate 	int	k, m, n;
462527Schin 	int	i, j;
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate 	if ((n = to - from) <= 1)
4650Sstevel@tonic-gate 		return;
4660Sstevel@tonic-gate 	for (j = 1; j <= n; j *= 2)
4670Sstevel@tonic-gate 		;
4680Sstevel@tonic-gate 	for (m = 2 * j - 1; m /= 2; )
4690Sstevel@tonic-gate 	{
4700Sstevel@tonic-gate 		k = n - m;
4710Sstevel@tonic-gate 		for (j = 0; j < k; j++)
4720Sstevel@tonic-gate 		{
4730Sstevel@tonic-gate 			for (i = j; i >= 0; i -= m)
4740Sstevel@tonic-gate 			{
475527Schin 				unsigned char **fromi;
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate 				fromi = &from[i];
4780Sstevel@tonic-gate 				if (cf(fromi[m], fromi[0]) > 0)
4790Sstevel@tonic-gate 				{
4800Sstevel@tonic-gate 					break;
4810Sstevel@tonic-gate 				}
4820Sstevel@tonic-gate 				else
4830Sstevel@tonic-gate 				{
4840Sstevel@tonic-gate 					unsigned char *s;
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 					s = fromi[m];
4870Sstevel@tonic-gate 					fromi[m] = fromi[0];
4880Sstevel@tonic-gate 					fromi[0] = s;
4890Sstevel@tonic-gate 				}
4900Sstevel@tonic-gate 			}
4910Sstevel@tonic-gate 		}
4920Sstevel@tonic-gate 	}
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate /*
4960Sstevel@tonic-gate  * Argument list generation
4970Sstevel@tonic-gate  */
498527Schin int
getarg(ac)4990Sstevel@tonic-gate getarg(ac)
5000Sstevel@tonic-gate struct comnod	*ac;
5010Sstevel@tonic-gate {
502527Schin 	struct argnod	*argp;
503527Schin 	int		count = 0;
504527Schin 	struct comnod	*c;
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 	if (c = ac)
5070Sstevel@tonic-gate 	{
5080Sstevel@tonic-gate 		argp = c->comarg;
5090Sstevel@tonic-gate 		while (argp)
5100Sstevel@tonic-gate 		{
5110Sstevel@tonic-gate 			count += split(macro(argp->argval), 1);
5120Sstevel@tonic-gate 			argp = argp->argnxt;
5130Sstevel@tonic-gate 		}
5140Sstevel@tonic-gate 	}
5150Sstevel@tonic-gate 	return (count);
5160Sstevel@tonic-gate }
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate static int
split(s)5190Sstevel@tonic-gate split(s)		/* blank interpretation routine */
5200Sstevel@tonic-gate unsigned char	*s;
5210Sstevel@tonic-gate {
522527Schin 	unsigned char	*argp;
523527Schin 	int		c;
5240Sstevel@tonic-gate 	int		count = 0;
5250Sstevel@tonic-gate 	for (;;)
5260Sstevel@tonic-gate 	{
527527Schin 		int length;
5280Sstevel@tonic-gate 		sigchk();
5290Sstevel@tonic-gate 		argp = locstak() + BYTESPERWORD;
5300Sstevel@tonic-gate 		while (c = *s) {
5310Sstevel@tonic-gate 			wchar_t wc;
5320Sstevel@tonic-gate 			if ((length = mbtowc(&wc, (char *)s,
5330Sstevel@tonic-gate 					MB_LEN_MAX)) <= 0) {
5340Sstevel@tonic-gate 				wc = (unsigned char)*s;
5350Sstevel@tonic-gate 				length = 1;
5360Sstevel@tonic-gate 			}
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate 			if (c == '\\') { /* skip over quoted characters */
5390Sstevel@tonic-gate 				if (argp >= brkend)
5400Sstevel@tonic-gate 					growstak(argp);
5410Sstevel@tonic-gate 				*argp++ = c;
5420Sstevel@tonic-gate 				s++;
5430Sstevel@tonic-gate 				/* get rest of multibyte character */
5440Sstevel@tonic-gate 				if ((length = mbtowc(&wc, (char *)s,
5450Sstevel@tonic-gate 						MB_LEN_MAX)) <= 0) {
5460Sstevel@tonic-gate 					wc = (unsigned char)*s;
5470Sstevel@tonic-gate 					length = 1;
5480Sstevel@tonic-gate 				}
5490Sstevel@tonic-gate 				if (argp >= brkend)
5500Sstevel@tonic-gate 					growstak(argp);
5510Sstevel@tonic-gate 				*argp++ = *s++;
5520Sstevel@tonic-gate 				while (--length > 0) {
5530Sstevel@tonic-gate 					if (argp >= brkend)
5540Sstevel@tonic-gate 						growstak(argp);
5550Sstevel@tonic-gate 					*argp++ = *s++;
5560Sstevel@tonic-gate 				}
5570Sstevel@tonic-gate 				continue;
5580Sstevel@tonic-gate 			}
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 			if (anys(s, ifsnod.namval)) {
5610Sstevel@tonic-gate 				/* skip to next character position */
5620Sstevel@tonic-gate 				s += length;
5630Sstevel@tonic-gate 				break;
5640Sstevel@tonic-gate 			}
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 			if (argp >= brkend)
5670Sstevel@tonic-gate 				growstak(argp);
5680Sstevel@tonic-gate 			*argp++ = c;
5690Sstevel@tonic-gate 			s++;
5700Sstevel@tonic-gate 			while (--length > 0) {
5710Sstevel@tonic-gate 				if (argp >= brkend)
5720Sstevel@tonic-gate 					growstak(argp);
5730Sstevel@tonic-gate 				*argp++ = *s++;
5740Sstevel@tonic-gate 			}
5750Sstevel@tonic-gate 		}
5760Sstevel@tonic-gate 		if (argp == staktop + BYTESPERWORD)
5770Sstevel@tonic-gate 		{
5780Sstevel@tonic-gate 			if (c)
5790Sstevel@tonic-gate 			{
5800Sstevel@tonic-gate 				continue;
5810Sstevel@tonic-gate 			}
5820Sstevel@tonic-gate 			else
5830Sstevel@tonic-gate 			{
5840Sstevel@tonic-gate 				return (count);
5850Sstevel@tonic-gate 			}
5860Sstevel@tonic-gate 		}
5870Sstevel@tonic-gate 		/*
5880Sstevel@tonic-gate 		 * file name generation
5890Sstevel@tonic-gate 		 */
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 		argp = endstak(argp);
5920Sstevel@tonic-gate 		trims(((struct argnod *)argp)->argval);
5930Sstevel@tonic-gate 		if ((flags & nofngflg) == 0 &&
5940Sstevel@tonic-gate 			(c = expand(((struct argnod *)argp)->argval, 0)))
5950Sstevel@tonic-gate 			count += c;
5960Sstevel@tonic-gate 		else
5970Sstevel@tonic-gate 		{
598527Schin 			makearg((struct argnod *)argp);
5990Sstevel@tonic-gate 			count++;
6000Sstevel@tonic-gate 		}
6010Sstevel@tonic-gate 		gchain = (struct argnod *)((int)gchain | ARGMK);
6020Sstevel@tonic-gate 	}
6030Sstevel@tonic-gate }
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate #ifdef ACCT
6060Sstevel@tonic-gate #include	<sys/types.h>
6070Sstevel@tonic-gate #include	<sys/acct.h>
6080Sstevel@tonic-gate #include 	<sys/times.h>
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate struct acct sabuf;
6110Sstevel@tonic-gate struct tms buffer;
6120Sstevel@tonic-gate static clock_t before;
6130Sstevel@tonic-gate static int shaccton;	/* 0 implies do not write record on exit */
6140Sstevel@tonic-gate 			/* 1 implies write acct record on exit */
615527Schin static comp_t compress(clock_t);
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate /*
6190Sstevel@tonic-gate  *	suspend accounting until turned on by preacct()
6200Sstevel@tonic-gate  */
621527Schin void
suspacct(void)622527Schin suspacct(void)
6230Sstevel@tonic-gate {
6240Sstevel@tonic-gate 	shaccton = 0;
6250Sstevel@tonic-gate }
6260Sstevel@tonic-gate 
627527Schin void
preacct(unsigned char * cmdadr)628527Schin preacct(unsigned char *cmdadr)
6290Sstevel@tonic-gate {
6300Sstevel@tonic-gate 	unsigned char *simple();
6310Sstevel@tonic-gate 
632528Schin 	if (acctnod.namval && *acctnod.namval) {
6330Sstevel@tonic-gate 		sabuf.ac_btime = time((time_t *)0);
6340Sstevel@tonic-gate 		before = times(&buffer);
6350Sstevel@tonic-gate 		sabuf.ac_uid = getuid();
6360Sstevel@tonic-gate 		sabuf.ac_gid = getgid();
6370Sstevel@tonic-gate 		movstrn(simple(cmdadr), sabuf.ac_comm, sizeof (sabuf.ac_comm));
6380Sstevel@tonic-gate 		shaccton = 1;
6390Sstevel@tonic-gate 	}
6400Sstevel@tonic-gate }
6410Sstevel@tonic-gate 
642527Schin void
doacct(void)643527Schin doacct(void)
6440Sstevel@tonic-gate {
6450Sstevel@tonic-gate 	int fd;
6460Sstevel@tonic-gate 	clock_t after;
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate 	if (shaccton) {
6490Sstevel@tonic-gate 		after = times(&buffer);
6500Sstevel@tonic-gate 		sabuf.ac_utime = compress(buffer.tms_utime + buffer.tms_cutime);
6510Sstevel@tonic-gate 		sabuf.ac_stime = compress(buffer.tms_stime + buffer.tms_cstime);
6520Sstevel@tonic-gate 		sabuf.ac_etime = compress(after - before);
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate 		if ((fd = open((char *)acctnod.namval,
655*12273SCasper.Dik@Sun.COM 		    O_WRONLY | O_APPEND | O_CREAT, 0666)) != -1) {
6560Sstevel@tonic-gate 			write(fd, &sabuf, sizeof (sabuf));
6570Sstevel@tonic-gate 			close(fd);
6580Sstevel@tonic-gate 		}
6590Sstevel@tonic-gate 	}
6600Sstevel@tonic-gate }
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate /*
6630Sstevel@tonic-gate  *	Produce a pseudo-floating point representation
6640Sstevel@tonic-gate  *	with 3 bits base-8 exponent, 13 bits fraction
6650Sstevel@tonic-gate  */
6660Sstevel@tonic-gate 
667527Schin static comp_t
compress(clock_t t)668527Schin compress(clock_t t)
6690Sstevel@tonic-gate {
670527Schin 	int exp = 0;
671527Schin 	int rund = 0;
6720Sstevel@tonic-gate 
673528Schin 	while (t >= 8192) {
6740Sstevel@tonic-gate 		exp++;
6750Sstevel@tonic-gate 		rund = t & 04;
6760Sstevel@tonic-gate 		t >>= 3;
6770Sstevel@tonic-gate 	}
6780Sstevel@tonic-gate 
679528Schin 	if (rund) {
6800Sstevel@tonic-gate 		t++;
681528Schin 		if (t >= 8192) {
6820Sstevel@tonic-gate 			t >>= 3;
6830Sstevel@tonic-gate 			exp++;
6840Sstevel@tonic-gate 		}
6850Sstevel@tonic-gate 	}
6860Sstevel@tonic-gate 	return ((exp << 13) + t);
6870Sstevel@tonic-gate }
6880Sstevel@tonic-gate #endif
689