1 /* $Header: /p/tcsh/cvsroot/tcsh/tc.os.c,v 3.72 2011/01/25 13:58:19 christos Exp $ */ 2 /* 3 * tc.os.c: OS Dependent builtin functions 4 */ 5 /*- 6 * Copyright (c) 1980, 1991 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 #include "sh.h" 34 35 RCSID("$tcsh: tc.os.c,v 3.72 2011/01/25 13:58:19 christos Exp $") 36 37 #include "tw.h" 38 #include "ed.h" 39 #include "ed.defns.h" /* for the function names */ 40 #include "sh.decls.h" 41 42 #ifdef _UWIN 43 #define TIOCGPGRP TIOCGETPGRP 44 #define TIOCSPGRP TIOCSETPGRP 45 #endif 46 47 /*** 48 *** MACH 49 ***/ 50 51 #ifdef MACH 52 /* dosetpath -- setpath built-in command 53 * 54 ********************************************************************** 55 * HISTORY 56 * 08-May-88 Richard Draves (rpd) at Carnegie-Mellon University 57 * Major changes to remove artificial limits on sizes and numbers 58 * of paths. 59 * 60 ********************************************************************** 61 */ 62 63 #ifdef MACH 64 static Char STRCPATH[] = {'C', 'P', 'A', 'T', 'H', '\0'}; 65 static Char STRLPATH[] = {'L', 'P', 'A', 'T', 'H', '\0'}; 66 static Char STRMPATH[] = {'M', 'P', 'A', 'T', 'H', '\0'}; 67 # if EPATH 68 static Char STREPATH[] = {'E', 'P', 'A', 'T', 'H', '\0'}; 69 # endif 70 #endif /* MACH */ 71 static Char *syspaths[] = {STRKPATH, STRCPATH, STRLPATH, STRMPATH, 72 73 #if EPATH 74 STREPATH, 75 #endif 76 0}; 77 #define LOCALSYSPATH "/usr/local" 78 79 /*ARGSUSED*/ 80 void 81 dosetpath(Char **arglist, struct command *c) 82 { 83 extern char *getenv(); 84 Char **pathvars, **cmdargs; 85 char **spaths, **cpaths, **cmds; 86 char *tcp; 87 unsigned int npaths, ncmds; 88 int i, sysflag; 89 90 pintr_disabled++; 91 cleanup_push(&pintr_disabled, disabled_cleanup); 92 93 /* 94 * setpath(3) uses stdio and we want 0, 1, 2 to work... 95 */ 96 if (!didfds) { 97 (void) dcopy(SHIN, 0); 98 (void) dcopy(SHOUT, 1); 99 (void) dcopy(SHDIAG, 2); 100 didfds = 1; 101 } 102 103 for (i = 1; arglist[i] && (arglist[i][0] != '-'); i++); 104 npaths = i - 1; 105 106 cmdargs = &arglist[i]; 107 for (; arglist[i]; i++); 108 ncmds = i - npaths - 1; 109 110 if (npaths) { 111 sysflag = 0; 112 pathvars = &arglist[1]; 113 } 114 else { 115 sysflag = 1; 116 npaths = (sizeof syspaths / sizeof *syspaths) - 1; 117 pathvars = syspaths; 118 } 119 120 /* note that npaths != 0 */ 121 122 spaths = xmalloc(npaths * sizeof *spaths); 123 setzero(spaths, npaths * sizeof *spaths); 124 cpaths = xmalloc((npaths + 1) * sizeof *cpaths); 125 setzero(cpaths, (npaths + 1) * sizeof *cpaths); 126 cmds = xmalloc((ncmds + 1) * sizeof *cmds); 127 setzero(cmds, (ncmds + 1) * sizeof *cmds); 128 for (i = 0; i < npaths; i++) { 129 char *val = getenv(short2str(pathvars[i])); 130 131 if (val == NULL) 132 val = ""; 133 134 spaths[i] = xmalloc((Strlen(pathvars[i]) + strlen(val) + 2) * 135 sizeof **spaths); 136 (void) strcpy(spaths[i], short2str(pathvars[i])); 137 (void) strcat(spaths[i], "="); 138 (void) strcat(spaths[i], val); 139 cpaths[i] = spaths[i]; 140 } 141 142 for (i = 0; i < ncmds; i++) { 143 Char *val = globone(cmdargs[i], G_ERROR);/*FIXRESET*/ 144 145 if (val == NULL) 146 goto abortpath; 147 cmds[i] = strsave(short2str(val)); 148 } 149 150 151 if (setpath(cpaths, cmds, LOCALSYSPATH, sysflag, 1) < 0) { 152 abortpath: 153 if (spaths) { 154 for (i = 0; i < npaths; i++) 155 xfree(spaths[i]); 156 xfree(spaths); 157 } 158 xfree(cpaths); 159 if (cmds) { 160 for (i = 0; i < ncmds; i++) 161 xfree(cmds[i]); 162 xfree(cmds); 163 } 164 165 cleanup_until(&pintr_disabled); 166 donefds(); 167 return; 168 } 169 170 for (i = 0; i < npaths; i++) { 171 Char *val, *name; 172 173 name = str2short(cpaths[i]); 174 for (val = str2short(cpaths[i]); val && *val && *val != '='; val++); 175 if (val && *val == '=') { 176 *val++ = '\0'; 177 178 tsetenv(name, val);/*FIXRESET*/ 179 if (Strcmp(name, STRKPATH) == 0) { 180 importpath(val);/*FIXRESET*/ 181 if (havhash) 182 dohash(NULL, NULL);/*FIXRESET*/ 183 } 184 *--val = '='; 185 } 186 } 187 cleanup_until(&pintr_disabled); 188 donefds(); 189 } 190 #endif /* MACH */ 191 192 /*** 193 *** AIX 194 ***/ 195 #ifdef TCF 196 /* ARGSUSED */ 197 void 198 dogetxvers(Char **v, struct command *c) 199 { 200 char xvers[MAXPATHLEN]; 201 202 if (getxvers(xvers, MAXPATHLEN) == -1) 203 stderror(ERR_SYSTEM, "getxvers", strerror(errno)); 204 xprintf("%s\n", xvers); 205 flush(); 206 } 207 208 /*ARGSUSED*/ 209 void 210 dosetxvers(Char **v, struct command *c) 211 { 212 char *xvers; 213 214 ++v; 215 if (!*v || *v[0] == '\0') 216 xvers = ""; 217 else 218 xvers = short2str(*v); 219 if (setxvers(xvers) == -1) 220 stderror(ERR_SYSTEM, "setxvers", strerror(errno)); 221 } 222 223 #include <sf.h> 224 #ifdef _AIXPS2 225 # define XC_PDP11 0x01 226 # define XC_23 0x02 227 # define XC_Z8K 0x03 228 # define XC_8086 0x04 229 # define XC_68K 0x05 230 # define XC_Z80 0x06 231 # define XC_VAX 0x07 232 # define XC_16032 0x08 233 # define XC_286 0x09 234 # define XC_386 0x0a 235 # define XC_S370 0x0b 236 #else 237 # include <sys/x.out.h> 238 #endif /* _AIXPS2 */ 239 240 static struct xc_cpu_t { 241 short xc_id; 242 char *xc_name; 243 } xcpu[] = 244 { 245 { XC_PDP11, "pdp11" }, 246 { XC_23, "i370" }, 247 { XC_Z8K, "z8000" }, 248 { XC_8086, "i86" }, 249 { XC_68K, "mc68000" }, 250 { XC_Z80, "x80" }, 251 { XC_VAX, "vax" }, 252 { XC_16032, "ns16032" }, 253 { XC_286, "i286" }, 254 { XC_386, "i386" }, 255 { XC_S370, "xa370" }, 256 { 0, NULL } 257 }; 258 259 /* 260 * our local hack table, stolen from x.out.h 261 */ 262 static char * 263 getxcode(short xcid) 264 { 265 int i; 266 267 for (i = 0; xcpu[i].xc_name != NULL; i++) 268 if (xcpu[i].xc_id == xcid) 269 return (xcpu[i].xc_name); 270 return (NULL); 271 } 272 273 static short 274 getxid(char *xcname) 275 { 276 int i; 277 278 for (i = 0; xcpu[i].xc_name != NULL; i++) 279 if (strcmp(xcpu[i].xc_name, xcname) == 0) 280 return (xcpu[i].xc_id); 281 return ((short) -1); 282 } 283 284 285 /*ARGSUSED*/ 286 void 287 dogetspath(Char **v, struct command *c) 288 { 289 int i, j; 290 sitepath_t p[MAXSITE]; 291 struct sf *st; 292 static char *local = "LOCAL "; 293 294 if ((j = getspath(p, MAXSITE)) == -1) 295 stderror(ERR_SYSTEM, "getspath", strerror(errno)); 296 for (i = 0; i < j && (p[i] & SPATH_CPU) != NOSITE; i++) { 297 if (p[i] & SPATH_CPU) { 298 if ((p[i] & SPATH_MASK) == NULLSITE) 299 xprintf(local); 300 else if ((st = sfxcode((short) (p[i] & SPATH_MASK))) != NULL) 301 xprintf("%s ", st->sf_ctype); 302 else { 303 char *xc = getxcode(p[i] & SPATH_MASK); 304 305 if (xc != NULL) 306 xprintf("%s ", xc); 307 else 308 xprintf("*cpu %d* ", (int) (p[i] & SPATH_MASK)); 309 /* 310 * BUG in the aix code... needs that cause if 311 * sfxcode fails once it fails for ever 312 */ 313 endsf(); 314 } 315 } 316 else { 317 if (p[i] == NULLSITE) 318 xprintf(local); 319 else if ((st = sfnum(p[i])) != NULL) 320 xprintf("%s ", st->sf_sname); 321 else 322 xprintf("*site %d* ", (int) (p[i] & SPATH_MASK)); 323 } 324 } 325 xputchar('\n'); 326 flush(); 327 } 328 329 /*ARGSUSED*/ 330 void 331 dosetspath(Char **v, struct command *c) 332 { 333 int i; 334 short j; 335 char *s; 336 sitepath_t p[MAXSITE]; 337 struct sf *st; 338 339 /* 340 * sfname() on AIX G9.9 at least, mallocs too pointers p, q 341 * then does the equivalent of while (*p++ == *q++) continue; 342 * and then tries to free(p,q) them! Congrats to the wizard who 343 * wrote that one. I bet he tested it really well too. 344 * Sooo, we set dont_free :-) 345 */ 346 dont_free = 1; 347 for (i = 0, v++; *v && *v[0] != '\0'; v++, i++) { 348 s = short2str(*v); 349 if (isdigit(*s)) 350 p[i] = atoi(s); 351 else if (strcmp(s, "LOCAL") == 0) 352 p[i] = NULLSITE; 353 else if ((st = sfctype(s)) != NULL) 354 p[i] = SPATH_CPU | st->sf_ccode; 355 else if ((j = getxid(s)) != -1) 356 p[i] = SPATH_CPU | j; 357 else if ((st = sfname(s)) != NULL) 358 p[i] = st->sf_id; 359 else { 360 setname(s); 361 stderror(ERR_NAME | ERR_STRING, CGETS(23, 1, "Bad cpu/site name")); 362 } 363 if (i == MAXSITE - 1) 364 stderror(ERR_NAME | ERR_STRING, CGETS(23, 2, "Site path too long")); 365 } 366 if (setspath(p, i) == -1) 367 stderror(ERR_SYSTEM, "setspath", strerror(errno)); 368 dont_free = 0; 369 } 370 371 /* sitename(): 372 * Return the site name where the process is running 373 */ 374 char * 375 sitename(pid_t pid) 376 { 377 siteno_t ss; 378 struct sf *st; 379 380 if ((ss = site(pid)) == -1 || (st = sfnum(ss)) == NULL) 381 return CGETS(23, 3, "unknown"); 382 else 383 return st->sf_sname; 384 } 385 386 static int 387 migratepid(pit_t pid, siteno_t new_site) 388 { 389 struct sf *st; 390 int need_local; 391 392 need_local = (pid == 0) || (pid == getpid()); 393 394 if (kill3(pid, SIGMIGRATE, new_site) < 0) { 395 xprintf("%d: %s\n", pid, strerror(errno)); 396 return (-1); 397 } 398 399 if (need_local) { 400 if ((new_site = site(0)) == -1) { 401 xprintf(CGETS(23, 4, "site: %s\n"), strerror(errno)); 402 return (-1); 403 } 404 if ((st = sfnum(new_site)) == NULL) { 405 xprintf(CGETS(23, 5, "%d: Site not found\n"), new_site); 406 return (-1); 407 } 408 if (setlocal(st->sf_local, strlen(st->sf_local)) == -1) { 409 xprintf(CGETS(23, 6, "setlocal: %s: %s\n"), 410 st->sf_local, strerror(errno)); 411 return (-1); 412 } 413 } 414 return (0); 415 } 416 417 /*ARGSUSED*/ 418 void 419 domigrate(Char **v, struct command *c) 420 { 421 struct sf *st; 422 char *s; 423 Char *cp; 424 struct process *pp; 425 int err1 = 0; 426 int pid = 0; 427 siteno_t new_site = 0; 428 429 pchild_disabled++; 430 cleanup_push(&pchild_disabled, disabled_cleanup); 431 if (setintr) { 432 pintr_disabled++; 433 cleanup_push(&pintr_disabled, disabled_cleanup); 434 } 435 436 ++v; 437 if (*v[0] == '-') { 438 /* 439 * Do the -site. 440 */ 441 s = short2str(&v[0][1]); 442 /* 443 * see comment in setspath() 444 */ 445 dont_free = 1; 446 if ((st = sfname(s)) == NULL) { 447 dont_free = 0; 448 setname(s); 449 stderror(ERR_NAME | ERR_STRING, CGETS(23, 7, "Site not found")); 450 } 451 dont_free = 0; 452 new_site = st->sf_id; 453 ++v; 454 } 455 456 if (!*v || *v[0] == '\0') { 457 if (migratepid(0, new_site) == -1) 458 err1++; 459 } 460 else { 461 Char **globbed; 462 463 v = glob_all_or_error(v); 464 globbed = v; 465 cleanup_push(globbed, blk_cleanup); 466 467 while (v && (cp = *v)) { 468 if (*cp == '%') { 469 pp = pfind(cp); 470 if (kill3(- pp->p_jobid, SIGMIGRATE, new_site) < 0) { 471 xprintf("%S: %s\n", cp, strerror(errno)); 472 err1++; 473 } 474 } 475 else if (!(Isdigit(*cp) || *cp == '-')) 476 stderror(ERR_NAME | ERR_JOBARGS); 477 else { 478 pid = atoi(short2str(cp)); 479 if (migratepid(pid, new_site) == -1) 480 err1++; 481 } 482 v++; 483 } 484 cleanup_until(globbed); 485 } 486 487 done: 488 cleanup_until(&pchild_disabled); 489 if (err1) 490 stderror(ERR_SILENT); 491 } 492 493 #endif /* TCF */ 494 495 /*** 496 *** CRAY ddmode <velo@sesun3.epfl.ch> (Martin Ouwehand EPFL-SIC/SE) 497 ***/ 498 #if defined(_CRAY) && !defined(_CRAYMPP) 499 void 500 dodmmode(Char **v, struct command *c) 501 { 502 Char *cp = v[1]; 503 504 USE(c); 505 506 if ( !cp ) { 507 int mode; 508 509 mode = dmmode(0); 510 dmmode(mode); 511 xprintf("%d\n",mode); 512 } 513 else { 514 if (cp[1] != '\0') 515 stderror(ERR_NAME | ERR_STRING, 516 CGETS(23, 30, "Too many arguments")); 517 else 518 switch(*cp) { 519 case '0': 520 dmmode(0); 521 break; 522 case '1': 523 dmmode(1); 524 break; 525 default: 526 stderror(ERR_NAME | ERR_STRING, 527 CGETS(23, 31, "Invalid argument")); 528 } 529 } 530 } 531 #endif /* _CRAY && !_CRAYMPP */ 532 533 534 /*** 535 *** CONVEX Warps. 536 ***/ 537 538 #ifdef WARP 539 /* 540 * handle the funky warping of symlinks 541 */ 542 #include <warpdb.h> 543 #include <sys/warp.h> 544 545 static jmp_buf sigsys_buf; 546 547 static void 548 catch_sigsys(void) 549 { 550 sigset_t set; 551 sigemptyset(&set, SIGSYS); 552 (void)sigprocmask(SIG_UNBLOCK, &set, NULL); 553 longjmp(sigsys_buf, 1); 554 } 555 556 557 /*ARGSUSED*/ 558 void 559 dowarp(Char **v, struct command *c) 560 { 561 int warp, oldwarp; 562 struct warpent *we; 563 volatile struct sigaction old_sigsys_handler; 564 char *newwarp; 565 566 if (setjmp(sigsys_buf)) { 567 sigaction(SIGSYS, &old_sigsys_handler, NULL); 568 stderror(ERR_NAME | ERR_STRING, 569 CGETS(23, 8, "You're trapped in a universe you never made")); 570 return; 571 } 572 sigaction(SIGSYS, NULL, &old_sigsys_handler); 573 signal(SIGSYS, catch_sigsys); 574 575 warp = getwarp(); 576 577 v++; 578 if (*v == 0) { /* display warp value */ 579 if (warp < 0) 580 stderror(ERR_NAME | ERR_STRING, CGETS(23, 9, "Getwarp failed")); 581 we = getwarpbyvalue(warp); 582 if (we) 583 printf("%s\n", we->w_name); 584 else 585 printf("%d\n", warp); 586 } 587 else { /* set warp value */ 588 oldwarp = warp; 589 newwarp = short2str(*v); 590 if (Isdigit(*v[0])) 591 warp = atoi(newwarp); 592 else { 593 we = getwarpbyname(newwarp); 594 if (we) 595 warp = we->w_value; 596 else 597 warp = -1; 598 } 599 if ((warp < 0) || (warp >= WARP_MAXLINK)) 600 stderror(ERR_NAME | ERR_STRING, CGETS(23, 10, "Invalid warp")); 601 if ((setwarp(warp) < 0) || (getwarp() != warp)) { 602 (void) setwarp(oldwarp); 603 stderror(ERR_NAME | ERR_STRING, CGETS(23, 11, "Setwarp failed")); 604 } 605 } 606 sigaction(SIGSYS, &old_sigsys_handler, NULL); 607 } 608 #endif /* WARP */ 609 610 /*** 611 *** Masscomp or HCX 612 ***/ 613 /* Added, DAS DEC-90. */ 614 #if defined(masscomp) || defined(_CX_UX) 615 static void 616 setuniverse_cleanup(void *xbuf) 617 { 618 char *buf; 619 620 buf = xbuf; 621 setuniverse(buf); 622 } 623 624 /*ARGSUSED*/ 625 void 626 douniverse(Char **v, struct command *c) 627 { 628 Char *cp = v[1]; 629 Char *cp2; /* dunno how many elements v comes in with */ 630 char ubuf[100]; 631 632 if (cp == 0) { 633 (void) getuniverse(ubuf); 634 xprintf("%s\n", ubuf); 635 } 636 else { 637 cp2 = v[2]; 638 if (cp2 == 0) { 639 if (*cp == '\0' || setuniverse(short2str(cp)) != 0) 640 stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe")); 641 } 642 else { 643 (void) getuniverse(ubuf); 644 if (*cp == '\0' || setuniverse(short2str(cp)) != 0) 645 stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe")); 646 cleanup_push(ubuf, setuniverse_cleanup); 647 if (setintr) { 648 pintr_disabled++; 649 cleanup_push(&pintr_disabled, disabled_cleanup); 650 } 651 lshift(v, 2); 652 if (setintr) 653 cleanup_until(&pintr_disabled); 654 reexecute(c); 655 cleanup_until(ubuf); 656 } 657 } 658 } 659 #endif /* masscomp || _CX_UX */ 660 661 /*** 662 *** BS2000/OSD POSIX (Fujitsu Siemens Computers) 663 ***/ 664 #if defined(_OSD_POSIX) 665 static int 666 bs2upcase(char *str) 667 { 668 enum { outside = ' ', singlequote='\'', doublequote='"'} string = outside; 669 670 char *white; 671 672 for (white = str + strlen(str) - 1; isspace(*white) && white > str; --white) 673 *white = '\0'; 674 675 for (; *str != '\0'; ++str) 676 { 677 if (string == outside) 678 { 679 *str = toupper (*str); 680 } 681 if (*str == '\'') 682 { 683 if (string == outside) 684 string = singlequote; 685 else if (string != doublequote) 686 string = outside; 687 } 688 else if (*str == '"') 689 { 690 if (string == outside) 691 string = doublequote; 692 else if (string != singlequote) 693 string = outside; 694 } 695 } 696 if (string != outside) 697 { 698 stderror(ERR_NAME | ERR_UNMATCHED, (Char) string); 699 return 1; 700 } 701 return 0; 702 } 703 static int 704 bs2cmdlist(char *str) 705 { 706 char *str_beg = NULL; 707 int ret = 0; 708 709 enum { outside = ' ', singlequote='\'', doublequote='"'} string = outside; 710 711 while (*str != '\0') 712 { 713 while (isspace(*str)) 714 ++str; 715 716 if (*str == '\0') 717 break; 718 719 str_beg = str; 720 721 for (; *str != '\0'; ++str) 722 { 723 if (string == outside && *str == ';') /* End of command */ 724 { 725 *str++ = '\0'; 726 break; /* continue with next command */ 727 } 728 if (*str == '\'') 729 { 730 if (string == outside) 731 string = singlequote; 732 else if (string != doublequote) 733 string = outside; 734 } 735 else if (*str == '"') 736 { 737 if (string == outside) 738 string = doublequote; 739 else if (string != singlequote) 740 string = outside; 741 } 742 } 743 if (strlen(str_beg) != 0) 744 { 745 ret = bs2system(str_beg); 746 flush(); 747 if (ret != 0 /*&& !option.err_ignore*/) 748 break; /* do not continue after errors */ 749 } 750 } 751 752 if (string != outside) 753 { 754 stderror(ERR_NAME | ERR_UNMATCHED, (Char) string); 755 return -1; 756 } 757 758 return ret; 759 } 760 /*ARGSUSED*/ 761 void 762 dobs2cmd(Char **v, struct command *c) 763 { 764 Char *cp, **globbed; 765 int i = 0, len = 0; 766 char *cmd = NULL; 767 int pvec[2]; 768 struct command faket; 769 Char *fakecom[2]; 770 char tibuf[BUFSIZE]; 771 int icnt, old_pintr_disabled; 772 static const Char STRbs2cmd[] = { 'b','s','2','c','m','d','\0' }; 773 774 v++; 775 if (setintr) 776 pintr_push_enable(&old_pintr_disabled); 777 v = glob_all_or_error(v); 778 if (setintr) 779 cleanup_until(&old_pintr_disabled); 780 globbed = v; 781 cleanup_push(globbed, blk_cleanup); 782 783 /* First round: count the string lengths */ 784 for (i=0; v[i]; ++i) { 785 len += Strlen(v[i]) + (v[i+1] != NULL); 786 } 787 788 cmd = xmalloc(len+1); /* 1 for the final '\0' *//* FIXME: memory leak? */ 789 790 /* 2nd round: fill cmd buffer */ 791 i = 0; 792 while ((cp = *v++) != 0) { 793 int c; 794 while (c = *cp++) 795 cmd[i++] = (char)c; 796 if (*v) 797 cmd[i++] = ' '; 798 } 799 cmd[i] = '\0'; 800 801 /* Make upper case */ 802 bs2upcase(cmd); 803 804 faket.t_dtyp = NODE_COMMAND; 805 faket.t_dflg = F_BACKQ|F_STDERR; 806 faket.t_dlef = 0; 807 faket.t_drit = 0; 808 faket.t_dspr = 0; 809 faket.t_dcom = fakecom; 810 fakecom[0] = (Char *)STRbs2cmd; 811 fakecom[1] = 0; 812 813 mypipe(pvec); 814 cleanup_push(&pvec[0], open_cleanup); 815 cleanup_push(&pvec[1], open_cleanup); 816 if (pfork(&faket, -1) == 0) { 817 sigset_t set; 818 /* child */ 819 xclose(pvec[0]); 820 (void) dmove(pvec[1], 1); 821 (void) dmove(SHDIAG, 2); 822 initdesc(); 823 sigemptyset(&set); 824 sigaddset(&set, SIGINT); 825 (void)sigprocmask(SIG_UNBLOCK, &set, NULL); 826 #ifdef SIGTSTP 827 signal(SIGTSTP, SIG_IGN); 828 #endif 829 #ifdef SIGTTIN 830 signal(SIGTTIN, SIG_IGN); 831 #endif 832 #ifdef SIGTTOU 833 signal(SIGTTOU, SIG_IGN); 834 #endif 835 xexit(bs2cmdlist(cmd)); 836 } 837 cleanup_until(&pvec[1]); 838 for(;;) { 839 int old_pintr_disabled; 840 841 if (setintr) 842 pintr_push_enable(&old_pintr_disabled); 843 icnt = xread(pvec[0], tibuf, sizeof(tibuf)); 844 if (setintr) 845 cleanup_until(&old_pintr_disabled); 846 if (icnt <= 0) 847 break; 848 for (i = 0; i < icnt; i++) 849 xputchar((unsigned char) tibuf[i]); 850 } 851 cleanup_until(&pvec[0]); 852 pwait(); 853 854 flush(); 855 856 cleanup_until(globbed); 857 } 858 #endif /* _OSD_POSIX */ 859 860 #if defined(_CX_UX) 861 static void 862 setuniverse_cleanup(void *xbuf) 863 { 864 char *buf; 865 866 buf = xbuf; 867 setuniverse(buf); 868 } 869 870 /*ARGSUSED*/ 871 void 872 doatt(Char **v, struct command *c) 873 { 874 Char *cp = v[1]; 875 char ubuf[100]; 876 877 if (cp == 0) 878 (void) setuniverse("att"); 879 else { 880 (void) getuniverse(ubuf); 881 (void) setuniverse("att"); 882 cleanup_push(ubuf, setuniverse_cleanup); 883 if (setintr) { 884 pintr_disabled++; 885 cleanup_push(&pintr_disabled, disabled_cleanup); 886 } 887 lshift(v, 1); 888 if (setintr) 889 cleanup_until(&pintr_disabled); 890 reexecute(c); 891 cleanup_until(ubuf); 892 } 893 } 894 895 /*ARGSUSED*/ 896 void 897 doucb(Char **v, struct command *c) 898 { 899 Char *cp = v[1]; 900 char ubuf[100]; 901 902 if (cp == 0) 903 (void) setuniverse("ucb"); 904 else { 905 (void) getuniverse(ubuf); 906 (void) setuniverse("ucb"); 907 cleanup_push(ubuf, setuniverse_cleanup); 908 if (setintr) { 909 pintr_disabled++; 910 cleanup_push(&pintr_disabled, disabled_cleanup); 911 } 912 lshift(v, 1); 913 if (setintr) 914 cleanup_until(&pintr_disabled); 915 reexecute(c); 916 cleanup_until(ubuf); 917 } 918 } 919 #endif /* _CX_UX */ 920 921 #ifdef _SEQUENT_ 922 /* 923 * Compute the difference in process stats. 924 */ 925 void 926 pr_stat_sub(struct process_stats *p2, struct process_stats *p1, 927 struct process_stats *pr) 928 { 929 pr->ps_utime.tv_sec = p2->ps_utime.tv_sec - p1->ps_utime.tv_sec; 930 pr->ps_utime.tv_usec = p2->ps_utime.tv_usec - p1->ps_utime.tv_usec; 931 if (pr->ps_utime.tv_usec < 0) { 932 pr->ps_utime.tv_sec -= 1; 933 pr->ps_utime.tv_usec += 1000000; 934 } 935 pr->ps_stime.tv_sec = p2->ps_stime.tv_sec - p1->ps_stime.tv_sec; 936 pr->ps_stime.tv_usec = p2->ps_stime.tv_usec - p1->ps_stime.tv_usec; 937 if (pr->ps_stime.tv_usec < 0) { 938 pr->ps_stime.tv_sec -= 1; 939 pr->ps_stime.tv_usec += 1000000; 940 } 941 942 pr->ps_maxrss = p2->ps_maxrss - p1->ps_maxrss; 943 pr->ps_pagein = p2->ps_pagein - p1->ps_pagein; 944 pr->ps_reclaim = p2->ps_reclaim - p1->ps_reclaim; 945 pr->ps_zerofill = p2->ps_zerofill - p1->ps_zerofill; 946 pr->ps_pffincr = p2->ps_pffincr - p1->ps_pffincr; 947 pr->ps_pffdecr = p2->ps_pffdecr - p1->ps_pffdecr; 948 pr->ps_swap = p2->ps_swap - p1->ps_swap; 949 pr->ps_syscall = p2->ps_syscall - p1->ps_syscall; 950 pr->ps_volcsw = p2->ps_volcsw - p1->ps_volcsw; 951 pr->ps_involcsw = p2->ps_involcsw - p1->ps_involcsw; 952 pr->ps_signal = p2->ps_signal - p1->ps_signal; 953 pr->ps_lread = p2->ps_lread - p1->ps_lread; 954 pr->ps_lwrite = p2->ps_lwrite - p1->ps_lwrite; 955 pr->ps_bread = p2->ps_bread - p1->ps_bread; 956 pr->ps_bwrite = p2->ps_bwrite - p1->ps_bwrite; 957 pr->ps_phread = p2->ps_phread - p1->ps_phread; 958 pr->ps_phwrite = p2->ps_phwrite - p1->ps_phwrite; 959 } 960 961 #endif /* _SEQUENT_ */ 962 963 964 #ifndef HAVE_MEMSET 965 /* This is a replacement for a missing memset function */ 966 void *xmemset(void *loc, int value, size_t len) 967 { 968 char *ptr = loc; 969 970 while (len--) 971 *ptr++ = value; 972 return loc; 973 } 974 #endif /* !HAVE_MEMSET */ 975 976 977 #ifndef HAVE_MEMMOVE 978 /* memmove(): 979 * This is the ANSI form of bcopy() with the arguments backwards... 980 * Unlike memcpy(), it handles overlaps between source and 981 * destination memory 982 */ 983 void * 984 xmemmove(void *vdst, const void *vsrc, size_t len) 985 { 986 const char *src = vsrc; 987 char *dst = vdst; 988 989 if (src == dst) 990 return vdst; 991 992 if (src > dst) { 993 while (len--) 994 *dst++ = *src++; 995 } 996 else { 997 src += len; 998 dst += len; 999 while (len--) 1000 *--dst = *--src; 1001 } 1002 return vdst; 1003 } 1004 #endif /* HAVE_MEMMOVE */ 1005 1006 1007 #ifndef WINNT_NATIVE 1008 #ifdef NEEDtcgetpgrp 1009 pid_t 1010 xtcgetpgrp(int fd) 1011 { 1012 int pgrp; 1013 1014 /* ioctl will handle setting errno correctly. */ 1015 if (ioctl(fd, TIOCGPGRP, (ioctl_t) & pgrp) < 0) 1016 return (-1); 1017 return (pgrp); 1018 } 1019 1020 /* 1021 * XXX: tcsetpgrp is not a macro any more cause on some systems, 1022 * pid_t is a short, but the ioctl() takes a pointer to int (pyr) 1023 * Thanks to Simon Day (simon@pharaoh.cyborg.bt.co.uk) for pointing 1024 * this out. 1025 */ 1026 int 1027 xtcsetpgrp(int fd, int pgrp) 1028 { 1029 return ioctl(fd, TIOCSPGRP, (ioctl_t) &pgrp); 1030 } 1031 1032 #endif /* NEEDtcgetpgrp */ 1033 #endif /* WINNT_NATIVE */ 1034 1035 1036 #ifdef YPBUGS 1037 void 1038 fix_yp_bugs(void) 1039 { 1040 char *mydomain; 1041 1042 extern int yp_get_default_domain (char **); 1043 /* 1044 * PWP: The previous version assumed that yp domain was the same as the 1045 * internet name domain. This isn't allways true. (Thanks to Mat Landau 1046 * <mlandau@bbn.com> for the original version of this.) 1047 */ 1048 if (yp_get_default_domain(&mydomain) == 0) { /* if we got a name */ 1049 extern void yp_unbind (const char *); 1050 1051 yp_unbind(mydomain); 1052 } 1053 } 1054 1055 #endif /* YPBUGS */ 1056 1057 #ifdef STRCOLLBUG 1058 void 1059 fix_strcoll_bug(void) 1060 { 1061 #if defined(NLS) && defined(HAVE_STRCOLL) 1062 /* 1063 * SunOS4 checks the file descriptor from openlocale() for <= 0 1064 * instead of == -1. Someone should tell sun that file descriptor 0 1065 * is valid! Our portable hack: open one so we call it with 0 used... 1066 * We have to call this routine every time the locale changes... 1067 * 1068 * Of course it also tries to free the constant locale "C" it initially 1069 * had allocated, with the sequence 1070 * > setenv LANG "fr" 1071 * > ls^D 1072 * > unsetenv LANG 1073 * But we are smarter than that and just print a warning message. 1074 */ 1075 int fd = -1; 1076 static char *root = "/"; 1077 1078 if (!didfds) 1079 fd = xopen(root, O_RDONLY|O_LARGEFILE); 1080 1081 (void) strcoll(root, root); 1082 1083 if (fd != -1) 1084 xclose(fd); 1085 #endif 1086 } 1087 #endif /* STRCOLLBUG */ 1088 1089 1090 #ifdef OREO 1091 #include <compat.h> 1092 #endif /* OREO */ 1093 1094 void 1095 osinit(void) 1096 { 1097 #ifdef OREO 1098 set42sig(); 1099 setcompat(getcompat() & ~COMPAT_EXEC); 1100 signal(SIGIO, SIG_IGN); /* ignore SIGIO */ 1101 #endif /* OREO */ 1102 1103 #ifdef aiws 1104 { 1105 struct sigstack inst; 1106 inst.ss_sp = xmalloc(4192) + 4192; 1107 inst.ss_onstack = 0; 1108 sigstack(&inst, NULL); 1109 } 1110 #endif /* aiws */ 1111 1112 #ifdef apollo 1113 (void) isapad(); 1114 #endif 1115 1116 #ifdef _SX 1117 /* 1118 * kill(SIGCONT) problems, don't know what this syscall does 1119 * [schott@rzg.mpg.de] 1120 */ 1121 syscall(151, getpid(), getpid()); 1122 #endif /* _SX */ 1123 } 1124 1125 #ifndef HAVE_STRERROR 1126 extern int sys_nerr; 1127 extern char *sys_errlist[]; 1128 char * 1129 xstrerror(int i) 1130 { 1131 if (i >= 0 && i < sys_nerr) { 1132 return sys_errlist[i]; 1133 } else { 1134 static char *errbuf; /* = NULL; */ 1135 1136 xfree(errbuf); 1137 errbuf = xasprintf(CGETS(23, 13, "Unknown Error: %d"), i); 1138 return errbuf; 1139 } 1140 } 1141 #endif /* !HAVE_STRERROR */ 1142 1143 #ifndef HAVE_GETHOSTNAME 1144 # if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE) 1145 # include <sys/utsname.h> 1146 # endif /* !_MINIX && !__EMX__ && !WINNT_NATIVE */ 1147 1148 int 1149 xgethostname(char *name, int namlen) 1150 { 1151 # if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE) 1152 int i, retval; 1153 struct utsname uts; 1154 1155 retval = uname(&uts); 1156 1157 # ifdef DEBUG 1158 xprintf(CGETS(23, 14, "sysname: %s\n"), uts.sysname); 1159 xprintf(CGETS(23, 15, "nodename: %s\n"), uts.nodename); 1160 xprintf(CGETS(23, 16, "release: %s\n"), uts.release); 1161 xprintf(CGETS(23, 17, "version: %s\n"), uts.version); 1162 xprintf(CGETS(23, 18, "machine: %s\n"), uts.machine); 1163 # endif /* DEBUG */ 1164 i = strlen(uts.nodename) + 1; 1165 (void) strncpy(name, uts.nodename, i < namlen ? i : namlen); 1166 1167 return retval; 1168 # else /* !_MINIX && !__EMX__ */ 1169 if (namlen > 0) { 1170 # ifdef __EMX__ 1171 (void) strncpy(name, "OS/2", namlen); 1172 # else /* _MINIX */ 1173 (void) strncpy(name, "minix", namlen); 1174 # endif /* __EMX__ */ 1175 name[namlen-1] = '\0'; 1176 } 1177 return(0); 1178 #endif /* _MINIX && !__EMX__ */ 1179 } /* end xgethostname */ 1180 #endif /* !HAVE_GETHOSTNAME */ 1181 1182 #ifndef HAVE_NICE 1183 # if defined(_MINIX) && defined(NICE) 1184 # undef _POSIX_SOURCE /* redefined in <lib.h> */ 1185 # undef _MINIX /* redefined in <lib.h> */ 1186 # undef HZ /* redefined in <minix/const.h> */ 1187 # include <lib.h> 1188 # endif /* _MINIX && NICE */ 1189 int 1190 xnice(int incr) 1191 { 1192 #if defined(_MINIX) && defined(NICE) 1193 return callm1(MM, NICE, incr, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR); 1194 #else 1195 return /* incr ? 0 : */ 0; 1196 #endif /* _MINIX && NICE */ 1197 } /* end xnice */ 1198 #endif /* !HAVE_NICE */ 1199 1200 #ifndef HAVE_GETCWD 1201 static char *strnrcpy (char *, char *, size_t); 1202 1203 /* xgetcwd(): 1204 * Return the pathname of the current directory, or return 1205 * an error message in pathname. 1206 */ 1207 1208 # ifdef hp9000s500 1209 /* 1210 * From: Bernd Mohr <mohr@faui77.informatik.uni-erlangen.de> 1211 * I also ported the tcsh to the HP9000 Series 500. This computer 1212 * is a little bit different than the other HP 9000 computer. It has 1213 * a HP Chip instead of a Motorola CPU and it is no "real" UNIX. It runs 1214 * HP-UX which is emulated in top of a HP operating system. So, the last 1215 * supported version of HP-UX is 5.2 on the HP9000s500. This has two 1216 * consequences: it supports no job control and it has a filesystem 1217 * without "." and ".." !!! 1218 */ 1219 char * 1220 xgetcwd(char *pathname, size_t pathlen) 1221 { 1222 char pathbuf[MAXPATHLEN]; /* temporary pathname buffer */ 1223 char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */ 1224 dev_t rdev; /* root device number */ 1225 DIR *dirp = NULL; /* directory stream */ 1226 ino_t rino; /* root inode number */ 1227 off_t rsize; /* root size */ 1228 struct direct *dir; /* directory entry struct */ 1229 struct stat d, dd; /* file status struct */ 1230 int serrno; 1231 1232 *pnptr = '\0'; 1233 (void) stat("/.", &d); 1234 rdev = d.st_dev; 1235 rino = d.st_ino; 1236 rsize = d.st_size; 1237 for (;;) { 1238 if (stat(".", &d) == -1) { 1239 (void) xsnprintf(pathname, pathlen, CGETS(23, 24, 1240 "getcwd: Cannot stat \".\" (%s)"), strerror(errno)); 1241 goto fail; 1242 } 1243 if (d.st_ino == rino && d.st_dev == rdev && d.st_size == rsize) 1244 break; /* reached root directory */ 1245 if ((dirp = opendir("..")) == NULL) { 1246 (void) xsnprintf(pathname, pathlen, CGETS(23, 19, 1247 "getcwd: Cannot open \"..\" (%s)"), strerror(errno)); 1248 goto fail; 1249 } 1250 if (chdir("..") == -1) { 1251 (void) xsnprintf(pathname, pathlen, CGETS(23, 20, 1252 "getcwd: Cannot chdir to \"..\" (%s)"), strerror(errno)); 1253 goto fail; 1254 } 1255 do { 1256 if ((dir = readdir(dirp)) == NULL) { 1257 (void) xsnprintf(pathname, pathlen, 1258 CGETS(23, 21, "getcwd: Read error in \"..\" (%s)"), 1259 strerror(errno)); 1260 goto fail; 1261 } 1262 if (stat(dir->d_name, &dd) == -1) { 1263 (void) xsnprintf(pathname, pathlen, 1264 CGETS(23, 25, "getcwd: Cannot stat directory \"%s\" (%s)"), 1265 dir->d_name, strerror(errno)); 1266 goto fail; 1267 } 1268 } while (dd.st_ino != d.st_ino || 1269 dd.st_dev != d.st_dev || 1270 dd.st_size != d.st_size); 1271 closedir(dirp); 1272 dirp = NULL; 1273 pnptr = strnrcpy(dirp->d_name, pnptr, pnptr - pathbuf); 1274 pnptr = strnrcpy("/", pnptr, pnptr - pathbuf); 1275 } 1276 1277 if (*pnptr == '\0') /* current dir == root dir */ 1278 (void) strncpy(pathname, "/", pathlen); 1279 else { 1280 (void) strncpy(pathname, pnptr, pathlen); 1281 pathname[pathlen - 1] = '\0'; 1282 if (chdir(pnptr) == -1) { 1283 (void) xsnprintf(pathname, MAXPATHLEN, CGETS(23, 22, 1284 "getcwd: Cannot change back to \".\" (%s)"), 1285 strerror(errno)); 1286 return NULL; 1287 } 1288 } 1289 return pathname; 1290 1291 fail: 1292 serrno = errno; 1293 (void) chdir(strnrcpy(".", pnptr, pnptr - pathbuf)); 1294 errno = serrno; 1295 return NULL; 1296 } 1297 1298 # else /* ! hp9000s500 */ 1299 1300 1301 char * 1302 xgetcwd(char *pathname, size_t pathlen) 1303 { 1304 DIR *dp; 1305 struct dirent *d; 1306 1307 struct stat st_root, st_cur, st_next, st_dotdot; 1308 char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2]; 1309 char *pathptr, *nextpathptr, *cur_name_add; 1310 int save_errno = 0; 1311 1312 /* find the inode of root */ 1313 if (stat("/", &st_root) == -1) { 1314 (void) xsnprintf(pathname, pathlen, CGETS(23, 23, 1315 "getcwd: Cannot stat \"/\" (%s)"), 1316 strerror(errno)); 1317 return NULL; 1318 } 1319 pathbuf[MAXPATHLEN - 1] = '\0'; 1320 pathptr = &pathbuf[MAXPATHLEN - 1]; 1321 nextpathbuf[MAXPATHLEN - 1] = '\0'; 1322 cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1]; 1323 1324 /* find the inode of the current directory */ 1325 if (lstat(".", &st_cur) == -1) { 1326 (void) xsnprintf(pathname, pathlen, CGETS(23, 24, 1327 "getcwd: Cannot stat \".\" (%s)"), 1328 strerror(errno)); 1329 return NULL; 1330 } 1331 nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf); 1332 1333 /* Descend to root */ 1334 for (;;) { 1335 1336 /* look if we found root yet */ 1337 if (st_cur.st_ino == st_root.st_ino && 1338 DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) { 1339 (void) strncpy(pathname, *pathptr != '/' ? "/" : pathptr, pathlen); 1340 pathname[pathlen - 1] = '\0'; 1341 return pathname; 1342 } 1343 1344 /* open the parent directory */ 1345 if (stat(nextpathptr, &st_dotdot) == -1) { 1346 (void) xsnprintf(pathname, pathlen, CGETS(23, 25, 1347 "getcwd: Cannot stat directory \"%s\" (%s)"), 1348 nextpathptr, strerror(errno)); 1349 return NULL; 1350 } 1351 if ((dp = opendir(nextpathptr)) == NULL) { 1352 (void) xsnprintf(pathname, pathlen, CGETS(23, 26, 1353 "getcwd: Cannot open directory \"%s\" (%s)"), 1354 nextpathptr, strerror(errno)); 1355 return NULL; 1356 } 1357 1358 /* look in the parent for the entry with the same inode */ 1359 if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) { 1360 /* Parent has same device. No need to stat every member */ 1361 for (d = readdir(dp); d != NULL; d = readdir(dp)) { 1362 #ifdef __clipper__ 1363 if (((unsigned long)d->d_ino & 0xffff) == st_cur.st_ino) 1364 break; 1365 #else 1366 if (d->d_ino == st_cur.st_ino) 1367 break; 1368 #endif 1369 } 1370 } 1371 else { 1372 /* 1373 * Parent has a different device. This is a mount point so we 1374 * need to stat every member 1375 */ 1376 for (d = readdir(dp); d != NULL; d = readdir(dp)) { 1377 if (ISDOT(d->d_name) || ISDOTDOT(d->d_name)) 1378 continue; 1379 (void)strncpy(cur_name_add, d->d_name, 1380 (size_t) (&nextpathbuf[sizeof(nextpathbuf) - 1] - cur_name_add)); 1381 if (lstat(nextpathptr, &st_next) == -1) { 1382 /* 1383 * We might not be able to stat() some path components 1384 * if we are using afs, but this is not an error as 1385 * long as we find the one we need; we also save the 1386 * first error to report it if we don't finally succeed. 1387 */ 1388 if (save_errno == 0) 1389 save_errno = errno; 1390 continue; 1391 } 1392 /* check if we found it yet */ 1393 if (st_next.st_ino == st_cur.st_ino && 1394 DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev)) 1395 break; 1396 } 1397 } 1398 if (d == NULL) { 1399 (void) xsnprintf(pathname, pathlen, CGETS(23, 27, 1400 "getcwd: Cannot find \".\" in \"..\" (%s)"), 1401 strerror(save_errno ? save_errno : ENOENT)); 1402 closedir(dp); 1403 return NULL; 1404 } 1405 else 1406 save_errno = 0; 1407 st_cur = st_dotdot; 1408 pathptr = strnrcpy(pathptr, d->d_name, pathptr - pathbuf); 1409 pathptr = strnrcpy(pathptr, "/", pathptr - pathbuf); 1410 nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf); 1411 *cur_name_add = '\0'; 1412 closedir(dp); 1413 } 1414 } /* end getcwd */ 1415 # endif /* hp9000s500 */ 1416 1417 /* strnrcpy(): 1418 * Like strncpy, going backwards and returning the new pointer 1419 */ 1420 static char * 1421 strnrcpy(char *ptr, char *str, size_t siz) 1422 { 1423 int len = strlen(str); 1424 if (siz == 0) 1425 return ptr; 1426 1427 while (len && siz--) 1428 *--ptr = str[--len]; 1429 1430 return (ptr); 1431 } /* end strnrcpy */ 1432 #endif /* !HAVE_GETCWD */ 1433 1434 #ifdef apollo 1435 /*** 1436 *** Domain/OS 1437 ***/ 1438 #include <apollo/base.h> 1439 #include <apollo/loader.h> 1440 #include <apollo/error.h> 1441 1442 1443 static char * 1444 apperr(status_$t *st) 1445 { 1446 static char *buf; /* = NULL */ 1447 short e_subl, e_modl, e_codel; 1448 error_$string_t e_sub, e_mod, e_code; 1449 1450 error_$get_text(*st, e_sub, &e_subl, e_mod, &e_modl, e_code, &e_codel); 1451 e_sub[e_subl] = '\0'; 1452 e_code[e_codel] = '\0'; 1453 e_mod[e_modl] = '\0'; 1454 xfree(buf); 1455 buf = xasprintf("%s (%s/%s)", e_code, e_sub, e_mod); 1456 1457 return(buf); 1458 } 1459 1460 static int 1461 llib(Char *s) 1462 { 1463 short len = Strlen(s); 1464 status_$t st; 1465 char *t; 1466 1467 loader_$inlib(t = short2str(s), len, &st); 1468 if (st.all != status_$ok) 1469 stderror(ERR_SYSTEM, t, apperr(&st)); 1470 } 1471 1472 /*ARGSUSED*/ 1473 void 1474 doinlib(Char **v, struct command *c) 1475 { 1476 Char **globbed; 1477 1478 setname(short2str(*v++)); 1479 v = glob_all_or_error(v); 1480 globbed = v; 1481 cleanup_push(globbed, blk_cleanup); 1482 1483 while (v && *v) 1484 llib(*v++); 1485 cleanup_until(globbed); 1486 } 1487 1488 int 1489 getv(Char *v) 1490 { 1491 if (eq(v, STRbsd43)) 1492 return(1); 1493 else if (eq(v, STRsys53)) 1494 return(0); 1495 else 1496 stderror(ERR_NAME | ERR_SYSTEM, short2str(v), 1497 CGETS(23, 28, "Invalid system type")); 1498 /*NOTREACHED*/ 1499 return(0); 1500 } 1501 1502 /*ARGSUSED*/ 1503 void 1504 dover(Char **v, struct command *c) 1505 { 1506 Char *p; 1507 1508 setname(short2str(*v++)); 1509 if (!*v) { 1510 if (!(p = tgetenv(STRSYSTYPE))) 1511 stderror(ERR_NAME | ERR_STRING, 1512 CGETS(23, 29, "System type is not set")); 1513 xprintf("%S\n", p); 1514 } 1515 else { 1516 tsetenv(STRSYSTYPE, getv(*v) ? STRbsd43 : STRsys53); 1517 dohash(NULL, NULL); 1518 } 1519 } 1520 1521 /* 1522 * Many thanks to rees@citi.umich.edu (Jim Rees) and 1523 * mathys@ssdt-tempe.sps.mot.com (Yves Mathys) 1524 * For figuring out how to do this... I could have never done 1525 * it without their help. 1526 */ 1527 typedef short enum { 1528 name_$wdir_type, 1529 name_$ndir_type, 1530 name_$node_dir_type, 1531 } name_$dir_type_t; 1532 1533 /*ARGSUSED*/ 1534 void 1535 dorootnode(Char **v, struct command *c) 1536 { 1537 name_$dir_type_t dirtype = name_$node_dir_type; 1538 uid_$t uid; 1539 status_$t st; 1540 char *name; 1541 short namelen; 1542 1543 setname(short2str(*v++)); 1544 1545 name = short2str(*v); 1546 namelen = strlen(name); 1547 1548 name_$resolve(name, &namelen, &uid, &st); 1549 if (st.all != status_$ok) 1550 stderror(ERR_SYSTEM, name, apperr(&st)); 1551 namelen = 0; 1552 name_$set_diru(&uid, "", &namelen, &dirtype, &st); 1553 if (st.all != status_$ok) 1554 stderror(ERR_SYSTEM, name, apperr(&st)); 1555 dohash(NULL, NULL); 1556 } 1557 1558 int 1559 isapad(void) 1560 { 1561 static int res = -1; 1562 static status_$t st; 1563 1564 if (res == -1) { 1565 int strm; 1566 if (isatty(0)) 1567 strm = 0; 1568 if (isatty(1)) 1569 strm = 1; 1570 if (isatty(2)) 1571 strm = 2; 1572 else { 1573 res = 0; 1574 st.all = status_$ok; 1575 return(res); 1576 } 1577 res = stream_$isavt(&strm, &st); 1578 res = res ? 1 : 0; 1579 } 1580 else { 1581 if (st.all != status_$ok) 1582 stderror(ERR_SYSTEM, "stream_$isavt", apperr(&st)); 1583 } 1584 return(res); 1585 } 1586 #endif 1587 1588 #ifdef __ANDROID__ 1589 #include <stdio.h> 1590 /* Android (<= 2.1?) has an incomplete ttyname implementation. */ 1591 char * 1592 ttyname(int fd) 1593 { 1594 char path[64]; 1595 ssize_t siz; 1596 static char ttyname[32]; 1597 1598 if (!isatty(fd)) 1599 return NULL; 1600 1601 (void)snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); 1602 siz = readlink(path, ttyname, sizeof(ttyname)); 1603 if (siz < 0 || siz == sizeof(ttyname)) 1604 return NULL; 1605 ttyname[siz] = '\0'; 1606 return ttyname; 1607 } 1608 #endif /* __ANDROID__ */ 1609 1610 #if defined(__CYGWIN__) && !defined(NO_CRYPT) 1611 #undef CHAR /* Collides with Win32 API */ 1612 #define WIN32_LEAN_AND_MEAN 1613 #include <windows.h> 1614 #include <sys/cygwin.h> 1615 char * 1616 cygwin_xcrypt(struct passwd *pw, const char *password, const char *expected_pwd) 1617 { 1618 static char invalid_password[] = "\377"; 1619 HANDLE token = cygwin_logon_user(pw, password); 1620 if (token == INVALID_HANDLE_VALUE) 1621 return invalid_password; 1622 CloseHandle(token); 1623 return (char *) expected_pwd; 1624 } 1625 #endif /* __CYGWIN__ && !NO_CRYPT */ 1626