1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*0Sstevel@tonic-gate /* All Rights Reserved */ 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate 26*0Sstevel@tonic-gate /* 27*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 28*0Sstevel@tonic-gate * Use is subject to license terms. 29*0Sstevel@tonic-gate */ 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.22.5.1 */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate /* 34*0Sstevel@tonic-gate * UNIX shell 35*0Sstevel@tonic-gate */ 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate #include "defs.h" 38*0Sstevel@tonic-gate #include <errno.h> 39*0Sstevel@tonic-gate #include <fcntl.h> 40*0Sstevel@tonic-gate #include "sh_policy.h" 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate #define ARGMK 01 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate static unsigned char *execs(); 45*0Sstevel@tonic-gate static int gsort(); 46*0Sstevel@tonic-gate static int split(); 47*0Sstevel@tonic-gate extern const char *sysmsg[]; 48*0Sstevel@tonic-gate extern short topfd; 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate /* 53*0Sstevel@tonic-gate * service routines for `execute' 54*0Sstevel@tonic-gate */ 55*0Sstevel@tonic-gate initio(iop, save) 56*0Sstevel@tonic-gate struct ionod *iop; 57*0Sstevel@tonic-gate int save; 58*0Sstevel@tonic-gate { 59*0Sstevel@tonic-gate register unsigned char *ion; 60*0Sstevel@tonic-gate register int iof, fd; 61*0Sstevel@tonic-gate int ioufd; 62*0Sstevel@tonic-gate short lastfd; 63*0Sstevel@tonic-gate int newmode; 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate lastfd = topfd; 66*0Sstevel@tonic-gate while (iop) { 67*0Sstevel@tonic-gate iof = iop->iofile; 68*0Sstevel@tonic-gate ion = mactrim(iop->ioname); 69*0Sstevel@tonic-gate ioufd = iof & IOUFD; 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate if (*ion && (flags&noexec) == 0) { 72*0Sstevel@tonic-gate if (save) { 73*0Sstevel@tonic-gate fdmap[topfd].org_fd = ioufd; 74*0Sstevel@tonic-gate fdmap[topfd++].dup_fd = savefd(ioufd); 75*0Sstevel@tonic-gate } 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate if (iof & IODOC) { 78*0Sstevel@tonic-gate struct tempblk tb; 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate subst(chkopen(ion, 0), (fd = tmpfil(&tb))); 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate /* 83*0Sstevel@tonic-gate * pushed in tmpfil() -- 84*0Sstevel@tonic-gate * bug fix for problem with 85*0Sstevel@tonic-gate * in-line scripts 86*0Sstevel@tonic-gate */ 87*0Sstevel@tonic-gate poptemp(); 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate fd = chkopen(tmpout, 0); 90*0Sstevel@tonic-gate unlink((const char *)tmpout); 91*0Sstevel@tonic-gate } else if (iof & IOMOV) { 92*0Sstevel@tonic-gate if (eq(minus, ion)) { 93*0Sstevel@tonic-gate fd = -1; 94*0Sstevel@tonic-gate close(ioufd); 95*0Sstevel@tonic-gate } else if ((fd = stoi(ion)) >= USERIO) { 96*0Sstevel@tonic-gate failed(ion, badfile); 97*0Sstevel@tonic-gate } 98*0Sstevel@tonic-gate else 99*0Sstevel@tonic-gate fd = dup(fd); 100*0Sstevel@tonic-gate } else if (((iof & IOPUT) == 0) && ((iof & IORDW) == 0)) 101*0Sstevel@tonic-gate fd = chkopen(ion, 0); 102*0Sstevel@tonic-gate else if (iof & IORDW) /* For <> */ { 103*0Sstevel@tonic-gate newmode = O_RDWR|O_CREAT; 104*0Sstevel@tonic-gate fd = chkopen(ion, newmode); 105*0Sstevel@tonic-gate } else if (flags & rshflg) { 106*0Sstevel@tonic-gate failed(ion, restricted); 107*0Sstevel@tonic-gate } else if (iof & IOAPP && 108*0Sstevel@tonic-gate (fd = open((char *)ion, 1)) >= 0) { 109*0Sstevel@tonic-gate lseek(fd, (off_t)0, SEEK_END); 110*0Sstevel@tonic-gate } else { 111*0Sstevel@tonic-gate fd = create(ion); 112*0Sstevel@tonic-gate } 113*0Sstevel@tonic-gate if (fd >= 0) 114*0Sstevel@tonic-gate renamef(fd, ioufd); 115*0Sstevel@tonic-gate } 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate iop = iop->ionxt; 118*0Sstevel@tonic-gate } 119*0Sstevel@tonic-gate return (lastfd); 120*0Sstevel@tonic-gate } 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gate unsigned char * 123*0Sstevel@tonic-gate simple(s) 124*0Sstevel@tonic-gate unsigned char *s; 125*0Sstevel@tonic-gate { 126*0Sstevel@tonic-gate unsigned char *sname; 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate sname = s; 129*0Sstevel@tonic-gate while (1) { 130*0Sstevel@tonic-gate if (any('/', sname)) 131*0Sstevel@tonic-gate while (*sname++ != '/') 132*0Sstevel@tonic-gate ; 133*0Sstevel@tonic-gate else 134*0Sstevel@tonic-gate return (sname); 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate } 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate unsigned char * 139*0Sstevel@tonic-gate getpath(s) 140*0Sstevel@tonic-gate unsigned char *s; 141*0Sstevel@tonic-gate { 142*0Sstevel@tonic-gate register unsigned char *path, *newpath; 143*0Sstevel@tonic-gate register int pathlen; 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate if (any('/', s)) 146*0Sstevel@tonic-gate { 147*0Sstevel@tonic-gate if (flags & rshflg) 148*0Sstevel@tonic-gate failed(s, restricted); 149*0Sstevel@tonic-gate else 150*0Sstevel@tonic-gate return ((unsigned char *)nullstr); 151*0Sstevel@tonic-gate } else if ((path = pathnod.namval) == 0) 152*0Sstevel@tonic-gate return ((unsigned char *)defpath); 153*0Sstevel@tonic-gate else { 154*0Sstevel@tonic-gate pathlen = length(path)-1; 155*0Sstevel@tonic-gate /* Add extra ':' if PATH variable ends in ':' */ 156*0Sstevel@tonic-gate if (pathlen > 2 && path[pathlen - 1] == ':' && 157*0Sstevel@tonic-gate path[pathlen - 2] != ':') { 158*0Sstevel@tonic-gate newpath = locstak(); 159*0Sstevel@tonic-gate (void) memcpystak(newpath, path, pathlen); 160*0Sstevel@tonic-gate newpath[pathlen] = ':'; 161*0Sstevel@tonic-gate endstak(newpath + pathlen + 1); 162*0Sstevel@tonic-gate return (newpath); 163*0Sstevel@tonic-gate } else 164*0Sstevel@tonic-gate return (cpystak(path)); 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate } 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate pathopen(path, name) 169*0Sstevel@tonic-gate register unsigned char *path, *name; 170*0Sstevel@tonic-gate { 171*0Sstevel@tonic-gate register int f; 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate do 174*0Sstevel@tonic-gate { 175*0Sstevel@tonic-gate path = catpath(path, name); 176*0Sstevel@tonic-gate } while ((f = open((char *)curstak(), 0)) < 0 && path); 177*0Sstevel@tonic-gate return (f); 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate unsigned char * 181*0Sstevel@tonic-gate catpath(path, name) 182*0Sstevel@tonic-gate register unsigned char *path; 183*0Sstevel@tonic-gate unsigned char *name; 184*0Sstevel@tonic-gate { 185*0Sstevel@tonic-gate /* 186*0Sstevel@tonic-gate * leaves result on top of stack 187*0Sstevel@tonic-gate */ 188*0Sstevel@tonic-gate register unsigned char *scanp = path; 189*0Sstevel@tonic-gate register unsigned char *argp = locstak(); 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate while (*scanp && *scanp != COLON) 192*0Sstevel@tonic-gate { 193*0Sstevel@tonic-gate if (argp >= brkend) 194*0Sstevel@tonic-gate growstak(argp); 195*0Sstevel@tonic-gate *argp++ = *scanp++; 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate if (scanp != path) 198*0Sstevel@tonic-gate { 199*0Sstevel@tonic-gate if (argp >= brkend) 200*0Sstevel@tonic-gate growstak(argp); 201*0Sstevel@tonic-gate *argp++ = '/'; 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate if (*scanp == COLON) 204*0Sstevel@tonic-gate scanp++; 205*0Sstevel@tonic-gate path = (*scanp ? scanp : 0); 206*0Sstevel@tonic-gate scanp = name; 207*0Sstevel@tonic-gate do 208*0Sstevel@tonic-gate { 209*0Sstevel@tonic-gate if (argp >= brkend) 210*0Sstevel@tonic-gate growstak(argp); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate while (*argp++ = *scanp++); 213*0Sstevel@tonic-gate return (path); 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate unsigned char * 217*0Sstevel@tonic-gate nextpath(path) 218*0Sstevel@tonic-gate register unsigned char *path; 219*0Sstevel@tonic-gate { 220*0Sstevel@tonic-gate register unsigned char *scanp = path; 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate while (*scanp && *scanp != COLON) 223*0Sstevel@tonic-gate scanp++; 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate if (*scanp == COLON) 226*0Sstevel@tonic-gate scanp++; 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate return (*scanp ? scanp : 0); 229*0Sstevel@tonic-gate } 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate static unsigned char *xecmsg; 232*0Sstevel@tonic-gate static unsigned char **xecenv; 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate int 235*0Sstevel@tonic-gate execa(at, pos) 236*0Sstevel@tonic-gate unsigned char *at[]; 237*0Sstevel@tonic-gate short pos; 238*0Sstevel@tonic-gate { 239*0Sstevel@tonic-gate register unsigned char *path; 240*0Sstevel@tonic-gate register unsigned char **t = at; 241*0Sstevel@tonic-gate int cnt; 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate if ((flags & noexec) == 0) 244*0Sstevel@tonic-gate { 245*0Sstevel@tonic-gate xecmsg = (unsigned char *)notfound; 246*0Sstevel@tonic-gate path = getpath(*t); 247*0Sstevel@tonic-gate xecenv = local_setenv(); 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate if (pos > 0) 250*0Sstevel@tonic-gate { 251*0Sstevel@tonic-gate cnt = 1; 252*0Sstevel@tonic-gate while (cnt != pos) 253*0Sstevel@tonic-gate { 254*0Sstevel@tonic-gate ++cnt; 255*0Sstevel@tonic-gate path = nextpath(path); 256*0Sstevel@tonic-gate } 257*0Sstevel@tonic-gate execs(path, t); 258*0Sstevel@tonic-gate path = getpath(*t); 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate while (path = execs(path, t)) 261*0Sstevel@tonic-gate ; 262*0Sstevel@tonic-gate failed(*t, xecmsg); 263*0Sstevel@tonic-gate } 264*0Sstevel@tonic-gate } 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate static unsigned char * 267*0Sstevel@tonic-gate execs(ap, t) 268*0Sstevel@tonic-gate unsigned char *ap; 269*0Sstevel@tonic-gate register unsigned char *t[]; 270*0Sstevel@tonic-gate { 271*0Sstevel@tonic-gate register int pfstatus = NOATTRS; 272*0Sstevel@tonic-gate register unsigned char *p, *prefix; 273*0Sstevel@tonic-gate unsigned char *savptr; 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate prefix = catpath(ap, t[0]); 276*0Sstevel@tonic-gate trim(p = curstak()); 277*0Sstevel@tonic-gate sigchk(); 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate if (flags & pfshflg) { 280*0Sstevel@tonic-gate /* 281*0Sstevel@tonic-gate * Need to save the stack information, or the 282*0Sstevel@tonic-gate * first memory allocation in secpolicy_profile_lookup() 283*0Sstevel@tonic-gate * will clobber it. 284*0Sstevel@tonic-gate */ 285*0Sstevel@tonic-gate savptr = endstak(p + strlen((const char *)p) + 1); 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate pfstatus = secpolicy_pfexec((const char *)p, 288*0Sstevel@tonic-gate (char **)t, (const char **)xecenv); 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate if (pfstatus != NOATTRS) { 291*0Sstevel@tonic-gate errno = pfstatus; 292*0Sstevel@tonic-gate } 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate tdystak(savptr); 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate if (pfstatus == NOATTRS) { 298*0Sstevel@tonic-gate execve((const char *)p, (char *const *)&t[0], 299*0Sstevel@tonic-gate (char *const *)xecenv); 300*0Sstevel@tonic-gate } 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate switch (errno) 303*0Sstevel@tonic-gate { 304*0Sstevel@tonic-gate case ENOEXEC: /* could be a shell script */ 305*0Sstevel@tonic-gate funcnt = 0; 306*0Sstevel@tonic-gate flags = 0; 307*0Sstevel@tonic-gate *flagadr = 0; 308*0Sstevel@tonic-gate comdiv = 0; 309*0Sstevel@tonic-gate ioset = 0; 310*0Sstevel@tonic-gate clearup(); /* remove open files and for loop junk */ 311*0Sstevel@tonic-gate if (input) 312*0Sstevel@tonic-gate close(input); 313*0Sstevel@tonic-gate input = chkopen(p, 0); 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate #ifdef ACCT 316*0Sstevel@tonic-gate preacct(p); /* reset accounting */ 317*0Sstevel@tonic-gate #endif 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate /* 320*0Sstevel@tonic-gate * set up new args 321*0Sstevel@tonic-gate */ 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate setargs(t); 324*0Sstevel@tonic-gate longjmp(subshell, 1); 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate case ENOMEM: 327*0Sstevel@tonic-gate failed(p, toobig); 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate case E2BIG: 330*0Sstevel@tonic-gate failed(p, arglist); 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate case ETXTBSY: 333*0Sstevel@tonic-gate failed(p, txtbsy); 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate case ELIBACC: 336*0Sstevel@tonic-gate failed(p, libacc); 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate case ELIBBAD: 339*0Sstevel@tonic-gate failed(p, libbad); 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate case ELIBSCN: 342*0Sstevel@tonic-gate failed(p, libscn); 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate case ELIBMAX: 345*0Sstevel@tonic-gate failed(p, libmax); 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate default: 348*0Sstevel@tonic-gate xecmsg = (unsigned char *)badexec; 349*0Sstevel@tonic-gate case ENOENT: 350*0Sstevel@tonic-gate return (prefix); 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate } 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate BOOL nosubst; 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate trim(at) 357*0Sstevel@tonic-gate unsigned char *at; 358*0Sstevel@tonic-gate { 359*0Sstevel@tonic-gate register unsigned char *last; 360*0Sstevel@tonic-gate register unsigned char *current; 361*0Sstevel@tonic-gate register unsigned char c; 362*0Sstevel@tonic-gate int len; 363*0Sstevel@tonic-gate wchar_t wc; 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate nosubst = 0; 366*0Sstevel@tonic-gate if (current = at) 367*0Sstevel@tonic-gate { 368*0Sstevel@tonic-gate last = at; 369*0Sstevel@tonic-gate while (c = *current) { 370*0Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 371*0Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 372*0Sstevel@tonic-gate *last++ = c; 373*0Sstevel@tonic-gate current++; 374*0Sstevel@tonic-gate continue; 375*0Sstevel@tonic-gate } 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate if (wc != '\\') { 378*0Sstevel@tonic-gate memcpy(last, current, len); 379*0Sstevel@tonic-gate last += len; 380*0Sstevel@tonic-gate current += len; 381*0Sstevel@tonic-gate continue; 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate /* remove \ and quoted nulls */ 385*0Sstevel@tonic-gate nosubst = 1; 386*0Sstevel@tonic-gate current++; 387*0Sstevel@tonic-gate if (c = *current) { 388*0Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 389*0Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 390*0Sstevel@tonic-gate *last++ = c; 391*0Sstevel@tonic-gate current++; 392*0Sstevel@tonic-gate continue; 393*0Sstevel@tonic-gate } 394*0Sstevel@tonic-gate memcpy(last, current, len); 395*0Sstevel@tonic-gate last += len; 396*0Sstevel@tonic-gate current += len; 397*0Sstevel@tonic-gate } else 398*0Sstevel@tonic-gate current++; 399*0Sstevel@tonic-gate } 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate *last = 0; 402*0Sstevel@tonic-gate } 403*0Sstevel@tonic-gate } 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate /* Same as trim, but only removes backlashes before slashes */ 406*0Sstevel@tonic-gate trims(at) 407*0Sstevel@tonic-gate unsigned char *at; 408*0Sstevel@tonic-gate { 409*0Sstevel@tonic-gate register unsigned char *last; 410*0Sstevel@tonic-gate register unsigned char *current; 411*0Sstevel@tonic-gate register unsigned char c; 412*0Sstevel@tonic-gate int len; 413*0Sstevel@tonic-gate wchar_t wc; 414*0Sstevel@tonic-gate 415*0Sstevel@tonic-gate if (current = at) 416*0Sstevel@tonic-gate { 417*0Sstevel@tonic-gate last = at; 418*0Sstevel@tonic-gate while (c = *current) { 419*0Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 420*0Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 421*0Sstevel@tonic-gate *last++ = c; 422*0Sstevel@tonic-gate current++; 423*0Sstevel@tonic-gate continue; 424*0Sstevel@tonic-gate } 425*0Sstevel@tonic-gate 426*0Sstevel@tonic-gate if (wc != '\\') { 427*0Sstevel@tonic-gate memcpy(last, current, len); 428*0Sstevel@tonic-gate last += len; current += len; 429*0Sstevel@tonic-gate continue; 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate /* remove \ and quoted nulls */ 433*0Sstevel@tonic-gate current++; 434*0Sstevel@tonic-gate if (!(c = *current)) { 435*0Sstevel@tonic-gate current++; 436*0Sstevel@tonic-gate continue; 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate if (c == '/') { 440*0Sstevel@tonic-gate *last++ = c; 441*0Sstevel@tonic-gate current++; 442*0Sstevel@tonic-gate continue; 443*0Sstevel@tonic-gate } 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate *last++ = '\\'; 446*0Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)current, 447*0Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 448*0Sstevel@tonic-gate *last++ = c; 449*0Sstevel@tonic-gate current++; 450*0Sstevel@tonic-gate continue; 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate memcpy(last, current, len); 453*0Sstevel@tonic-gate last += len; current += len; 454*0Sstevel@tonic-gate } 455*0Sstevel@tonic-gate *last = 0; 456*0Sstevel@tonic-gate } 457*0Sstevel@tonic-gate } 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate unsigned char * 460*0Sstevel@tonic-gate mactrim(s) 461*0Sstevel@tonic-gate unsigned char *s; 462*0Sstevel@tonic-gate { 463*0Sstevel@tonic-gate register unsigned char *t = macro(s); 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate trim(t); 466*0Sstevel@tonic-gate return (t); 467*0Sstevel@tonic-gate } 468*0Sstevel@tonic-gate 469*0Sstevel@tonic-gate unsigned char ** 470*0Sstevel@tonic-gate scan(argn) 471*0Sstevel@tonic-gate int argn; 472*0Sstevel@tonic-gate { 473*0Sstevel@tonic-gate register struct argnod *argp = 474*0Sstevel@tonic-gate (struct argnod *)(Rcheat(gchain) & ~ARGMK); 475*0Sstevel@tonic-gate register unsigned char **comargn, **comargm; 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate comargn = (unsigned char **)getstak(BYTESPERWORD * argn + BYTESPERWORD); 478*0Sstevel@tonic-gate comargm = comargn += argn; 479*0Sstevel@tonic-gate *comargn = ENDARGS; 480*0Sstevel@tonic-gate while (argp) 481*0Sstevel@tonic-gate { 482*0Sstevel@tonic-gate *--comargn = argp->argval; 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate trim(*comargn); 485*0Sstevel@tonic-gate argp = argp->argnxt; 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate if (argp == 0 || Rcheat(argp) & ARGMK) 488*0Sstevel@tonic-gate { 489*0Sstevel@tonic-gate gsort(comargn, comargm); 490*0Sstevel@tonic-gate comargm = comargn; 491*0Sstevel@tonic-gate } 492*0Sstevel@tonic-gate argp = (struct argnod *)(Rcheat(argp) & ~ARGMK); 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate return (comargn); 495*0Sstevel@tonic-gate } 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate static int 498*0Sstevel@tonic-gate gsort(from, to) 499*0Sstevel@tonic-gate unsigned char *from[], *to[]; 500*0Sstevel@tonic-gate { 501*0Sstevel@tonic-gate int k, m, n; 502*0Sstevel@tonic-gate register int i, j; 503*0Sstevel@tonic-gate 504*0Sstevel@tonic-gate if ((n = to - from) <= 1) 505*0Sstevel@tonic-gate return; 506*0Sstevel@tonic-gate for (j = 1; j <= n; j *= 2) 507*0Sstevel@tonic-gate ; 508*0Sstevel@tonic-gate for (m = 2 * j - 1; m /= 2; ) 509*0Sstevel@tonic-gate { 510*0Sstevel@tonic-gate k = n - m; 511*0Sstevel@tonic-gate for (j = 0; j < k; j++) 512*0Sstevel@tonic-gate { 513*0Sstevel@tonic-gate for (i = j; i >= 0; i -= m) 514*0Sstevel@tonic-gate { 515*0Sstevel@tonic-gate register unsigned char **fromi; 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate fromi = &from[i]; 518*0Sstevel@tonic-gate if (cf(fromi[m], fromi[0]) > 0) 519*0Sstevel@tonic-gate { 520*0Sstevel@tonic-gate break; 521*0Sstevel@tonic-gate } 522*0Sstevel@tonic-gate else 523*0Sstevel@tonic-gate { 524*0Sstevel@tonic-gate unsigned char *s; 525*0Sstevel@tonic-gate 526*0Sstevel@tonic-gate s = fromi[m]; 527*0Sstevel@tonic-gate fromi[m] = fromi[0]; 528*0Sstevel@tonic-gate fromi[0] = s; 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate } 531*0Sstevel@tonic-gate } 532*0Sstevel@tonic-gate } 533*0Sstevel@tonic-gate } 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate /* 536*0Sstevel@tonic-gate * Argument list generation 537*0Sstevel@tonic-gate */ 538*0Sstevel@tonic-gate getarg(ac) 539*0Sstevel@tonic-gate struct comnod *ac; 540*0Sstevel@tonic-gate { 541*0Sstevel@tonic-gate register struct argnod *argp; 542*0Sstevel@tonic-gate register int count = 0; 543*0Sstevel@tonic-gate register struct comnod *c; 544*0Sstevel@tonic-gate 545*0Sstevel@tonic-gate if (c = ac) 546*0Sstevel@tonic-gate { 547*0Sstevel@tonic-gate argp = c->comarg; 548*0Sstevel@tonic-gate while (argp) 549*0Sstevel@tonic-gate { 550*0Sstevel@tonic-gate count += split(macro(argp->argval), 1); 551*0Sstevel@tonic-gate argp = argp->argnxt; 552*0Sstevel@tonic-gate } 553*0Sstevel@tonic-gate } 554*0Sstevel@tonic-gate return (count); 555*0Sstevel@tonic-gate } 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate static int 558*0Sstevel@tonic-gate split(s) /* blank interpretation routine */ 559*0Sstevel@tonic-gate unsigned char *s; 560*0Sstevel@tonic-gate { 561*0Sstevel@tonic-gate register unsigned char *argp; 562*0Sstevel@tonic-gate register int c; 563*0Sstevel@tonic-gate int count = 0; 564*0Sstevel@tonic-gate for (;;) 565*0Sstevel@tonic-gate { 566*0Sstevel@tonic-gate register int length; 567*0Sstevel@tonic-gate sigchk(); 568*0Sstevel@tonic-gate argp = locstak() + BYTESPERWORD; 569*0Sstevel@tonic-gate while (c = *s) { 570*0Sstevel@tonic-gate wchar_t wc; 571*0Sstevel@tonic-gate if ((length = mbtowc(&wc, (char *)s, 572*0Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 573*0Sstevel@tonic-gate wc = (unsigned char)*s; 574*0Sstevel@tonic-gate length = 1; 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate if (c == '\\') { /* skip over quoted characters */ 578*0Sstevel@tonic-gate if (argp >= brkend) 579*0Sstevel@tonic-gate growstak(argp); 580*0Sstevel@tonic-gate *argp++ = c; 581*0Sstevel@tonic-gate s++; 582*0Sstevel@tonic-gate /* get rest of multibyte character */ 583*0Sstevel@tonic-gate if ((length = mbtowc(&wc, (char *)s, 584*0Sstevel@tonic-gate MB_LEN_MAX)) <= 0) { 585*0Sstevel@tonic-gate wc = (unsigned char)*s; 586*0Sstevel@tonic-gate length = 1; 587*0Sstevel@tonic-gate } 588*0Sstevel@tonic-gate if (argp >= brkend) 589*0Sstevel@tonic-gate growstak(argp); 590*0Sstevel@tonic-gate *argp++ = *s++; 591*0Sstevel@tonic-gate while (--length > 0) { 592*0Sstevel@tonic-gate if (argp >= brkend) 593*0Sstevel@tonic-gate growstak(argp); 594*0Sstevel@tonic-gate *argp++ = *s++; 595*0Sstevel@tonic-gate } 596*0Sstevel@tonic-gate continue; 597*0Sstevel@tonic-gate } 598*0Sstevel@tonic-gate 599*0Sstevel@tonic-gate if (anys(s, ifsnod.namval)) { 600*0Sstevel@tonic-gate /* skip to next character position */ 601*0Sstevel@tonic-gate s += length; 602*0Sstevel@tonic-gate break; 603*0Sstevel@tonic-gate } 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate if (argp >= brkend) 606*0Sstevel@tonic-gate growstak(argp); 607*0Sstevel@tonic-gate *argp++ = c; 608*0Sstevel@tonic-gate s++; 609*0Sstevel@tonic-gate while (--length > 0) { 610*0Sstevel@tonic-gate if (argp >= brkend) 611*0Sstevel@tonic-gate growstak(argp); 612*0Sstevel@tonic-gate *argp++ = *s++; 613*0Sstevel@tonic-gate } 614*0Sstevel@tonic-gate } 615*0Sstevel@tonic-gate if (argp == staktop + BYTESPERWORD) 616*0Sstevel@tonic-gate { 617*0Sstevel@tonic-gate if (c) 618*0Sstevel@tonic-gate { 619*0Sstevel@tonic-gate continue; 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate else 622*0Sstevel@tonic-gate { 623*0Sstevel@tonic-gate return (count); 624*0Sstevel@tonic-gate } 625*0Sstevel@tonic-gate } 626*0Sstevel@tonic-gate /* 627*0Sstevel@tonic-gate * file name generation 628*0Sstevel@tonic-gate */ 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate argp = endstak(argp); 631*0Sstevel@tonic-gate trims(((struct argnod *)argp)->argval); 632*0Sstevel@tonic-gate if ((flags & nofngflg) == 0 && 633*0Sstevel@tonic-gate (c = expand(((struct argnod *)argp)->argval, 0))) 634*0Sstevel@tonic-gate count += c; 635*0Sstevel@tonic-gate else 636*0Sstevel@tonic-gate { 637*0Sstevel@tonic-gate makearg(argp); 638*0Sstevel@tonic-gate count++; 639*0Sstevel@tonic-gate } 640*0Sstevel@tonic-gate gchain = (struct argnod *)((int)gchain | ARGMK); 641*0Sstevel@tonic-gate } 642*0Sstevel@tonic-gate } 643*0Sstevel@tonic-gate 644*0Sstevel@tonic-gate #ifdef ACCT 645*0Sstevel@tonic-gate #include <sys/types.h> 646*0Sstevel@tonic-gate #include <sys/acct.h> 647*0Sstevel@tonic-gate #include <sys/times.h> 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate struct acct sabuf; 650*0Sstevel@tonic-gate struct tms buffer; 651*0Sstevel@tonic-gate static clock_t before; 652*0Sstevel@tonic-gate static int shaccton; /* 0 implies do not write record on exit */ 653*0Sstevel@tonic-gate /* 1 implies write acct record on exit */ 654*0Sstevel@tonic-gate 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate /* 657*0Sstevel@tonic-gate * suspend accounting until turned on by preacct() 658*0Sstevel@tonic-gate */ 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gate suspacct() 661*0Sstevel@tonic-gate { 662*0Sstevel@tonic-gate shaccton = 0; 663*0Sstevel@tonic-gate } 664*0Sstevel@tonic-gate 665*0Sstevel@tonic-gate preacct(cmdadr) 666*0Sstevel@tonic-gate unsigned char *cmdadr; 667*0Sstevel@tonic-gate { 668*0Sstevel@tonic-gate unsigned char *simple(); 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gate if (acctnod.namval && *acctnod.namval) 671*0Sstevel@tonic-gate { 672*0Sstevel@tonic-gate sabuf.ac_btime = time((time_t *)0); 673*0Sstevel@tonic-gate before = times(&buffer); 674*0Sstevel@tonic-gate sabuf.ac_uid = getuid(); 675*0Sstevel@tonic-gate sabuf.ac_gid = getgid(); 676*0Sstevel@tonic-gate movstrn(simple(cmdadr), sabuf.ac_comm, sizeof (sabuf.ac_comm)); 677*0Sstevel@tonic-gate shaccton = 1; 678*0Sstevel@tonic-gate } 679*0Sstevel@tonic-gate } 680*0Sstevel@tonic-gate 681*0Sstevel@tonic-gate 682*0Sstevel@tonic-gate doacct() 683*0Sstevel@tonic-gate { 684*0Sstevel@tonic-gate int fd; 685*0Sstevel@tonic-gate clock_t after; 686*0Sstevel@tonic-gate 687*0Sstevel@tonic-gate if (shaccton) { 688*0Sstevel@tonic-gate after = times(&buffer); 689*0Sstevel@tonic-gate sabuf.ac_utime = compress(buffer.tms_utime + buffer.tms_cutime); 690*0Sstevel@tonic-gate sabuf.ac_stime = compress(buffer.tms_stime + buffer.tms_cstime); 691*0Sstevel@tonic-gate sabuf.ac_etime = compress(after - before); 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate if ((fd = open((char *)acctnod.namval, 694*0Sstevel@tonic-gate O_WRONLY | O_APPEND | O_CREAT, 0666)) != -1) { 695*0Sstevel@tonic-gate write(fd, &sabuf, sizeof (sabuf)); 696*0Sstevel@tonic-gate close(fd); 697*0Sstevel@tonic-gate } 698*0Sstevel@tonic-gate } 699*0Sstevel@tonic-gate } 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate /* 702*0Sstevel@tonic-gate * Produce a pseudo-floating point representation 703*0Sstevel@tonic-gate * with 3 bits base-8 exponent, 13 bits fraction 704*0Sstevel@tonic-gate */ 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate compress(t) 707*0Sstevel@tonic-gate register clock_t t; 708*0Sstevel@tonic-gate { 709*0Sstevel@tonic-gate register exp = 0; 710*0Sstevel@tonic-gate register rund = 0; 711*0Sstevel@tonic-gate 712*0Sstevel@tonic-gate while (t >= 8192) 713*0Sstevel@tonic-gate { 714*0Sstevel@tonic-gate exp++; 715*0Sstevel@tonic-gate rund = t & 04; 716*0Sstevel@tonic-gate t >>= 3; 717*0Sstevel@tonic-gate } 718*0Sstevel@tonic-gate 719*0Sstevel@tonic-gate if (rund) 720*0Sstevel@tonic-gate { 721*0Sstevel@tonic-gate t++; 722*0Sstevel@tonic-gate if (t >= 8192) 723*0Sstevel@tonic-gate { 724*0Sstevel@tonic-gate t >>= 3; 725*0Sstevel@tonic-gate exp++; 726*0Sstevel@tonic-gate } 727*0Sstevel@tonic-gate } 728*0Sstevel@tonic-gate return ((exp << 13) + t); 729*0Sstevel@tonic-gate } 730*0Sstevel@tonic-gate #endif 731