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