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 28965005c8Schin /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29965005c8Schin /* All Rights Reserved */ 30965005c8Schin 31965005c8Schin #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(); 45965005c8Schin static void gsort(); 467c478bd9Sstevel@tonic-gate static int split(); 47965005c8Schin 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 */ 55965005c8Schin short 56965005c8Schin initio(struct ionod *iop, int save) 577c478bd9Sstevel@tonic-gate { 58965005c8Schin unsigned char *ion; 59965005c8Schin 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 { 141965005c8Schin unsigned char *path, *newpath; 142965005c8Schin 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 167965005c8Schin int 168965005c8Schin pathopen(unsigned char *path, unsigned char *name) 1697c478bd9Sstevel@tonic-gate { 170965005c8Schin 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 * 180965005c8Schin 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 */ 185965005c8Schin unsigned char *scanp = path; 186965005c8Schin unsigned char *argp = locstak(); 1877c478bd9Sstevel@tonic-gate 188*db397771Schin while (*scanp && *scanp != COLON) { 1897c478bd9Sstevel@tonic-gate if (argp >= brkend) 1907c478bd9Sstevel@tonic-gate growstak(argp); 1917c478bd9Sstevel@tonic-gate *argp++ = *scanp++; 1927c478bd9Sstevel@tonic-gate } 193*db397771Schin if (scanp != path) { 1947c478bd9Sstevel@tonic-gate if (argp >= brkend) 1957c478bd9Sstevel@tonic-gate growstak(argp); 1967c478bd9Sstevel@tonic-gate *argp++ = '/'; 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate if (*scanp == COLON) 1997c478bd9Sstevel@tonic-gate scanp++; 2007c478bd9Sstevel@tonic-gate path = (*scanp ? scanp : 0); 2017c478bd9Sstevel@tonic-gate scanp = name; 2027c478bd9Sstevel@tonic-gate do 2037c478bd9Sstevel@tonic-gate { 2047c478bd9Sstevel@tonic-gate if (argp >= brkend) 2057c478bd9Sstevel@tonic-gate growstak(argp); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate while (*argp++ = *scanp++); 2087c478bd9Sstevel@tonic-gate return (path); 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate unsigned char * 212965005c8Schin nextpath(unsigned char *path) 2137c478bd9Sstevel@tonic-gate { 214965005c8Schin unsigned char *scanp = path; 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate while (*scanp && *scanp != COLON) 2177c478bd9Sstevel@tonic-gate scanp++; 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate if (*scanp == COLON) 2207c478bd9Sstevel@tonic-gate scanp++; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate return (*scanp ? scanp : 0); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 225965005c8Schin static const char *xecmsg; 2267c478bd9Sstevel@tonic-gate static unsigned char **xecenv; 2277c478bd9Sstevel@tonic-gate 228965005c8Schin void 229965005c8Schin execa(unsigned char *at[], short pos) 2307c478bd9Sstevel@tonic-gate { 231965005c8Schin unsigned char *path; 232965005c8Schin unsigned char **t = at; 2337c478bd9Sstevel@tonic-gate int cnt; 2347c478bd9Sstevel@tonic-gate 235*db397771Schin if ((flags & noexec) == 0) { 236965005c8Schin xecmsg = notfound; 2377c478bd9Sstevel@tonic-gate path = getpath(*t); 2387c478bd9Sstevel@tonic-gate xecenv = local_setenv(); 2397c478bd9Sstevel@tonic-gate 240*db397771Schin if (pos > 0) { 2417c478bd9Sstevel@tonic-gate cnt = 1; 242*db397771Schin while (cnt != pos) { 2437c478bd9Sstevel@tonic-gate ++cnt; 2447c478bd9Sstevel@tonic-gate path = nextpath(path); 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate execs(path, t); 2477c478bd9Sstevel@tonic-gate path = getpath(*t); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate while (path = execs(path, t)) 2507c478bd9Sstevel@tonic-gate ; 2517c478bd9Sstevel@tonic-gate failed(*t, xecmsg); 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate } 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate static unsigned char * 256965005c8Schin execs(unsigned char *ap, unsigned char *t[]) 2577c478bd9Sstevel@tonic-gate { 258965005c8Schin int pfstatus = NOATTRS; 259965005c8Schin unsigned char *p, *prefix; 2607c478bd9Sstevel@tonic-gate unsigned char *savptr; 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate prefix = catpath(ap, t[0]); 2637c478bd9Sstevel@tonic-gate trim(p = curstak()); 2647c478bd9Sstevel@tonic-gate sigchk(); 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate if (flags & pfshflg) { 2677c478bd9Sstevel@tonic-gate /* 2687c478bd9Sstevel@tonic-gate * Need to save the stack information, or the 2697c478bd9Sstevel@tonic-gate * first memory allocation in secpolicy_profile_lookup() 2707c478bd9Sstevel@tonic-gate * will clobber it. 2717c478bd9Sstevel@tonic-gate */ 2727c478bd9Sstevel@tonic-gate savptr = endstak(p + strlen((const char *)p) + 1); 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate pfstatus = secpolicy_pfexec((const char *)p, 2757c478bd9Sstevel@tonic-gate (char **)t, (const char **)xecenv); 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate if (pfstatus != NOATTRS) { 2787c478bd9Sstevel@tonic-gate errno = pfstatus; 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate tdystak(savptr); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate if (pfstatus == NOATTRS) { 2857c478bd9Sstevel@tonic-gate execve((const char *)p, (char *const *)&t[0], 2867c478bd9Sstevel@tonic-gate (char *const *)xecenv); 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 289*db397771Schin switch (errno) { 2907c478bd9Sstevel@tonic-gate case ENOEXEC: /* could be a shell script */ 2917c478bd9Sstevel@tonic-gate funcnt = 0; 2927c478bd9Sstevel@tonic-gate flags = 0; 2937c478bd9Sstevel@tonic-gate *flagadr = 0; 2947c478bd9Sstevel@tonic-gate comdiv = 0; 2957c478bd9Sstevel@tonic-gate ioset = 0; 2967c478bd9Sstevel@tonic-gate clearup(); /* remove open files and for loop junk */ 2977c478bd9Sstevel@tonic-gate if (input) 2987c478bd9Sstevel@tonic-gate close(input); 2997c478bd9Sstevel@tonic-gate input = chkopen(p, 0); 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate #ifdef ACCT 3027c478bd9Sstevel@tonic-gate preacct(p); /* reset accounting */ 3037c478bd9Sstevel@tonic-gate #endif 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate /* 3067c478bd9Sstevel@tonic-gate * set up new args 3077c478bd9Sstevel@tonic-gate */ 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate setargs(t); 3107c478bd9Sstevel@tonic-gate longjmp(subshell, 1); 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate case ENOMEM: 3137c478bd9Sstevel@tonic-gate failed(p, toobig); 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate case E2BIG: 3167c478bd9Sstevel@tonic-gate failed(p, arglist); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate case ETXTBSY: 3197c478bd9Sstevel@tonic-gate failed(p, txtbsy); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate case ELIBACC: 3227c478bd9Sstevel@tonic-gate failed(p, libacc); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate case ELIBBAD: 3257c478bd9Sstevel@tonic-gate failed(p, libbad); 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate case ELIBSCN: 3287c478bd9Sstevel@tonic-gate failed(p, libscn); 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate case ELIBMAX: 3317c478bd9Sstevel@tonic-gate failed(p, libmax); 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate default: 334965005c8Schin xecmsg = badexec; 3357c478bd9Sstevel@tonic-gate case ENOENT: 3367c478bd9Sstevel@tonic-gate return (prefix); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate BOOL nosubst; 3417c478bd9Sstevel@tonic-gate 342965005c8Schin void 343965005c8Schin trim(unsigned char *at) 3447c478bd9Sstevel@tonic-gate { 345965005c8Schin unsigned char *last; 346965005c8Schin unsigned char *current; 347965005c8Schin unsigned char c; 3487c478bd9Sstevel@tonic-gate int len; 3497c478bd9Sstevel@tonic-gate wchar_t wc; 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate nosubst = 0; 352*db397771Schin if (current = at) { 3537c478bd9Sstevel@tonic-gate last = at; 3547c478bd9Sstevel@tonic-gate while (c = *current) { 3557c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 3567c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 3577c478bd9Sstevel@tonic-gate *last++ = c; 3587c478bd9Sstevel@tonic-gate current++; 3597c478bd9Sstevel@tonic-gate continue; 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate if (wc != '\\') { 3637c478bd9Sstevel@tonic-gate memcpy(last, current, len); 3647c478bd9Sstevel@tonic-gate last += len; 3657c478bd9Sstevel@tonic-gate current += len; 3667c478bd9Sstevel@tonic-gate continue; 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate /* remove \ and quoted nulls */ 3707c478bd9Sstevel@tonic-gate nosubst = 1; 3717c478bd9Sstevel@tonic-gate current++; 3727c478bd9Sstevel@tonic-gate if (c = *current) { 3737c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 3747c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 3757c478bd9Sstevel@tonic-gate *last++ = c; 3767c478bd9Sstevel@tonic-gate current++; 3777c478bd9Sstevel@tonic-gate continue; 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate memcpy(last, current, len); 3807c478bd9Sstevel@tonic-gate last += len; 3817c478bd9Sstevel@tonic-gate current += len; 3827c478bd9Sstevel@tonic-gate } else 3837c478bd9Sstevel@tonic-gate current++; 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate *last = 0; 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate /* Same as trim, but only removes backlashes before slashes */ 391965005c8Schin void 3927c478bd9Sstevel@tonic-gate trims(at) 3937c478bd9Sstevel@tonic-gate unsigned char *at; 3947c478bd9Sstevel@tonic-gate { 395965005c8Schin unsigned char *last; 396965005c8Schin unsigned char *current; 397965005c8Schin unsigned char c; 3987c478bd9Sstevel@tonic-gate int len; 3997c478bd9Sstevel@tonic-gate wchar_t wc; 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate if (current = at) 4027c478bd9Sstevel@tonic-gate { 4037c478bd9Sstevel@tonic-gate last = at; 4047c478bd9Sstevel@tonic-gate while (c = *current) { 4057c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 4067c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 4077c478bd9Sstevel@tonic-gate *last++ = c; 4087c478bd9Sstevel@tonic-gate current++; 4097c478bd9Sstevel@tonic-gate continue; 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate if (wc != '\\') { 4137c478bd9Sstevel@tonic-gate memcpy(last, current, len); 4147c478bd9Sstevel@tonic-gate last += len; current += len; 4157c478bd9Sstevel@tonic-gate continue; 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate /* remove \ and quoted nulls */ 4197c478bd9Sstevel@tonic-gate current++; 4207c478bd9Sstevel@tonic-gate if (!(c = *current)) { 4217c478bd9Sstevel@tonic-gate current++; 4227c478bd9Sstevel@tonic-gate continue; 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate if (c == '/') { 4267c478bd9Sstevel@tonic-gate *last++ = c; 4277c478bd9Sstevel@tonic-gate current++; 4287c478bd9Sstevel@tonic-gate continue; 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate *last++ = '\\'; 4327c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 4337c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 4347c478bd9Sstevel@tonic-gate *last++ = c; 4357c478bd9Sstevel@tonic-gate current++; 4367c478bd9Sstevel@tonic-gate continue; 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate memcpy(last, current, len); 4397c478bd9Sstevel@tonic-gate last += len; current += len; 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate *last = 0; 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate unsigned char * 4467c478bd9Sstevel@tonic-gate mactrim(s) 4477c478bd9Sstevel@tonic-gate unsigned char *s; 4487c478bd9Sstevel@tonic-gate { 449965005c8Schin unsigned char *t = macro(s); 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate trim(t); 4527c478bd9Sstevel@tonic-gate return (t); 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate unsigned char ** 4567c478bd9Sstevel@tonic-gate scan(argn) 4577c478bd9Sstevel@tonic-gate int argn; 4587c478bd9Sstevel@tonic-gate { 459965005c8Schin struct argnod *argp = 4607c478bd9Sstevel@tonic-gate (struct argnod *)(Rcheat(gchain) & ~ARGMK); 461965005c8Schin unsigned char **comargn, **comargm; 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate comargn = (unsigned char **)getstak(BYTESPERWORD * argn + BYTESPERWORD); 4647c478bd9Sstevel@tonic-gate comargm = comargn += argn; 4657c478bd9Sstevel@tonic-gate *comargn = ENDARGS; 4667c478bd9Sstevel@tonic-gate while (argp) 4677c478bd9Sstevel@tonic-gate { 4687c478bd9Sstevel@tonic-gate *--comargn = argp->argval; 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate trim(*comargn); 4717c478bd9Sstevel@tonic-gate argp = argp->argnxt; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate if (argp == 0 || Rcheat(argp) & ARGMK) 4747c478bd9Sstevel@tonic-gate { 4757c478bd9Sstevel@tonic-gate gsort(comargn, comargm); 4767c478bd9Sstevel@tonic-gate comargm = comargn; 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate argp = (struct argnod *)(Rcheat(argp) & ~ARGMK); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate return (comargn); 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate 483965005c8Schin static void 4847c478bd9Sstevel@tonic-gate gsort(from, to) 4857c478bd9Sstevel@tonic-gate unsigned char *from[], *to[]; 4867c478bd9Sstevel@tonic-gate { 4877c478bd9Sstevel@tonic-gate int k, m, n; 488965005c8Schin int i, j; 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate if ((n = to - from) <= 1) 4917c478bd9Sstevel@tonic-gate return; 4927c478bd9Sstevel@tonic-gate for (j = 1; j <= n; j *= 2) 4937c478bd9Sstevel@tonic-gate ; 4947c478bd9Sstevel@tonic-gate for (m = 2 * j - 1; m /= 2; ) 4957c478bd9Sstevel@tonic-gate { 4967c478bd9Sstevel@tonic-gate k = n - m; 4977c478bd9Sstevel@tonic-gate for (j = 0; j < k; j++) 4987c478bd9Sstevel@tonic-gate { 4997c478bd9Sstevel@tonic-gate for (i = j; i >= 0; i -= m) 5007c478bd9Sstevel@tonic-gate { 501965005c8Schin unsigned char **fromi; 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate fromi = &from[i]; 5047c478bd9Sstevel@tonic-gate if (cf(fromi[m], fromi[0]) > 0) 5057c478bd9Sstevel@tonic-gate { 5067c478bd9Sstevel@tonic-gate break; 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate else 5097c478bd9Sstevel@tonic-gate { 5107c478bd9Sstevel@tonic-gate unsigned char *s; 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate s = fromi[m]; 5137c478bd9Sstevel@tonic-gate fromi[m] = fromi[0]; 5147c478bd9Sstevel@tonic-gate fromi[0] = s; 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate /* 5227c478bd9Sstevel@tonic-gate * Argument list generation 5237c478bd9Sstevel@tonic-gate */ 524965005c8Schin int 5257c478bd9Sstevel@tonic-gate getarg(ac) 5267c478bd9Sstevel@tonic-gate struct comnod *ac; 5277c478bd9Sstevel@tonic-gate { 528965005c8Schin struct argnod *argp; 529965005c8Schin int count = 0; 530965005c8Schin struct comnod *c; 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate if (c = ac) 5337c478bd9Sstevel@tonic-gate { 5347c478bd9Sstevel@tonic-gate argp = c->comarg; 5357c478bd9Sstevel@tonic-gate while (argp) 5367c478bd9Sstevel@tonic-gate { 5377c478bd9Sstevel@tonic-gate count += split(macro(argp->argval), 1); 5387c478bd9Sstevel@tonic-gate argp = argp->argnxt; 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate return (count); 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate static int 5457c478bd9Sstevel@tonic-gate split(s) /* blank interpretation routine */ 5467c478bd9Sstevel@tonic-gate unsigned char *s; 5477c478bd9Sstevel@tonic-gate { 548965005c8Schin unsigned char *argp; 549965005c8Schin int c; 5507c478bd9Sstevel@tonic-gate int count = 0; 5517c478bd9Sstevel@tonic-gate for (;;) 5527c478bd9Sstevel@tonic-gate { 553965005c8Schin int length; 5547c478bd9Sstevel@tonic-gate sigchk(); 5557c478bd9Sstevel@tonic-gate argp = locstak() + BYTESPERWORD; 5567c478bd9Sstevel@tonic-gate while (c = *s) { 5577c478bd9Sstevel@tonic-gate wchar_t wc; 5587c478bd9Sstevel@tonic-gate if ((length = mbtowc(&wc, (char *)s, 5597c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 5607c478bd9Sstevel@tonic-gate wc = (unsigned char)*s; 5617c478bd9Sstevel@tonic-gate length = 1; 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate if (c == '\\') { /* skip over quoted characters */ 5657c478bd9Sstevel@tonic-gate if (argp >= brkend) 5667c478bd9Sstevel@tonic-gate growstak(argp); 5677c478bd9Sstevel@tonic-gate *argp++ = c; 5687c478bd9Sstevel@tonic-gate s++; 5697c478bd9Sstevel@tonic-gate /* get rest of multibyte character */ 5707c478bd9Sstevel@tonic-gate if ((length = mbtowc(&wc, (char *)s, 5717c478bd9Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 5727c478bd9Sstevel@tonic-gate wc = (unsigned char)*s; 5737c478bd9Sstevel@tonic-gate length = 1; 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate if (argp >= brkend) 5767c478bd9Sstevel@tonic-gate growstak(argp); 5777c478bd9Sstevel@tonic-gate *argp++ = *s++; 5787c478bd9Sstevel@tonic-gate while (--length > 0) { 5797c478bd9Sstevel@tonic-gate if (argp >= brkend) 5807c478bd9Sstevel@tonic-gate growstak(argp); 5817c478bd9Sstevel@tonic-gate *argp++ = *s++; 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate continue; 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate if (anys(s, ifsnod.namval)) { 5877c478bd9Sstevel@tonic-gate /* skip to next character position */ 5887c478bd9Sstevel@tonic-gate s += length; 5897c478bd9Sstevel@tonic-gate break; 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate if (argp >= brkend) 5937c478bd9Sstevel@tonic-gate growstak(argp); 5947c478bd9Sstevel@tonic-gate *argp++ = c; 5957c478bd9Sstevel@tonic-gate s++; 5967c478bd9Sstevel@tonic-gate while (--length > 0) { 5977c478bd9Sstevel@tonic-gate if (argp >= brkend) 5987c478bd9Sstevel@tonic-gate growstak(argp); 5997c478bd9Sstevel@tonic-gate *argp++ = *s++; 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate if (argp == staktop + BYTESPERWORD) 6037c478bd9Sstevel@tonic-gate { 6047c478bd9Sstevel@tonic-gate if (c) 6057c478bd9Sstevel@tonic-gate { 6067c478bd9Sstevel@tonic-gate continue; 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate else 6097c478bd9Sstevel@tonic-gate { 6107c478bd9Sstevel@tonic-gate return (count); 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate /* 6147c478bd9Sstevel@tonic-gate * file name generation 6157c478bd9Sstevel@tonic-gate */ 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate argp = endstak(argp); 6187c478bd9Sstevel@tonic-gate trims(((struct argnod *)argp)->argval); 6197c478bd9Sstevel@tonic-gate if ((flags & nofngflg) == 0 && 6207c478bd9Sstevel@tonic-gate (c = expand(((struct argnod *)argp)->argval, 0))) 6217c478bd9Sstevel@tonic-gate count += c; 6227c478bd9Sstevel@tonic-gate else 6237c478bd9Sstevel@tonic-gate { 624965005c8Schin makearg((struct argnod *)argp); 6257c478bd9Sstevel@tonic-gate count++; 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate gchain = (struct argnod *)((int)gchain | ARGMK); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate #ifdef ACCT 6327c478bd9Sstevel@tonic-gate #include <sys/types.h> 6337c478bd9Sstevel@tonic-gate #include <sys/acct.h> 6347c478bd9Sstevel@tonic-gate #include <sys/times.h> 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate struct acct sabuf; 6377c478bd9Sstevel@tonic-gate struct tms buffer; 6387c478bd9Sstevel@tonic-gate static clock_t before; 6397c478bd9Sstevel@tonic-gate static int shaccton; /* 0 implies do not write record on exit */ 6407c478bd9Sstevel@tonic-gate /* 1 implies write acct record on exit */ 641965005c8Schin static comp_t compress(clock_t); 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate /* 6457c478bd9Sstevel@tonic-gate * suspend accounting until turned on by preacct() 6467c478bd9Sstevel@tonic-gate */ 647965005c8Schin void 648965005c8Schin suspacct(void) 6497c478bd9Sstevel@tonic-gate { 6507c478bd9Sstevel@tonic-gate shaccton = 0; 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 653965005c8Schin void 654965005c8Schin preacct(unsigned char *cmdadr) 6557c478bd9Sstevel@tonic-gate { 6567c478bd9Sstevel@tonic-gate unsigned char *simple(); 6577c478bd9Sstevel@tonic-gate 658*db397771Schin if (acctnod.namval && *acctnod.namval) { 6597c478bd9Sstevel@tonic-gate sabuf.ac_btime = time((time_t *)0); 6607c478bd9Sstevel@tonic-gate before = times(&buffer); 6617c478bd9Sstevel@tonic-gate sabuf.ac_uid = getuid(); 6627c478bd9Sstevel@tonic-gate sabuf.ac_gid = getgid(); 6637c478bd9Sstevel@tonic-gate movstrn(simple(cmdadr), sabuf.ac_comm, sizeof (sabuf.ac_comm)); 6647c478bd9Sstevel@tonic-gate shaccton = 1; 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate 668965005c8Schin void 669965005c8Schin doacct(void) 6707c478bd9Sstevel@tonic-gate { 6717c478bd9Sstevel@tonic-gate int fd; 6727c478bd9Sstevel@tonic-gate clock_t after; 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate if (shaccton) { 6757c478bd9Sstevel@tonic-gate after = times(&buffer); 6767c478bd9Sstevel@tonic-gate sabuf.ac_utime = compress(buffer.tms_utime + buffer.tms_cutime); 6777c478bd9Sstevel@tonic-gate sabuf.ac_stime = compress(buffer.tms_stime + buffer.tms_cstime); 6787c478bd9Sstevel@tonic-gate sabuf.ac_etime = compress(after - before); 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate if ((fd = open((char *)acctnod.namval, 6817c478bd9Sstevel@tonic-gate O_WRONLY | O_APPEND | O_CREAT, 0666)) != -1) { 6827c478bd9Sstevel@tonic-gate write(fd, &sabuf, sizeof (sabuf)); 6837c478bd9Sstevel@tonic-gate close(fd); 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate } 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate /* 6897c478bd9Sstevel@tonic-gate * Produce a pseudo-floating point representation 6907c478bd9Sstevel@tonic-gate * with 3 bits base-8 exponent, 13 bits fraction 6917c478bd9Sstevel@tonic-gate */ 6927c478bd9Sstevel@tonic-gate 693965005c8Schin static comp_t 694965005c8Schin compress(clock_t t) 6957c478bd9Sstevel@tonic-gate { 696965005c8Schin int exp = 0; 697965005c8Schin int rund = 0; 6987c478bd9Sstevel@tonic-gate 699*db397771Schin while (t >= 8192) { 7007c478bd9Sstevel@tonic-gate exp++; 7017c478bd9Sstevel@tonic-gate rund = t & 04; 7027c478bd9Sstevel@tonic-gate t >>= 3; 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate 705*db397771Schin if (rund) { 7067c478bd9Sstevel@tonic-gate t++; 707*db397771Schin if (t >= 8192) { 7087c478bd9Sstevel@tonic-gate t >>= 3; 7097c478bd9Sstevel@tonic-gate exp++; 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate return ((exp << 13) + t); 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate #endif 715