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