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