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