17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*39e7390aSna195498 * Common Development and Distribution License (the "License"). 6*39e7390aSna195498 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate /* 23*39e7390aSna195498 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27965005c8Schin /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28965005c8Schin /* All Rights Reserved */ 29965005c8Schin 30965005c8Schin #pragma ident "%Z%%M% %I% %E% SMI" 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate /* 337c478bd9Sstevel@tonic-gate * UNIX shell 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include "defs.h" 377c478bd9Sstevel@tonic-gate #include <errno.h> 387c478bd9Sstevel@tonic-gate #include <fcntl.h> 397c478bd9Sstevel@tonic-gate #include "sh_policy.h" 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #define ARGMK 01 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate static unsigned char *execs(); 44965005c8Schin static void gsort(); 457c478bd9Sstevel@tonic-gate static int split(); 46965005c8Schin extern void makearg(struct argnod *); 477c478bd9Sstevel@tonic-gate extern short topfd; 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate /* 517c478bd9Sstevel@tonic-gate * service routines for `execute' 527c478bd9Sstevel@tonic-gate */ 53965005c8Schin short 54965005c8Schin initio(struct ionod *iop, int save) 557c478bd9Sstevel@tonic-gate { 56965005c8Schin unsigned char *ion; 57965005c8Schin int iof, fd; 587c478bd9Sstevel@tonic-gate int ioufd; 597c478bd9Sstevel@tonic-gate short lastfd; 607c478bd9Sstevel@tonic-gate int newmode; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate lastfd = topfd; 637c478bd9Sstevel@tonic-gate while (iop) { 647c478bd9Sstevel@tonic-gate iof = iop->iofile; 657c478bd9Sstevel@tonic-gate ion = mactrim(iop->ioname); 667c478bd9Sstevel@tonic-gate ioufd = iof & IOUFD; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate if (*ion && (flags&noexec) == 0) { 697c478bd9Sstevel@tonic-gate if (save) { 707c478bd9Sstevel@tonic-gate fdmap[topfd].org_fd = ioufd; 717c478bd9Sstevel@tonic-gate fdmap[topfd++].dup_fd = savefd(ioufd); 727c478bd9Sstevel@tonic-gate } 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate if (iof & IODOC) { 757c478bd9Sstevel@tonic-gate struct tempblk tb; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate subst(chkopen(ion, 0), (fd = tmpfil(&tb))); 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* 807c478bd9Sstevel@tonic-gate * pushed in tmpfil() -- 817c478bd9Sstevel@tonic-gate * bug fix for problem with 827c478bd9Sstevel@tonic-gate * in-line scripts 837c478bd9Sstevel@tonic-gate */ 847c478bd9Sstevel@tonic-gate poptemp(); 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate fd = chkopen(tmpout, 0); 877c478bd9Sstevel@tonic-gate unlink((const char *)tmpout); 887c478bd9Sstevel@tonic-gate } else if (iof & IOMOV) { 897c478bd9Sstevel@tonic-gate if (eq(minus, ion)) { 907c478bd9Sstevel@tonic-gate fd = -1; 917c478bd9Sstevel@tonic-gate close(ioufd); 927c478bd9Sstevel@tonic-gate } else if ((fd = stoi(ion)) >= USERIO) { 937c478bd9Sstevel@tonic-gate failed(ion, badfile); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate else 967c478bd9Sstevel@tonic-gate fd = dup(fd); 977c478bd9Sstevel@tonic-gate } else if (((iof & IOPUT) == 0) && ((iof & IORDW) == 0)) 987c478bd9Sstevel@tonic-gate fd = chkopen(ion, 0); 997c478bd9Sstevel@tonic-gate else if (iof & IORDW) /* For <> */ { 1007c478bd9Sstevel@tonic-gate newmode = O_RDWR|O_CREAT; 1017c478bd9Sstevel@tonic-gate fd = chkopen(ion, newmode); 1027c478bd9Sstevel@tonic-gate } else if (flags & rshflg) { 1037c478bd9Sstevel@tonic-gate failed(ion, restricted); 1047c478bd9Sstevel@tonic-gate } else if (iof & IOAPP && 1057c478bd9Sstevel@tonic-gate (fd = open((char *)ion, 1)) >= 0) { 1067c478bd9Sstevel@tonic-gate lseek(fd, (off_t)0, SEEK_END); 1077c478bd9Sstevel@tonic-gate } else { 1087c478bd9Sstevel@tonic-gate fd = create(ion); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate if (fd >= 0) 1117c478bd9Sstevel@tonic-gate renamef(fd, ioufd); 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate iop = iop->ionxt; 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate return (lastfd); 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate unsigned char * 1207c478bd9Sstevel@tonic-gate simple(s) 1217c478bd9Sstevel@tonic-gate unsigned char *s; 1227c478bd9Sstevel@tonic-gate { 1237c478bd9Sstevel@tonic-gate unsigned char *sname; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate sname = s; 1267c478bd9Sstevel@tonic-gate while (1) { 1277c478bd9Sstevel@tonic-gate if (any('/', sname)) 1287c478bd9Sstevel@tonic-gate while (*sname++ != '/') 1297c478bd9Sstevel@tonic-gate ; 1307c478bd9Sstevel@tonic-gate else 1317c478bd9Sstevel@tonic-gate return (sname); 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate unsigned char * 1367c478bd9Sstevel@tonic-gate getpath(s) 1377c478bd9Sstevel@tonic-gate unsigned char *s; 1387c478bd9Sstevel@tonic-gate { 139965005c8Schin unsigned char *path, *newpath; 140965005c8Schin int pathlen; 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate if (any('/', s)) 1437c478bd9Sstevel@tonic-gate { 1447c478bd9Sstevel@tonic-gate if (flags & rshflg) 1457c478bd9Sstevel@tonic-gate failed(s, restricted); 1467c478bd9Sstevel@tonic-gate else 1477c478bd9Sstevel@tonic-gate return ((unsigned char *)nullstr); 1487c478bd9Sstevel@tonic-gate } else if ((path = pathnod.namval) == 0) 1497c478bd9Sstevel@tonic-gate return ((unsigned char *)defpath); 1507c478bd9Sstevel@tonic-gate else { 1517c478bd9Sstevel@tonic-gate pathlen = length(path)-1; 1527c478bd9Sstevel@tonic-gate /* Add extra ':' if PATH variable ends in ':' */ 1537c478bd9Sstevel@tonic-gate if (pathlen > 2 && path[pathlen - 1] == ':' && 1547c478bd9Sstevel@tonic-gate path[pathlen - 2] != ':') { 1557c478bd9Sstevel@tonic-gate newpath = locstak(); 1567c478bd9Sstevel@tonic-gate (void) memcpystak(newpath, path, pathlen); 1577c478bd9Sstevel@tonic-gate newpath[pathlen] = ':'; 1587c478bd9Sstevel@tonic-gate endstak(newpath + pathlen + 1); 1597c478bd9Sstevel@tonic-gate return (newpath); 1607c478bd9Sstevel@tonic-gate } else 1617c478bd9Sstevel@tonic-gate return (cpystak(path)); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 165965005c8Schin int 166965005c8Schin pathopen(unsigned char *path, unsigned char *name) 1677c478bd9Sstevel@tonic-gate { 168965005c8Schin int f; 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate do 1717c478bd9Sstevel@tonic-gate { 1727c478bd9Sstevel@tonic-gate path = catpath(path, name); 1737c478bd9Sstevel@tonic-gate } while ((f = open((char *)curstak(), 0)) < 0 && path); 1747c478bd9Sstevel@tonic-gate return (f); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate unsigned char * 178965005c8Schin catpath(unsigned char *path, unsigned char *name) 1797c478bd9Sstevel@tonic-gate { 1807c478bd9Sstevel@tonic-gate /* 1817c478bd9Sstevel@tonic-gate * leaves result on top of stack 1827c478bd9Sstevel@tonic-gate */ 183965005c8Schin unsigned char *scanp = path; 184965005c8Schin unsigned char *argp = locstak(); 1857c478bd9Sstevel@tonic-gate 186db397771Schin while (*scanp && *scanp != COLON) { 1877c478bd9Sstevel@tonic-gate if (argp >= brkend) 1887c478bd9Sstevel@tonic-gate growstak(argp); 1897c478bd9Sstevel@tonic-gate *argp++ = *scanp++; 1907c478bd9Sstevel@tonic-gate } 191db397771Schin if (scanp != path) { 1927c478bd9Sstevel@tonic-gate if (argp >= brkend) 1937c478bd9Sstevel@tonic-gate growstak(argp); 1947c478bd9Sstevel@tonic-gate *argp++ = '/'; 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate if (*scanp == COLON) 1977c478bd9Sstevel@tonic-gate scanp++; 1987c478bd9Sstevel@tonic-gate path = (*scanp ? scanp : 0); 1997c478bd9Sstevel@tonic-gate scanp = name; 2007c478bd9Sstevel@tonic-gate do 2017c478bd9Sstevel@tonic-gate { 2027c478bd9Sstevel@tonic-gate if (argp >= brkend) 2037c478bd9Sstevel@tonic-gate growstak(argp); 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate while (*argp++ = *scanp++); 2067c478bd9Sstevel@tonic-gate return (path); 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate unsigned char * 210965005c8Schin nextpath(unsigned char *path) 2117c478bd9Sstevel@tonic-gate { 212965005c8Schin unsigned char *scanp = path; 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate while (*scanp && *scanp != COLON) 2157c478bd9Sstevel@tonic-gate scanp++; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate if (*scanp == COLON) 2187c478bd9Sstevel@tonic-gate scanp++; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate return (*scanp ? scanp : 0); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 223965005c8Schin static const char *xecmsg; 2247c478bd9Sstevel@tonic-gate static unsigned char **xecenv; 2257c478bd9Sstevel@tonic-gate 226965005c8Schin void 227965005c8Schin execa(unsigned char *at[], short pos) 2287c478bd9Sstevel@tonic-gate { 229965005c8Schin unsigned char *path; 230965005c8Schin unsigned char **t = at; 2317c478bd9Sstevel@tonic-gate int cnt; 2327c478bd9Sstevel@tonic-gate 233db397771Schin if ((flags & noexec) == 0) { 234965005c8Schin xecmsg = notfound; 2357c478bd9Sstevel@tonic-gate path = getpath(*t); 2367c478bd9Sstevel@tonic-gate xecenv = local_setenv(); 2377c478bd9Sstevel@tonic-gate 238db397771Schin if (pos > 0) { 2397c478bd9Sstevel@tonic-gate cnt = 1; 240db397771Schin while (cnt != pos) { 2417c478bd9Sstevel@tonic-gate ++cnt; 2427c478bd9Sstevel@tonic-gate path = nextpath(path); 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate execs(path, t); 2457c478bd9Sstevel@tonic-gate path = getpath(*t); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate while (path = execs(path, t)) 2487c478bd9Sstevel@tonic-gate ; 2497c478bd9Sstevel@tonic-gate failed(*t, xecmsg); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate static unsigned char * 254965005c8Schin execs(unsigned char *ap, unsigned char *t[]) 2557c478bd9Sstevel@tonic-gate { 256965005c8Schin int pfstatus = NOATTRS; 257965005c8Schin unsigned char *p, *prefix; 2587c478bd9Sstevel@tonic-gate unsigned char *savptr; 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate prefix = catpath(ap, t[0]); 2617c478bd9Sstevel@tonic-gate trim(p = curstak()); 2627c478bd9Sstevel@tonic-gate sigchk(); 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate if (flags & pfshflg) { 2657c478bd9Sstevel@tonic-gate /* 2667c478bd9Sstevel@tonic-gate * Need to save the stack information, or the 2677c478bd9Sstevel@tonic-gate * first memory allocation in secpolicy_profile_lookup() 2687c478bd9Sstevel@tonic-gate * will clobber it. 2697c478bd9Sstevel@tonic-gate */ 2707c478bd9Sstevel@tonic-gate savptr = endstak(p + strlen((const char *)p) + 1); 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate pfstatus = secpolicy_pfexec((const char *)p, 2737c478bd9Sstevel@tonic-gate (char **)t, (const char **)xecenv); 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate if (pfstatus != NOATTRS) { 2767c478bd9Sstevel@tonic-gate errno = pfstatus; 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate tdystak(savptr); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate if (pfstatus == NOATTRS) { 2837c478bd9Sstevel@tonic-gate execve((const char *)p, (char *const *)&t[0], 2847c478bd9Sstevel@tonic-gate (char *const *)xecenv); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 287db397771Schin switch (errno) { 2887c478bd9Sstevel@tonic-gate case ENOEXEC: /* could be a shell script */ 2897c478bd9Sstevel@tonic-gate funcnt = 0; 2907c478bd9Sstevel@tonic-gate flags = 0; 2917c478bd9Sstevel@tonic-gate *flagadr = 0; 2927c478bd9Sstevel@tonic-gate comdiv = 0; 2937c478bd9Sstevel@tonic-gate ioset = 0; 2947c478bd9Sstevel@tonic-gate clearup(); /* remove open files and for loop junk */ 2957c478bd9Sstevel@tonic-gate if (input) 2967c478bd9Sstevel@tonic-gate close(input); 2977c478bd9Sstevel@tonic-gate input = chkopen(p, 0); 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate #ifdef ACCT 3007c478bd9Sstevel@tonic-gate preacct(p); /* reset accounting */ 3017c478bd9Sstevel@tonic-gate #endif 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate /* 3047c478bd9Sstevel@tonic-gate * set up new args 3057c478bd9Sstevel@tonic-gate */ 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate setargs(t); 3087c478bd9Sstevel@tonic-gate longjmp(subshell, 1); 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate case ENOMEM: 3117c478bd9Sstevel@tonic-gate failed(p, toobig); 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate case E2BIG: 3147c478bd9Sstevel@tonic-gate failed(p, arglist); 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate case ETXTBSY: 3177c478bd9Sstevel@tonic-gate failed(p, txtbsy); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate case ELIBACC: 3207c478bd9Sstevel@tonic-gate failed(p, libacc); 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate case ELIBBAD: 3237c478bd9Sstevel@tonic-gate failed(p, libbad); 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate case ELIBSCN: 3267c478bd9Sstevel@tonic-gate failed(p, libscn); 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate case ELIBMAX: 3297c478bd9Sstevel@tonic-gate failed(p, libmax); 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate default: 332965005c8Schin xecmsg = badexec; 3337c478bd9Sstevel@tonic-gate case ENOENT: 3347c478bd9Sstevel@tonic-gate return (prefix); 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate BOOL nosubst; 3397c478bd9Sstevel@tonic-gate 340965005c8Schin void 341965005c8Schin trim(unsigned char *at) 3427c478bd9Sstevel@tonic-gate { 343965005c8Schin unsigned char *last; 344965005c8Schin unsigned char *current; 345965005c8Schin unsigned char c; 3467c478bd9Sstevel@tonic-gate int len; 3477c478bd9Sstevel@tonic-gate wchar_t wc; 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate nosubst = 0; 350db397771Schin if (current = at) { 3517c478bd9Sstevel@tonic-gate last = at; 3527c478bd9Sstevel@tonic-gate while (c = *current) { 3537c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 3547c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 3557c478bd9Sstevel@tonic-gate *last++ = c; 3567c478bd9Sstevel@tonic-gate current++; 3577c478bd9Sstevel@tonic-gate continue; 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if (wc != '\\') { 3617c478bd9Sstevel@tonic-gate memcpy(last, current, len); 3627c478bd9Sstevel@tonic-gate last += len; 3637c478bd9Sstevel@tonic-gate current += len; 3647c478bd9Sstevel@tonic-gate continue; 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate /* remove \ and quoted nulls */ 3687c478bd9Sstevel@tonic-gate nosubst = 1; 3697c478bd9Sstevel@tonic-gate current++; 3707c478bd9Sstevel@tonic-gate if (c = *current) { 3717c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 3727c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 3737c478bd9Sstevel@tonic-gate *last++ = c; 3747c478bd9Sstevel@tonic-gate current++; 3757c478bd9Sstevel@tonic-gate continue; 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate memcpy(last, current, len); 3787c478bd9Sstevel@tonic-gate last += len; 3797c478bd9Sstevel@tonic-gate current += len; 3807c478bd9Sstevel@tonic-gate } else 3817c478bd9Sstevel@tonic-gate current++; 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate *last = 0; 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate /* Same as trim, but only removes backlashes before slashes */ 389965005c8Schin void 3907c478bd9Sstevel@tonic-gate trims(at) 3917c478bd9Sstevel@tonic-gate unsigned char *at; 3927c478bd9Sstevel@tonic-gate { 393965005c8Schin unsigned char *last; 394965005c8Schin unsigned char *current; 395965005c8Schin unsigned char c; 3967c478bd9Sstevel@tonic-gate int len; 3977c478bd9Sstevel@tonic-gate wchar_t wc; 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate if (current = at) 4007c478bd9Sstevel@tonic-gate { 4017c478bd9Sstevel@tonic-gate last = at; 4027c478bd9Sstevel@tonic-gate while (c = *current) { 4037c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 4047c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 4057c478bd9Sstevel@tonic-gate *last++ = c; 4067c478bd9Sstevel@tonic-gate current++; 4077c478bd9Sstevel@tonic-gate continue; 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate if (wc != '\\') { 4117c478bd9Sstevel@tonic-gate memcpy(last, current, len); 4127c478bd9Sstevel@tonic-gate last += len; current += len; 4137c478bd9Sstevel@tonic-gate continue; 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate /* remove \ and quoted nulls */ 4177c478bd9Sstevel@tonic-gate current++; 4187c478bd9Sstevel@tonic-gate if (!(c = *current)) { 4197c478bd9Sstevel@tonic-gate current++; 4207c478bd9Sstevel@tonic-gate continue; 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate if (c == '/') { 4247c478bd9Sstevel@tonic-gate *last++ = c; 4257c478bd9Sstevel@tonic-gate current++; 4267c478bd9Sstevel@tonic-gate continue; 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate *last++ = '\\'; 4307c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 4317c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 4327c478bd9Sstevel@tonic-gate *last++ = c; 4337c478bd9Sstevel@tonic-gate current++; 4347c478bd9Sstevel@tonic-gate continue; 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate memcpy(last, current, len); 4377c478bd9Sstevel@tonic-gate last += len; current += len; 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate *last = 0; 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate unsigned char * 4447c478bd9Sstevel@tonic-gate mactrim(s) 4457c478bd9Sstevel@tonic-gate unsigned char *s; 4467c478bd9Sstevel@tonic-gate { 447965005c8Schin unsigned char *t = macro(s); 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate trim(t); 4507c478bd9Sstevel@tonic-gate return (t); 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate unsigned char ** 4547c478bd9Sstevel@tonic-gate scan(argn) 4557c478bd9Sstevel@tonic-gate int argn; 4567c478bd9Sstevel@tonic-gate { 457965005c8Schin struct argnod *argp = 4587c478bd9Sstevel@tonic-gate (struct argnod *)(Rcheat(gchain) & ~ARGMK); 459965005c8Schin unsigned char **comargn, **comargm; 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate comargn = (unsigned char **)getstak(BYTESPERWORD * argn + BYTESPERWORD); 4627c478bd9Sstevel@tonic-gate comargm = comargn += argn; 4637c478bd9Sstevel@tonic-gate *comargn = ENDARGS; 4647c478bd9Sstevel@tonic-gate while (argp) 4657c478bd9Sstevel@tonic-gate { 4667c478bd9Sstevel@tonic-gate *--comargn = argp->argval; 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate trim(*comargn); 4697c478bd9Sstevel@tonic-gate argp = argp->argnxt; 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate if (argp == 0 || Rcheat(argp) & ARGMK) 4727c478bd9Sstevel@tonic-gate { 4737c478bd9Sstevel@tonic-gate gsort(comargn, comargm); 4747c478bd9Sstevel@tonic-gate comargm = comargn; 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate argp = (struct argnod *)(Rcheat(argp) & ~ARGMK); 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate return (comargn); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 481965005c8Schin static void 4827c478bd9Sstevel@tonic-gate gsort(from, to) 4837c478bd9Sstevel@tonic-gate unsigned char *from[], *to[]; 4847c478bd9Sstevel@tonic-gate { 4857c478bd9Sstevel@tonic-gate int k, m, n; 486965005c8Schin int i, j; 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate if ((n = to - from) <= 1) 4897c478bd9Sstevel@tonic-gate return; 4907c478bd9Sstevel@tonic-gate for (j = 1; j <= n; j *= 2) 4917c478bd9Sstevel@tonic-gate ; 4927c478bd9Sstevel@tonic-gate for (m = 2 * j - 1; m /= 2; ) 4937c478bd9Sstevel@tonic-gate { 4947c478bd9Sstevel@tonic-gate k = n - m; 4957c478bd9Sstevel@tonic-gate for (j = 0; j < k; j++) 4967c478bd9Sstevel@tonic-gate { 4977c478bd9Sstevel@tonic-gate for (i = j; i >= 0; i -= m) 4987c478bd9Sstevel@tonic-gate { 499965005c8Schin unsigned char **fromi; 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate fromi = &from[i]; 5027c478bd9Sstevel@tonic-gate if (cf(fromi[m], fromi[0]) > 0) 5037c478bd9Sstevel@tonic-gate { 5047c478bd9Sstevel@tonic-gate break; 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate else 5077c478bd9Sstevel@tonic-gate { 5087c478bd9Sstevel@tonic-gate unsigned char *s; 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate s = fromi[m]; 5117c478bd9Sstevel@tonic-gate fromi[m] = fromi[0]; 5127c478bd9Sstevel@tonic-gate fromi[0] = s; 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate /* 5207c478bd9Sstevel@tonic-gate * Argument list generation 5217c478bd9Sstevel@tonic-gate */ 522965005c8Schin int 5237c478bd9Sstevel@tonic-gate getarg(ac) 5247c478bd9Sstevel@tonic-gate struct comnod *ac; 5257c478bd9Sstevel@tonic-gate { 526965005c8Schin struct argnod *argp; 527965005c8Schin int count = 0; 528965005c8Schin struct comnod *c; 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate if (c = ac) 5317c478bd9Sstevel@tonic-gate { 5327c478bd9Sstevel@tonic-gate argp = c->comarg; 5337c478bd9Sstevel@tonic-gate while (argp) 5347c478bd9Sstevel@tonic-gate { 5357c478bd9Sstevel@tonic-gate count += split(macro(argp->argval), 1); 5367c478bd9Sstevel@tonic-gate argp = argp->argnxt; 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate return (count); 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate static int 5437c478bd9Sstevel@tonic-gate split(s) /* blank interpretation routine */ 5447c478bd9Sstevel@tonic-gate unsigned char *s; 5457c478bd9Sstevel@tonic-gate { 546965005c8Schin unsigned char *argp; 547965005c8Schin int c; 5487c478bd9Sstevel@tonic-gate int count = 0; 5497c478bd9Sstevel@tonic-gate for (;;) 5507c478bd9Sstevel@tonic-gate { 551965005c8Schin int length; 5527c478bd9Sstevel@tonic-gate sigchk(); 5537c478bd9Sstevel@tonic-gate argp = locstak() + BYTESPERWORD; 5547c478bd9Sstevel@tonic-gate while (c = *s) { 5557c478bd9Sstevel@tonic-gate wchar_t wc; 5567c478bd9Sstevel@tonic-gate if ((length = mbtowc(&wc, (char *)s, 5577c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 5587c478bd9Sstevel@tonic-gate wc = (unsigned char)*s; 5597c478bd9Sstevel@tonic-gate length = 1; 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate if (c == '\\') { /* skip over quoted characters */ 5637c478bd9Sstevel@tonic-gate if (argp >= brkend) 5647c478bd9Sstevel@tonic-gate growstak(argp); 5657c478bd9Sstevel@tonic-gate *argp++ = c; 5667c478bd9Sstevel@tonic-gate s++; 5677c478bd9Sstevel@tonic-gate /* get rest of multibyte character */ 5687c478bd9Sstevel@tonic-gate if ((length = mbtowc(&wc, (char *)s, 5697c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 5707c478bd9Sstevel@tonic-gate wc = (unsigned char)*s; 5717c478bd9Sstevel@tonic-gate length = 1; 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate if (argp >= brkend) 5747c478bd9Sstevel@tonic-gate growstak(argp); 5757c478bd9Sstevel@tonic-gate *argp++ = *s++; 5767c478bd9Sstevel@tonic-gate while (--length > 0) { 5777c478bd9Sstevel@tonic-gate if (argp >= brkend) 5787c478bd9Sstevel@tonic-gate growstak(argp); 5797c478bd9Sstevel@tonic-gate *argp++ = *s++; 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate continue; 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate if (anys(s, ifsnod.namval)) { 5857c478bd9Sstevel@tonic-gate /* skip to next character position */ 5867c478bd9Sstevel@tonic-gate s += length; 5877c478bd9Sstevel@tonic-gate break; 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate if (argp >= brkend) 5917c478bd9Sstevel@tonic-gate growstak(argp); 5927c478bd9Sstevel@tonic-gate *argp++ = c; 5937c478bd9Sstevel@tonic-gate s++; 5947c478bd9Sstevel@tonic-gate while (--length > 0) { 5957c478bd9Sstevel@tonic-gate if (argp >= brkend) 5967c478bd9Sstevel@tonic-gate growstak(argp); 5977c478bd9Sstevel@tonic-gate *argp++ = *s++; 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate } 6007c478bd9Sstevel@tonic-gate if (argp == staktop + BYTESPERWORD) 6017c478bd9Sstevel@tonic-gate { 6027c478bd9Sstevel@tonic-gate if (c) 6037c478bd9Sstevel@tonic-gate { 6047c478bd9Sstevel@tonic-gate continue; 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate else 6077c478bd9Sstevel@tonic-gate { 6087c478bd9Sstevel@tonic-gate return (count); 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate /* 6127c478bd9Sstevel@tonic-gate * file name generation 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate argp = endstak(argp); 6167c478bd9Sstevel@tonic-gate trims(((struct argnod *)argp)->argval); 6177c478bd9Sstevel@tonic-gate if ((flags & nofngflg) == 0 && 6187c478bd9Sstevel@tonic-gate (c = expand(((struct argnod *)argp)->argval, 0))) 6197c478bd9Sstevel@tonic-gate count += c; 6207c478bd9Sstevel@tonic-gate else 6217c478bd9Sstevel@tonic-gate { 622965005c8Schin makearg((struct argnod *)argp); 6237c478bd9Sstevel@tonic-gate count++; 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate gchain = (struct argnod *)((int)gchain | ARGMK); 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate #ifdef ACCT 6307c478bd9Sstevel@tonic-gate #include <sys/types.h> 6317c478bd9Sstevel@tonic-gate #include <sys/acct.h> 6327c478bd9Sstevel@tonic-gate #include <sys/times.h> 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate struct acct sabuf; 6357c478bd9Sstevel@tonic-gate struct tms buffer; 6367c478bd9Sstevel@tonic-gate static clock_t before; 6377c478bd9Sstevel@tonic-gate static int shaccton; /* 0 implies do not write record on exit */ 6387c478bd9Sstevel@tonic-gate /* 1 implies write acct record on exit */ 639965005c8Schin static comp_t compress(clock_t); 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate /* 6437c478bd9Sstevel@tonic-gate * suspend accounting until turned on by preacct() 6447c478bd9Sstevel@tonic-gate */ 645965005c8Schin void 646965005c8Schin suspacct(void) 6477c478bd9Sstevel@tonic-gate { 6487c478bd9Sstevel@tonic-gate shaccton = 0; 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate 651965005c8Schin void 652965005c8Schin preacct(unsigned char *cmdadr) 6537c478bd9Sstevel@tonic-gate { 6547c478bd9Sstevel@tonic-gate unsigned char *simple(); 6557c478bd9Sstevel@tonic-gate 656db397771Schin if (acctnod.namval && *acctnod.namval) { 6577c478bd9Sstevel@tonic-gate sabuf.ac_btime = time((time_t *)0); 6587c478bd9Sstevel@tonic-gate before = times(&buffer); 6597c478bd9Sstevel@tonic-gate sabuf.ac_uid = getuid(); 6607c478bd9Sstevel@tonic-gate sabuf.ac_gid = getgid(); 6617c478bd9Sstevel@tonic-gate movstrn(simple(cmdadr), sabuf.ac_comm, sizeof (sabuf.ac_comm)); 6627c478bd9Sstevel@tonic-gate shaccton = 1; 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate 666965005c8Schin void 667965005c8Schin doacct(void) 6687c478bd9Sstevel@tonic-gate { 6697c478bd9Sstevel@tonic-gate int fd; 6707c478bd9Sstevel@tonic-gate clock_t after; 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate if (shaccton) { 6737c478bd9Sstevel@tonic-gate after = times(&buffer); 6747c478bd9Sstevel@tonic-gate sabuf.ac_utime = compress(buffer.tms_utime + buffer.tms_cutime); 6757c478bd9Sstevel@tonic-gate sabuf.ac_stime = compress(buffer.tms_stime + buffer.tms_cstime); 6767c478bd9Sstevel@tonic-gate sabuf.ac_etime = compress(after - before); 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate if ((fd = open((char *)acctnod.namval, 6797c478bd9Sstevel@tonic-gate O_WRONLY | O_APPEND | O_CREAT, 0666)) != -1) { 6807c478bd9Sstevel@tonic-gate write(fd, &sabuf, sizeof (sabuf)); 6817c478bd9Sstevel@tonic-gate close(fd); 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate /* 6877c478bd9Sstevel@tonic-gate * Produce a pseudo-floating point representation 6887c478bd9Sstevel@tonic-gate * with 3 bits base-8 exponent, 13 bits fraction 6897c478bd9Sstevel@tonic-gate */ 6907c478bd9Sstevel@tonic-gate 691965005c8Schin static comp_t 692965005c8Schin compress(clock_t t) 6937c478bd9Sstevel@tonic-gate { 694965005c8Schin int exp = 0; 695965005c8Schin int rund = 0; 6967c478bd9Sstevel@tonic-gate 697db397771Schin while (t >= 8192) { 6987c478bd9Sstevel@tonic-gate exp++; 6997c478bd9Sstevel@tonic-gate rund = t & 04; 7007c478bd9Sstevel@tonic-gate t >>= 3; 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate 703db397771Schin if (rund) { 7047c478bd9Sstevel@tonic-gate t++; 705db397771Schin if (t >= 8192) { 7067c478bd9Sstevel@tonic-gate t >>= 3; 7077c478bd9Sstevel@tonic-gate exp++; 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate return ((exp << 13) + t); 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate #endif 713