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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate /* 247c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 28*965005c8Schin /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29*965005c8Schin /* All Rights Reserved */ 30*965005c8Schin 31*965005c8Schin #pragma ident "%Z%%M% %I% %E% SMI" 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate /* 347c478bd9Sstevel@tonic-gate * UNIX shell 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #include "defs.h" 387c478bd9Sstevel@tonic-gate #include <errno.h> 397c478bd9Sstevel@tonic-gate #include <fcntl.h> 407c478bd9Sstevel@tonic-gate #include "sh_policy.h" 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #define ARGMK 01 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate static unsigned char *execs(); 45*965005c8Schin static void gsort(); 467c478bd9Sstevel@tonic-gate static int split(); 47*965005c8Schin extern void makearg(struct argnod *); 487c478bd9Sstevel@tonic-gate extern const char *sysmsg[]; 497c478bd9Sstevel@tonic-gate extern short topfd; 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate /* 537c478bd9Sstevel@tonic-gate * service routines for `execute' 547c478bd9Sstevel@tonic-gate */ 55*965005c8Schin short 56*965005c8Schin initio(struct ionod *iop, int save) 577c478bd9Sstevel@tonic-gate { 58*965005c8Schin unsigned char *ion; 59*965005c8Schin int iof, fd; 607c478bd9Sstevel@tonic-gate int ioufd; 617c478bd9Sstevel@tonic-gate short lastfd; 627c478bd9Sstevel@tonic-gate int newmode; 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate lastfd = topfd; 657c478bd9Sstevel@tonic-gate while (iop) { 667c478bd9Sstevel@tonic-gate iof = iop->iofile; 677c478bd9Sstevel@tonic-gate ion = mactrim(iop->ioname); 687c478bd9Sstevel@tonic-gate ioufd = iof & IOUFD; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate if (*ion && (flags&noexec) == 0) { 717c478bd9Sstevel@tonic-gate if (save) { 727c478bd9Sstevel@tonic-gate fdmap[topfd].org_fd = ioufd; 737c478bd9Sstevel@tonic-gate fdmap[topfd++].dup_fd = savefd(ioufd); 747c478bd9Sstevel@tonic-gate } 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate if (iof & IODOC) { 777c478bd9Sstevel@tonic-gate struct tempblk tb; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate subst(chkopen(ion, 0), (fd = tmpfil(&tb))); 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate /* 827c478bd9Sstevel@tonic-gate * pushed in tmpfil() -- 837c478bd9Sstevel@tonic-gate * bug fix for problem with 847c478bd9Sstevel@tonic-gate * in-line scripts 857c478bd9Sstevel@tonic-gate */ 867c478bd9Sstevel@tonic-gate poptemp(); 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate fd = chkopen(tmpout, 0); 897c478bd9Sstevel@tonic-gate unlink((const char *)tmpout); 907c478bd9Sstevel@tonic-gate } else if (iof & IOMOV) { 917c478bd9Sstevel@tonic-gate if (eq(minus, ion)) { 927c478bd9Sstevel@tonic-gate fd = -1; 937c478bd9Sstevel@tonic-gate close(ioufd); 947c478bd9Sstevel@tonic-gate } else if ((fd = stoi(ion)) >= USERIO) { 957c478bd9Sstevel@tonic-gate failed(ion, badfile); 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate else 987c478bd9Sstevel@tonic-gate fd = dup(fd); 997c478bd9Sstevel@tonic-gate } else if (((iof & IOPUT) == 0) && ((iof & IORDW) == 0)) 1007c478bd9Sstevel@tonic-gate fd = chkopen(ion, 0); 1017c478bd9Sstevel@tonic-gate else if (iof & IORDW) /* For <> */ { 1027c478bd9Sstevel@tonic-gate newmode = O_RDWR|O_CREAT; 1037c478bd9Sstevel@tonic-gate fd = chkopen(ion, newmode); 1047c478bd9Sstevel@tonic-gate } else if (flags & rshflg) { 1057c478bd9Sstevel@tonic-gate failed(ion, restricted); 1067c478bd9Sstevel@tonic-gate } else if (iof & IOAPP && 1077c478bd9Sstevel@tonic-gate (fd = open((char *)ion, 1)) >= 0) { 1087c478bd9Sstevel@tonic-gate lseek(fd, (off_t)0, SEEK_END); 1097c478bd9Sstevel@tonic-gate } else { 1107c478bd9Sstevel@tonic-gate fd = create(ion); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate if (fd >= 0) 1137c478bd9Sstevel@tonic-gate renamef(fd, ioufd); 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate iop = iop->ionxt; 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate return (lastfd); 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate unsigned char * 1227c478bd9Sstevel@tonic-gate simple(s) 1237c478bd9Sstevel@tonic-gate unsigned char *s; 1247c478bd9Sstevel@tonic-gate { 1257c478bd9Sstevel@tonic-gate unsigned char *sname; 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate sname = s; 1287c478bd9Sstevel@tonic-gate while (1) { 1297c478bd9Sstevel@tonic-gate if (any('/', sname)) 1307c478bd9Sstevel@tonic-gate while (*sname++ != '/') 1317c478bd9Sstevel@tonic-gate ; 1327c478bd9Sstevel@tonic-gate else 1337c478bd9Sstevel@tonic-gate return (sname); 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate unsigned char * 1387c478bd9Sstevel@tonic-gate getpath(s) 1397c478bd9Sstevel@tonic-gate unsigned char *s; 1407c478bd9Sstevel@tonic-gate { 141*965005c8Schin unsigned char *path, *newpath; 142*965005c8Schin int pathlen; 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate if (any('/', s)) 1457c478bd9Sstevel@tonic-gate { 1467c478bd9Sstevel@tonic-gate if (flags & rshflg) 1477c478bd9Sstevel@tonic-gate failed(s, restricted); 1487c478bd9Sstevel@tonic-gate else 1497c478bd9Sstevel@tonic-gate return ((unsigned char *)nullstr); 1507c478bd9Sstevel@tonic-gate } else if ((path = pathnod.namval) == 0) 1517c478bd9Sstevel@tonic-gate return ((unsigned char *)defpath); 1527c478bd9Sstevel@tonic-gate else { 1537c478bd9Sstevel@tonic-gate pathlen = length(path)-1; 1547c478bd9Sstevel@tonic-gate /* Add extra ':' if PATH variable ends in ':' */ 1557c478bd9Sstevel@tonic-gate if (pathlen > 2 && path[pathlen - 1] == ':' && 1567c478bd9Sstevel@tonic-gate path[pathlen - 2] != ':') { 1577c478bd9Sstevel@tonic-gate newpath = locstak(); 1587c478bd9Sstevel@tonic-gate (void) memcpystak(newpath, path, pathlen); 1597c478bd9Sstevel@tonic-gate newpath[pathlen] = ':'; 1607c478bd9Sstevel@tonic-gate endstak(newpath + pathlen + 1); 1617c478bd9Sstevel@tonic-gate return (newpath); 1627c478bd9Sstevel@tonic-gate } else 1637c478bd9Sstevel@tonic-gate return (cpystak(path)); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate 167*965005c8Schin int 168*965005c8Schin pathopen(unsigned char *path, unsigned char *name) 1697c478bd9Sstevel@tonic-gate { 170*965005c8Schin int f; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate do 1737c478bd9Sstevel@tonic-gate { 1747c478bd9Sstevel@tonic-gate path = catpath(path, name); 1757c478bd9Sstevel@tonic-gate } while ((f = open((char *)curstak(), 0)) < 0 && path); 1767c478bd9Sstevel@tonic-gate return (f); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate unsigned char * 180*965005c8Schin catpath(unsigned char *path, unsigned char *name) 1817c478bd9Sstevel@tonic-gate { 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * leaves result on top of stack 1847c478bd9Sstevel@tonic-gate */ 185*965005c8Schin unsigned char *scanp = path; 186*965005c8Schin unsigned char *argp = locstak(); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate while (*scanp && *scanp != COLON) 1897c478bd9Sstevel@tonic-gate { 1907c478bd9Sstevel@tonic-gate if (argp >= brkend) 1917c478bd9Sstevel@tonic-gate growstak(argp); 1927c478bd9Sstevel@tonic-gate *argp++ = *scanp++; 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate if (scanp != path) 1957c478bd9Sstevel@tonic-gate { 1967c478bd9Sstevel@tonic-gate if (argp >= brkend) 1977c478bd9Sstevel@tonic-gate growstak(argp); 1987c478bd9Sstevel@tonic-gate *argp++ = '/'; 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate if (*scanp == COLON) 2017c478bd9Sstevel@tonic-gate scanp++; 2027c478bd9Sstevel@tonic-gate path = (*scanp ? scanp : 0); 2037c478bd9Sstevel@tonic-gate scanp = name; 2047c478bd9Sstevel@tonic-gate do 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate if (argp >= brkend) 2077c478bd9Sstevel@tonic-gate growstak(argp); 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate while (*argp++ = *scanp++); 2107c478bd9Sstevel@tonic-gate return (path); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate unsigned char * 214*965005c8Schin nextpath(unsigned char *path) 2157c478bd9Sstevel@tonic-gate { 216*965005c8Schin unsigned char *scanp = path; 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate while (*scanp && *scanp != COLON) 2197c478bd9Sstevel@tonic-gate scanp++; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate if (*scanp == COLON) 2227c478bd9Sstevel@tonic-gate scanp++; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate return (*scanp ? scanp : 0); 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate 227*965005c8Schin static const char *xecmsg; 2287c478bd9Sstevel@tonic-gate static unsigned char **xecenv; 2297c478bd9Sstevel@tonic-gate 230*965005c8Schin void 231*965005c8Schin execa(unsigned char *at[], short pos) 2327c478bd9Sstevel@tonic-gate { 233*965005c8Schin unsigned char *path; 234*965005c8Schin unsigned char **t = at; 2357c478bd9Sstevel@tonic-gate int cnt; 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate if ((flags & noexec) == 0) 2387c478bd9Sstevel@tonic-gate { 239*965005c8Schin xecmsg = notfound; 2407c478bd9Sstevel@tonic-gate path = getpath(*t); 2417c478bd9Sstevel@tonic-gate xecenv = local_setenv(); 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate if (pos > 0) 2447c478bd9Sstevel@tonic-gate { 2457c478bd9Sstevel@tonic-gate cnt = 1; 2467c478bd9Sstevel@tonic-gate while (cnt != pos) 2477c478bd9Sstevel@tonic-gate { 2487c478bd9Sstevel@tonic-gate ++cnt; 2497c478bd9Sstevel@tonic-gate path = nextpath(path); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate execs(path, t); 2527c478bd9Sstevel@tonic-gate path = getpath(*t); 2537c478bd9Sstevel@tonic-gate } 2547c478bd9Sstevel@tonic-gate while (path = execs(path, t)) 2557c478bd9Sstevel@tonic-gate ; 2567c478bd9Sstevel@tonic-gate failed(*t, xecmsg); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate static unsigned char * 261*965005c8Schin execs(unsigned char *ap, unsigned char *t[]) 2627c478bd9Sstevel@tonic-gate { 263*965005c8Schin int pfstatus = NOATTRS; 264*965005c8Schin unsigned char *p, *prefix; 2657c478bd9Sstevel@tonic-gate unsigned char *savptr; 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate prefix = catpath(ap, t[0]); 2687c478bd9Sstevel@tonic-gate trim(p = curstak()); 2697c478bd9Sstevel@tonic-gate sigchk(); 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate if (flags & pfshflg) { 2727c478bd9Sstevel@tonic-gate /* 2737c478bd9Sstevel@tonic-gate * Need to save the stack information, or the 2747c478bd9Sstevel@tonic-gate * first memory allocation in secpolicy_profile_lookup() 2757c478bd9Sstevel@tonic-gate * will clobber it. 2767c478bd9Sstevel@tonic-gate */ 2777c478bd9Sstevel@tonic-gate savptr = endstak(p + strlen((const char *)p) + 1); 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate pfstatus = secpolicy_pfexec((const char *)p, 2807c478bd9Sstevel@tonic-gate (char **)t, (const char **)xecenv); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate if (pfstatus != NOATTRS) { 2837c478bd9Sstevel@tonic-gate errno = pfstatus; 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate tdystak(savptr); 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate if (pfstatus == NOATTRS) { 2907c478bd9Sstevel@tonic-gate execve((const char *)p, (char *const *)&t[0], 2917c478bd9Sstevel@tonic-gate (char *const *)xecenv); 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate switch (errno) 2957c478bd9Sstevel@tonic-gate { 2967c478bd9Sstevel@tonic-gate case ENOEXEC: /* could be a shell script */ 2977c478bd9Sstevel@tonic-gate funcnt = 0; 2987c478bd9Sstevel@tonic-gate flags = 0; 2997c478bd9Sstevel@tonic-gate *flagadr = 0; 3007c478bd9Sstevel@tonic-gate comdiv = 0; 3017c478bd9Sstevel@tonic-gate ioset = 0; 3027c478bd9Sstevel@tonic-gate clearup(); /* remove open files and for loop junk */ 3037c478bd9Sstevel@tonic-gate if (input) 3047c478bd9Sstevel@tonic-gate close(input); 3057c478bd9Sstevel@tonic-gate input = chkopen(p, 0); 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate #ifdef ACCT 3087c478bd9Sstevel@tonic-gate preacct(p); /* reset accounting */ 3097c478bd9Sstevel@tonic-gate #endif 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate /* 3127c478bd9Sstevel@tonic-gate * set up new args 3137c478bd9Sstevel@tonic-gate */ 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate setargs(t); 3167c478bd9Sstevel@tonic-gate longjmp(subshell, 1); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate case ENOMEM: 3197c478bd9Sstevel@tonic-gate failed(p, toobig); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate case E2BIG: 3227c478bd9Sstevel@tonic-gate failed(p, arglist); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate case ETXTBSY: 3257c478bd9Sstevel@tonic-gate failed(p, txtbsy); 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate case ELIBACC: 3287c478bd9Sstevel@tonic-gate failed(p, libacc); 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate case ELIBBAD: 3317c478bd9Sstevel@tonic-gate failed(p, libbad); 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate case ELIBSCN: 3347c478bd9Sstevel@tonic-gate failed(p, libscn); 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate case ELIBMAX: 3377c478bd9Sstevel@tonic-gate failed(p, libmax); 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate default: 340*965005c8Schin xecmsg = badexec; 3417c478bd9Sstevel@tonic-gate case ENOENT: 3427c478bd9Sstevel@tonic-gate return (prefix); 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate BOOL nosubst; 3477c478bd9Sstevel@tonic-gate 348*965005c8Schin void 349*965005c8Schin trim(unsigned char *at) 3507c478bd9Sstevel@tonic-gate { 351*965005c8Schin unsigned char *last; 352*965005c8Schin unsigned char *current; 353*965005c8Schin unsigned char c; 3547c478bd9Sstevel@tonic-gate int len; 3557c478bd9Sstevel@tonic-gate wchar_t wc; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate nosubst = 0; 3587c478bd9Sstevel@tonic-gate if (current = at) 3597c478bd9Sstevel@tonic-gate { 3607c478bd9Sstevel@tonic-gate last = at; 3617c478bd9Sstevel@tonic-gate while (c = *current) { 3627c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 3637c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 3647c478bd9Sstevel@tonic-gate *last++ = c; 3657c478bd9Sstevel@tonic-gate current++; 3667c478bd9Sstevel@tonic-gate continue; 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate if (wc != '\\') { 3707c478bd9Sstevel@tonic-gate memcpy(last, current, len); 3717c478bd9Sstevel@tonic-gate last += len; 3727c478bd9Sstevel@tonic-gate current += len; 3737c478bd9Sstevel@tonic-gate continue; 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate /* remove \ and quoted nulls */ 3777c478bd9Sstevel@tonic-gate nosubst = 1; 3787c478bd9Sstevel@tonic-gate current++; 3797c478bd9Sstevel@tonic-gate if (c = *current) { 3807c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 3817c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 3827c478bd9Sstevel@tonic-gate *last++ = c; 3837c478bd9Sstevel@tonic-gate current++; 3847c478bd9Sstevel@tonic-gate continue; 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate memcpy(last, current, len); 3877c478bd9Sstevel@tonic-gate last += len; 3887c478bd9Sstevel@tonic-gate current += len; 3897c478bd9Sstevel@tonic-gate } else 3907c478bd9Sstevel@tonic-gate current++; 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate *last = 0; 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate /* Same as trim, but only removes backlashes before slashes */ 398*965005c8Schin void 3997c478bd9Sstevel@tonic-gate trims(at) 4007c478bd9Sstevel@tonic-gate unsigned char *at; 4017c478bd9Sstevel@tonic-gate { 402*965005c8Schin unsigned char *last; 403*965005c8Schin unsigned char *current; 404*965005c8Schin unsigned char c; 4057c478bd9Sstevel@tonic-gate int len; 4067c478bd9Sstevel@tonic-gate wchar_t wc; 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate if (current = at) 4097c478bd9Sstevel@tonic-gate { 4107c478bd9Sstevel@tonic-gate last = at; 4117c478bd9Sstevel@tonic-gate while (c = *current) { 4127c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 4137c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 4147c478bd9Sstevel@tonic-gate *last++ = c; 4157c478bd9Sstevel@tonic-gate current++; 4167c478bd9Sstevel@tonic-gate continue; 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate if (wc != '\\') { 4207c478bd9Sstevel@tonic-gate memcpy(last, current, len); 4217c478bd9Sstevel@tonic-gate last += len; current += len; 4227c478bd9Sstevel@tonic-gate continue; 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate /* remove \ and quoted nulls */ 4267c478bd9Sstevel@tonic-gate current++; 4277c478bd9Sstevel@tonic-gate if (!(c = *current)) { 4287c478bd9Sstevel@tonic-gate current++; 4297c478bd9Sstevel@tonic-gate continue; 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate if (c == '/') { 4337c478bd9Sstevel@tonic-gate *last++ = c; 4347c478bd9Sstevel@tonic-gate current++; 4357c478bd9Sstevel@tonic-gate continue; 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate *last++ = '\\'; 4397c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 4407c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 4417c478bd9Sstevel@tonic-gate *last++ = c; 4427c478bd9Sstevel@tonic-gate current++; 4437c478bd9Sstevel@tonic-gate continue; 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate memcpy(last, current, len); 4467c478bd9Sstevel@tonic-gate last += len; current += len; 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate *last = 0; 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate unsigned char * 4537c478bd9Sstevel@tonic-gate mactrim(s) 4547c478bd9Sstevel@tonic-gate unsigned char *s; 4557c478bd9Sstevel@tonic-gate { 456*965005c8Schin unsigned char *t = macro(s); 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate trim(t); 4597c478bd9Sstevel@tonic-gate return (t); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate unsigned char ** 4637c478bd9Sstevel@tonic-gate scan(argn) 4647c478bd9Sstevel@tonic-gate int argn; 4657c478bd9Sstevel@tonic-gate { 466*965005c8Schin struct argnod *argp = 4677c478bd9Sstevel@tonic-gate (struct argnod *)(Rcheat(gchain) & ~ARGMK); 468*965005c8Schin unsigned char **comargn, **comargm; 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate comargn = (unsigned char **)getstak(BYTESPERWORD * argn + BYTESPERWORD); 4717c478bd9Sstevel@tonic-gate comargm = comargn += argn; 4727c478bd9Sstevel@tonic-gate *comargn = ENDARGS; 4737c478bd9Sstevel@tonic-gate while (argp) 4747c478bd9Sstevel@tonic-gate { 4757c478bd9Sstevel@tonic-gate *--comargn = argp->argval; 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate trim(*comargn); 4787c478bd9Sstevel@tonic-gate argp = argp->argnxt; 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate if (argp == 0 || Rcheat(argp) & ARGMK) 4817c478bd9Sstevel@tonic-gate { 4827c478bd9Sstevel@tonic-gate gsort(comargn, comargm); 4837c478bd9Sstevel@tonic-gate comargm = comargn; 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate argp = (struct argnod *)(Rcheat(argp) & ~ARGMK); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate return (comargn); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 490*965005c8Schin static void 4917c478bd9Sstevel@tonic-gate gsort(from, to) 4927c478bd9Sstevel@tonic-gate unsigned char *from[], *to[]; 4937c478bd9Sstevel@tonic-gate { 4947c478bd9Sstevel@tonic-gate int k, m, n; 495*965005c8Schin int i, j; 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate if ((n = to - from) <= 1) 4987c478bd9Sstevel@tonic-gate return; 4997c478bd9Sstevel@tonic-gate for (j = 1; j <= n; j *= 2) 5007c478bd9Sstevel@tonic-gate ; 5017c478bd9Sstevel@tonic-gate for (m = 2 * j - 1; m /= 2; ) 5027c478bd9Sstevel@tonic-gate { 5037c478bd9Sstevel@tonic-gate k = n - m; 5047c478bd9Sstevel@tonic-gate for (j = 0; j < k; j++) 5057c478bd9Sstevel@tonic-gate { 5067c478bd9Sstevel@tonic-gate for (i = j; i >= 0; i -= m) 5077c478bd9Sstevel@tonic-gate { 508*965005c8Schin unsigned char **fromi; 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate fromi = &from[i]; 5117c478bd9Sstevel@tonic-gate if (cf(fromi[m], fromi[0]) > 0) 5127c478bd9Sstevel@tonic-gate { 5137c478bd9Sstevel@tonic-gate break; 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate else 5167c478bd9Sstevel@tonic-gate { 5177c478bd9Sstevel@tonic-gate unsigned char *s; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate s = fromi[m]; 5207c478bd9Sstevel@tonic-gate fromi[m] = fromi[0]; 5217c478bd9Sstevel@tonic-gate fromi[0] = s; 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate /* 5297c478bd9Sstevel@tonic-gate * Argument list generation 5307c478bd9Sstevel@tonic-gate */ 531*965005c8Schin int 5327c478bd9Sstevel@tonic-gate getarg(ac) 5337c478bd9Sstevel@tonic-gate struct comnod *ac; 5347c478bd9Sstevel@tonic-gate { 535*965005c8Schin struct argnod *argp; 536*965005c8Schin int count = 0; 537*965005c8Schin struct comnod *c; 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate if (c = ac) 5407c478bd9Sstevel@tonic-gate { 5417c478bd9Sstevel@tonic-gate argp = c->comarg; 5427c478bd9Sstevel@tonic-gate while (argp) 5437c478bd9Sstevel@tonic-gate { 5447c478bd9Sstevel@tonic-gate count += split(macro(argp->argval), 1); 5457c478bd9Sstevel@tonic-gate argp = argp->argnxt; 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate return (count); 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate static int 5527c478bd9Sstevel@tonic-gate split(s) /* blank interpretation routine */ 5537c478bd9Sstevel@tonic-gate unsigned char *s; 5547c478bd9Sstevel@tonic-gate { 555*965005c8Schin unsigned char *argp; 556*965005c8Schin int c; 5577c478bd9Sstevel@tonic-gate int count = 0; 5587c478bd9Sstevel@tonic-gate for (;;) 5597c478bd9Sstevel@tonic-gate { 560*965005c8Schin int length; 5617c478bd9Sstevel@tonic-gate sigchk(); 5627c478bd9Sstevel@tonic-gate argp = locstak() + BYTESPERWORD; 5637c478bd9Sstevel@tonic-gate while (c = *s) { 5647c478bd9Sstevel@tonic-gate wchar_t wc; 5657c478bd9Sstevel@tonic-gate if ((length = mbtowc(&wc, (char *)s, 5667c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 5677c478bd9Sstevel@tonic-gate wc = (unsigned char)*s; 5687c478bd9Sstevel@tonic-gate length = 1; 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate if (c == '\\') { /* skip over quoted characters */ 5727c478bd9Sstevel@tonic-gate if (argp >= brkend) 5737c478bd9Sstevel@tonic-gate growstak(argp); 5747c478bd9Sstevel@tonic-gate *argp++ = c; 5757c478bd9Sstevel@tonic-gate s++; 5767c478bd9Sstevel@tonic-gate /* get rest of multibyte character */ 5777c478bd9Sstevel@tonic-gate if ((length = mbtowc(&wc, (char *)s, 5787c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 5797c478bd9Sstevel@tonic-gate wc = (unsigned char)*s; 5807c478bd9Sstevel@tonic-gate length = 1; 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate if (argp >= brkend) 5837c478bd9Sstevel@tonic-gate growstak(argp); 5847c478bd9Sstevel@tonic-gate *argp++ = *s++; 5857c478bd9Sstevel@tonic-gate while (--length > 0) { 5867c478bd9Sstevel@tonic-gate if (argp >= brkend) 5877c478bd9Sstevel@tonic-gate growstak(argp); 5887c478bd9Sstevel@tonic-gate *argp++ = *s++; 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate continue; 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate if (anys(s, ifsnod.namval)) { 5947c478bd9Sstevel@tonic-gate /* skip to next character position */ 5957c478bd9Sstevel@tonic-gate s += length; 5967c478bd9Sstevel@tonic-gate break; 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate if (argp >= brkend) 6007c478bd9Sstevel@tonic-gate growstak(argp); 6017c478bd9Sstevel@tonic-gate *argp++ = c; 6027c478bd9Sstevel@tonic-gate s++; 6037c478bd9Sstevel@tonic-gate while (--length > 0) { 6047c478bd9Sstevel@tonic-gate if (argp >= brkend) 6057c478bd9Sstevel@tonic-gate growstak(argp); 6067c478bd9Sstevel@tonic-gate *argp++ = *s++; 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate if (argp == staktop + BYTESPERWORD) 6107c478bd9Sstevel@tonic-gate { 6117c478bd9Sstevel@tonic-gate if (c) 6127c478bd9Sstevel@tonic-gate { 6137c478bd9Sstevel@tonic-gate continue; 6147c478bd9Sstevel@tonic-gate } 6157c478bd9Sstevel@tonic-gate else 6167c478bd9Sstevel@tonic-gate { 6177c478bd9Sstevel@tonic-gate return (count); 6187c478bd9Sstevel@tonic-gate } 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate /* 6217c478bd9Sstevel@tonic-gate * file name generation 6227c478bd9Sstevel@tonic-gate */ 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate argp = endstak(argp); 6257c478bd9Sstevel@tonic-gate trims(((struct argnod *)argp)->argval); 6267c478bd9Sstevel@tonic-gate if ((flags & nofngflg) == 0 && 6277c478bd9Sstevel@tonic-gate (c = expand(((struct argnod *)argp)->argval, 0))) 6287c478bd9Sstevel@tonic-gate count += c; 6297c478bd9Sstevel@tonic-gate else 6307c478bd9Sstevel@tonic-gate { 631*965005c8Schin makearg((struct argnod *)argp); 6327c478bd9Sstevel@tonic-gate count++; 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate gchain = (struct argnod *)((int)gchain | ARGMK); 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate #ifdef ACCT 6397c478bd9Sstevel@tonic-gate #include <sys/types.h> 6407c478bd9Sstevel@tonic-gate #include <sys/acct.h> 6417c478bd9Sstevel@tonic-gate #include <sys/times.h> 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate struct acct sabuf; 6447c478bd9Sstevel@tonic-gate struct tms buffer; 6457c478bd9Sstevel@tonic-gate static clock_t before; 6467c478bd9Sstevel@tonic-gate static int shaccton; /* 0 implies do not write record on exit */ 6477c478bd9Sstevel@tonic-gate /* 1 implies write acct record on exit */ 648*965005c8Schin static comp_t compress(clock_t); 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate /* 6527c478bd9Sstevel@tonic-gate * suspend accounting until turned on by preacct() 6537c478bd9Sstevel@tonic-gate */ 654*965005c8Schin void 655*965005c8Schin suspacct(void) 6567c478bd9Sstevel@tonic-gate { 6577c478bd9Sstevel@tonic-gate shaccton = 0; 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate 660*965005c8Schin void 661*965005c8Schin preacct(unsigned char *cmdadr) 6627c478bd9Sstevel@tonic-gate { 6637c478bd9Sstevel@tonic-gate unsigned char *simple(); 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate if (acctnod.namval && *acctnod.namval) 6667c478bd9Sstevel@tonic-gate { 6677c478bd9Sstevel@tonic-gate sabuf.ac_btime = time((time_t *)0); 6687c478bd9Sstevel@tonic-gate before = times(&buffer); 6697c478bd9Sstevel@tonic-gate sabuf.ac_uid = getuid(); 6707c478bd9Sstevel@tonic-gate sabuf.ac_gid = getgid(); 6717c478bd9Sstevel@tonic-gate movstrn(simple(cmdadr), sabuf.ac_comm, sizeof (sabuf.ac_comm)); 6727c478bd9Sstevel@tonic-gate shaccton = 1; 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate 676*965005c8Schin void 677*965005c8Schin doacct(void) 6787c478bd9Sstevel@tonic-gate { 6797c478bd9Sstevel@tonic-gate int fd; 6807c478bd9Sstevel@tonic-gate clock_t after; 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate if (shaccton) { 6837c478bd9Sstevel@tonic-gate after = times(&buffer); 6847c478bd9Sstevel@tonic-gate sabuf.ac_utime = compress(buffer.tms_utime + buffer.tms_cutime); 6857c478bd9Sstevel@tonic-gate sabuf.ac_stime = compress(buffer.tms_stime + buffer.tms_cstime); 6867c478bd9Sstevel@tonic-gate sabuf.ac_etime = compress(after - before); 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate if ((fd = open((char *)acctnod.namval, 6897c478bd9Sstevel@tonic-gate O_WRONLY | O_APPEND | O_CREAT, 0666)) != -1) { 6907c478bd9Sstevel@tonic-gate write(fd, &sabuf, sizeof (sabuf)); 6917c478bd9Sstevel@tonic-gate close(fd); 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate /* 6977c478bd9Sstevel@tonic-gate * Produce a pseudo-floating point representation 6987c478bd9Sstevel@tonic-gate * with 3 bits base-8 exponent, 13 bits fraction 6997c478bd9Sstevel@tonic-gate */ 7007c478bd9Sstevel@tonic-gate 701*965005c8Schin static comp_t 702*965005c8Schin compress(clock_t t) 7037c478bd9Sstevel@tonic-gate { 704*965005c8Schin int exp = 0; 705*965005c8Schin int rund = 0; 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate while (t >= 8192) 7087c478bd9Sstevel@tonic-gate { 7097c478bd9Sstevel@tonic-gate exp++; 7107c478bd9Sstevel@tonic-gate rund = t & 04; 7117c478bd9Sstevel@tonic-gate t >>= 3; 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate if (rund) 7157c478bd9Sstevel@tonic-gate { 7167c478bd9Sstevel@tonic-gate t++; 7177c478bd9Sstevel@tonic-gate if (t >= 8192) 7187c478bd9Sstevel@tonic-gate { 7197c478bd9Sstevel@tonic-gate t >>= 3; 7207c478bd9Sstevel@tonic-gate exp++; 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate } 7237c478bd9Sstevel@tonic-gate return ((exp << 13) + t); 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate #endif 726