1 /* 2 3 * Copyright (c) 1984, 1985, 1986 AT&T 4 * All Rights Reserved 5 6 * THIS IS UNPUBLISHED PROPRIETARY SOURCE 7 * CODE OF AT&T. 8 * The copyright notice above does not 9 * evidence any actual or intended 10 * publication of such source code. 11 12 */ 13 /* 14 * AT&T Bell Laboratories 15 * 16 */ 17 18 #include "defs.h" 19 #include "io.h" 20 #include "flags.h" 21 #include "name.h" 22 #include "shtype.h" 23 #include "sym.h" 24 #include "stak.h" 25 #include "brkincr.h" 26 #include "builtins.h" 27 #include "history.h" 28 #include "timeout.h" 29 30 /* This module defines the following routines */ 31 NAMPTR checkfor(); 32 void do_whence(); 33 #ifdef ECHO_N 34 char *echo_mode(); 35 #endif /* ECHO_N */ 36 #ifdef apollo 37 void ev_$set_var(); 38 #endif /* apollo */ 39 int genenv(); 40 char *heap(); 41 void meminit(); 42 void mem_scope(); 43 void mem_unscope(); 44 char *movstr(); 45 void name_unscope(); 46 char *qvalup(); 47 void prinscan(); 48 int printnam(); 49 void printflg(); 50 int readvar(); 51 void rmlocal(); 52 char **setenv(); 53 void setlist(); 54 NAMPTR setname(); 55 int syslook(); 56 57 /* This module references the following external routines */ 58 extern void assign(); 59 extern char *bracket_match(); 60 extern unsigned chkid(); 61 #ifdef ECHO_N 62 extern MSG echo_bin; 63 extern MSG echo_opt; 64 #endif /* ECHO_N */ 65 extern char **environ; 66 extern void exitsh(); 67 extern void failed(); 68 extern void free(); 69 extern NAMPTR findnod(); 70 extern char *fullname(); 71 extern char *getstak(); 72 extern struct Amemory *gettree(); 73 extern void gsort(); 74 extern long hist_list(); 75 extern void hist_flush(); 76 extern void initf(); 77 extern void gscan_all(); 78 extern void gscan_some(); 79 extern NAMPTR lookup(); 80 extern void linknod(); 81 extern char *mactrim(); 82 extern char *malloc(); 83 extern char *movstr(); 84 extern unsigned rand(); 85 extern void p_num(); 86 extern void p_str(); 87 extern void p_sub(); 88 extern void p_setout(); 89 extern void scan_all(); 90 extern char *simple(); 91 extern int srand(); 92 extern char *strchr(); 93 extern char *strcpy(); 94 extern void rmnval(); 95 extern void unassign(); 96 extern long time(); 97 extern char *utos(); 98 extern char *valup(); 99 100 static void countnam(); 101 #ifdef ECHO_N 102 static char *echo_arg; 103 #endif /* ECHO_N */ 104 static long get_rand(); 105 static long get_second(); 106 static struct Amemory *inittree(); 107 static void no_export(); 108 static void pr_name(); 109 static void pushnam(); 110 static void pushnid(); 111 static void rehash(); 112 static void rm_node(); 113 static int set_second(); 114 static int set_rand(); 115 static char *staknam(); 116 117 118 static rsflag; /* used to see if "SHELL" has been set in the environment */ 119 static int namec; 120 static char **argnam; 121 static struct Amemory *namebase; 122 123 struct Bfunction seconds = { get_second, set_second}; 124 struct Bfunction randnum = { get_rand, set_rand}; 125 126 127 128 /* ======== variable and string handling ======== */ 129 130 /* 131 * Table lookup routine 132 * The table <syswds> is searched for string <w> and corresponding value is returned 133 */ 134 syslook(w,syswds) 135 register char *w; 136 SYSTAB syswds; 137 { 138 register int first; 139 register SYSPTR syscan; 140 register int c; 141 if(w==0 || (first= *w)==0) 142 return(0); 143 syscan=syswds; 144 while((c= *syscan->sysnam) && c <= first) 145 { 146 if(first == c && eq(w,syscan->sysnam)) 147 return(syscan->sysval); 148 syscan++; 149 } 150 return(0); 151 } 152 153 /* 154 * perform parameter assignment on an argument list 155 */ 156 157 void setlist(arg,xp) 158 register ARGPTR arg; 159 register int xp; 160 { 161 if(is_option(ALLEXP)) 162 xp |= N_EXPORT; 163 while(arg) 164 { 165 register char *s; 166 if(arg->argflag&A_MAC) 167 s=mactrim(arg->argval,0); 168 else 169 s = arg->argval; 170 setname(s, xp); 171 arg=arg->argnxt; 172 if(is_option(EXECPR)) 173 { 174 p_setout(stderr); 175 p_str(s,arg?SP:NL); 176 } 177 } 178 } 179 180 /* 181 * Put <arg> into associative memory. 182 * If <xp> & V_FLAG then the alias list is used instead 183 * If <xp> & S_FLAG then use the current scope only 184 */ 185 186 187 NAMPTR setname(argi, xp) 188 char *argi; 189 int xp; 190 { 191 register char *argscan=argi; 192 register NAMPTR n; 193 register int sep = *argscan; 194 char *sim; 195 if(isalpha(sep) || ((xp&V_FLAG) && !expchar(sep))) 196 { 197 do 198 { 199 sep = *++argscan; 200 } 201 while(isalnum(sep)); 202 /* check for subscript*/ 203 if(sep=='[') 204 { 205 argscan = bracket_match(argscan)+1; 206 } 207 if((sep = *argscan) && sep!='=') 208 failed(argi,notid); 209 *argscan = 0; 210 if(xp&V_FLAG) 211 { 212 n = findnod(argi,alias,1); 213 if(attest(n,T_FLAG|NO_ALIAS)) 214 pattrib(n,~(NO_ALIAS|T_FLAG|N_EXPORT)); 215 } 216 else if(xp&S_FLAG) 217 /* scoped name must be in first tree */ 218 n = findnod(argi,namep,1); 219 else 220 n = lookup(argi); 221 *argscan++ = sep; 222 if(sep == '=') 223 { 224 if(n==PATHNOD || n==ENVNOD || n==SHELLNOD) 225 { 226 if(is_option(RSHFLG)) 227 failed(argi,restricted); 228 if(n==SHELLNOD) 229 { 230 sim = simple(argscan); 231 if(strchr(sim,'r') != NULL) 232 rsflag = 0; /* restricted shell */ 233 } 234 } 235 assign (n, argscan); 236 attrib(n, xp&~(S_FLAG|V_FLAG)); 237 #ifdef apollo 238 if(attest(n,N_EXPORT) && attest(n,N_IMPORT)==0 239 && (xp&(S_FLAG|V_FLAG))==0) 240 { 241 short namlen,vallen; 242 namlen =strlen(n->namid); 243 vallen = strlen(argscan); 244 ev_$set_var(n->namid,&namlen,argscan,&vallen); 245 } 246 #endif /* apollo */ 247 if(n==PATHNOD) 248 { 249 gscan_some(rehash,alias,T_FLAG,T_FLAG); 250 #ifdef ECHO_N 251 echo_arg = NIL; 252 #endif /* ECHO_N */ 253 } 254 if(n==VISINOD || ((n==EDITNOD)&&isnull(VISINOD))) 255 { 256 /* turn on vi or emacs option if editor name is either*/ 257 argscan = simple(argscan); 258 if(gmatch(argscan,"*vi")) 259 { 260 off_option(EDITVI|EMACS|GMACS); 261 on_option(EDITVI); 262 } 263 if(gmatch(argscan,"*macs")) 264 { 265 off_option(EDITVI|EMACS|GMACS); 266 if(*argscan=='g') 267 on_option(GMACS); 268 else 269 on_option(EMACS); 270 } 271 } 272 } 273 return(n); 274 } 275 failed (argi, notid); 276 /* NOTREACHED */ 277 } 278 279 /* 280 * Mark each node is invalid 281 */ 282 283 static void rehash(np) 284 register NAMPTR np; 285 { 286 attrib(np,NO_ALIAS); 287 } 288 289 /* 290 * alias each name to full path name 291 * realias returns the pathname or NULL if not found 292 */ 293 294 char *realias(np) 295 register NAMPTR np; 296 { 297 register char *sp; 298 register char *vp = np->value.namval.cp; 299 int flag = namflag(np)&(N_EXPORT|NO_ALIAS|T_FLAG); 300 /* turn of T_FLAG to avoid recursion */ 301 pattrib(np,~(NO_ALIAS|T_FLAG)); 302 sp = fullname(np->namid); 303 if(sp==NIL) 304 { 305 unassign(np); 306 return(NIL); 307 } 308 else if(*sp!= '/') 309 { 310 sattrib(np,flag); 311 return(NIL); 312 } 313 if(vp==0 || strcmp(sp,vp)!=0) 314 assign(np,sp); 315 /* turn T_FLAG back on */ 316 attrib(np,T_FLAG|N_EXPORT); 317 return(sp); 318 } 319 320 321 int readvar(names,fd,raw) 322 register char **names; 323 FILE *fd; 324 { 325 FILEBLK fb; 326 SHFILE f; 327 register int c; 328 int issep; 329 register NAMPTR n; 330 int checksep = 1; /* set when looking for separators */ 331 STKPTR rel; 332 char *seps; 333 char is_eol; 334 FILE *savef; 335 states |= RWAIT; 336 /* save in history file if S_FLAG is set */ 337 if((raw&S_FLAG) && fc_fix) 338 states |= FIXFLG; 339 raw &= R_FLAG; 340 f = &fb; 341 if(*names) 342 { 343 if(seps=strchr(*names,'?')) 344 *seps = 0; 345 n = lookup(*names++); 346 if(seps) 347 *seps = '?'; 348 } 349 else 350 n = REPLYNOD; 351 rel=(STKPTR)relstak(); 352 seps = qvalup(IFSNOD); 353 if(seps==NULL) 354 seps = sptbnl; 355 savef = input; 356 if(fd==NULL) 357 failed(bread,noquery); 358 if(fd != input) 359 { 360 /* buffer the input stream if possible */ 361 if(fnobuff(fd) && (fd!=stdin || !ispipe(stdin))) 362 setbuf(fd,malloc((unsigned)BUFSIZ)); 363 push(f); 364 initf(fd); 365 } 366 while(1) 367 { 368 c = (raw?readc():nextc()); 369 issep = (strchr(seps,c)!=0); 370 is_eol = eolchar(c); 371 if(checksep && issep && !is_eol) 372 { 373 /* visable adjacent separators signify null fields*/ 374 if(strchr(sptbnl,c)!=0) 375 continue; 376 } 377 checksep = 0; 378 if((issep && *names) || is_eol) /* from non-separator to separator */ 379 { 380 if(*names==NULL && staktop>stakbot) 381 { 382 /* remove trailing separators */ 383 while(strchr(seps,*--staktop)); 384 staktop++; 385 } 386 zerostak(); 387 assign(n,absstak(rel)); setstak(rel); 388 if(is_option(ALLEXP)) 389 attrib(n,N_EXPORT); 390 n = (*names?lookup(*names++):0); 391 if(is_eol) 392 break; 393 checksep = 1; 394 } 395 else /* not a separator */ 396 pushstak(c); 397 } 398 while(n) 399 { 400 assign(n, nullstr); 401 if(is_option(ALLEXP)) 402 attrib(n,N_EXPORT); 403 n = (*names?lookup(*names++):0); 404 } 405 if(savef != fd) 406 pop(1); 407 if(states&FIXFLG) 408 hist_flush(); 409 states &= ~(RWAIT|PROMPT); 410 states |= is_option(INTFLG); 411 return; 412 } 413 414 /* 415 * put string v onto the heap and return the heap pointer 416 */ 417 418 char *heap(v) 419 register char *v; 420 { 421 register char *p; 422 if(v) 423 { 424 movstr(v,p=malloc((unsigned)strlen(v)+1)); 425 return(p); 426 } 427 else 428 return(0); 429 } 430 431 432 /* 433 * print out the name and value of a name-value pair <n> 434 */ 435 436 int printnam(n,flag) 437 register NAMPTR n; 438 register int flag; 439 { 440 register FILE *fd; 441 register char *s; 442 union Namval *up= &n->value.namval; 443 if(trapnote&SIGSET) 444 exitsh(SIGFAIL); 445 fd = output; 446 if(attest(n,NO_ALIAS)==NO_ALIAS) 447 { 448 return(0); 449 } 450 if(is_afunction(n)) 451 { 452 fputs(bltfn,fd); 453 fputs(n->namid,fd); 454 if(flag==0 && n->value.namval.rp->hoffset >=0 ) 455 { 456 fputs(fn_hdr,fd); 457 hist_list(n->value.namval.rp->hoffset,EOF,"\n"); 458 } 459 else 460 putc('\n',fd); 461 return(n->namsz+1); 462 } 463 if(s=valup(n)) 464 { 465 char numbuf[30]; 466 pr_name(n,0); 467 flag = (flag?NL:'='); 468 if (attest (n, ARRAY)) 469 { 470 if(attest(n,INT_GER)) 471 { 472 /* copy to a save place */ 473 strcpy(numbuf,s); 474 s = numbuf; 475 } 476 p_sub((int)up->aray->adot,flag); 477 } 478 else 479 putc(flag,fd); 480 if(flag != NL) 481 p_str(s,NL); 482 return(1); 483 } 484 return(0); 485 } 486 487 /* 488 * print the name of a node followed by the character c 489 */ 490 491 static void pr_name(n,c) 492 register NAMPTR n; 493 int c; 494 { 495 register char *cp = strchr(n->namid,'='); 496 if(cp) 497 *cp = 0; 498 p_str(n->namid,c); 499 if(cp) 500 *cp = '='; 501 } 502 503 static void pushnid(np) 504 NAMPTR np; 505 { 506 *argnam++ = np->namid; 507 namec++; 508 if(attest(np,ARRAY)) 509 arayp(np)->adot = arayp(np)->maxi; 510 } 511 512 /* 513 * print the nodes in tree <root> which have attributes <flag> set 514 */ 515 516 void prinscan(file,flag,root,option) 517 FILE *file; 518 struct Amemory *root; 519 { 520 register char **argv; 521 register NAMPTR np; 522 p_setout(file); 523 argv = argnam = (char**)locstak(); 524 namec = 0; 525 if(flag) 526 gscan_some(pushnid,root,flag,flag); 527 else 528 gscan_all(pushnid,root); 529 gsort(argv,namec); 530 while(namec--) 531 { 532 { 533 register char *cp; 534 if(cp = strchr(*argv,'=')) 535 *cp = 0; 536 np = checkfor(*argv++,root); 537 if(cp) 538 *cp = '='; 539 } 540 if(np) 541 { 542 if(attest(np,ARRAY)) 543 { 544 register struct Namaray *ap = arayp (np); 545 register int i, imax; 546 i = ap->adot = 0; 547 imax = ap->maxi; 548 for (; i <= imax; i++) 549 { 550 ap->adot = i; 551 if (ap->val[i]) 552 printnam(np,option); 553 } 554 } 555 else 556 printnam(np,option); 557 } 558 } 559 } 560 561 static char *staknam(n,value) 562 char * value; 563 register NAMPTR n; 564 { 565 register char *p,*q; 566 q = getstak(strlen(n->namid)+strlen(value)+2); 567 p=movstr(n->namid,q); 568 *p++ = '='; 569 strcpy(p,value); 570 return(q); 571 } 572 573 574 void printflg(n) 575 register NAMPTR n; 576 { 577 register SYSPTR syscan; 578 register int val; 579 if (namflag(n) != N_DEFAULT) 580 { 581 syscan=attributes; 582 while(*syscan->sysnam) 583 { 584 val = syscan->sysval; 585 if(attest(n,val)==val) 586 { 587 p_str(syscan->sysnam,SP); 588 if (attest (n, L_JUST|R_JUST|Z_FILL)) 589 p_num(n->namsz,SP); 590 if(val == (BLT_NOD|INT_GER)) 591 break; 592 } 593 if(val == INT_GER && attest(n,INT_GER)) 594 { 595 if(n->namsz != 10) 596 { 597 p_str(intbase,SP); 598 p_num(n->namsz,SP); 599 } 600 break; 601 } 602 syscan++; 603 } 604 pr_name(n,NL); 605 } 606 } 607 608 int genenv() 609 { 610 register char **e=environ; 611 register NAMPTR n; 612 rsflag = 1; 613 if(e) 614 { 615 while(*e) 616 { 617 n = setname(*e, (N_IMPORT|N_EXPORT)); 618 n->namid = *e++; 619 } 620 } 621 return(rsflag); 622 } 623 624 625 static void countnam() 626 { 627 namec++; 628 } 629 630 631 static void pushnam(n) 632 register NAMPTR n; 633 { 634 register char *value; 635 if(attest(n,N_IMPORT)) 636 *argnam++ = n->namid; 637 else if(value=valup(n)) 638 *argnam++ = staknam(n,value); 639 } 640 641 /* 642 * Generate the environment list for the child. 643 */ 644 645 646 char **setenv() 647 { 648 register char **er; 649 namec = 0; 650 /* L_ARGNOD gets generated automatically as full path name of command */ 651 pattrib(L_ARGNOD,~N_EXPORT); 652 gscan_some (countnam,namep, N_EXPORT|N_IMPORT, N_EXPORT); 653 er = (char**)getstak((namec+2)*BYTESPERWORD); 654 argnam = ++er; 655 gscan_some (pushnam, namep, N_EXPORT|N_IMPORT, N_EXPORT); 656 *argnam++ = 0; 657 return(er); 658 } 659 660 /* 661 * Initialize the shell name and alias table 662 */ 663 664 void meminit() 665 { 666 register NAMPTR np; 667 bltin_nodes = (NAMPTR)malloc((unsigned)(NNODES*sizeof(struct Namnod))); 668 namebase = namep = inittree(node_names,bltin_nodes,0); 669 /* set up random number generator */ 670 #ifdef apollo 671 (PPIDNOD)->value.namval.cp = (char*)(&ppid); 672 (L_ARGNOD)->value.namval.cp = (char*)(&lastarg); 673 (TMOUTNOD)->value.namval.cp = (char*)(&timeout); 674 (SECONDS)->value.namval.cp = (char*)(&seconds); 675 (MCHKNOD)->value.namval.cp = (char*)(&mailchk); 676 (RANDNOD)->value.namval.cp = (char*)(&randnum); 677 #endif /* apollo */ 678 namflag(RANDNOD) = N_FREE|INT_GER|BLT_NOD; 679 /* set up the seconds clock */ 680 namflag(SECONDS) = N_FREE|INT_GER|BLT_NOD; 681 set_second(0L); 682 namflag(MCHKNOD) = N_FREE|INT_GER; 683 namflag(TMOUTNOD) = INT_GER; 684 namflag(PPIDNOD) = (N_FREE|INT_GER|N_RDONLY); 685 namflag(L_ARGNOD) = N_FREE|IN_DIR; 686 np = (NAMPTR)malloc(NALIAS*sizeof(struct Namnod)); 687 alias = inittree(alias_names,np,N_EXPORT); 688 prnames = gettree(MEMSIZE/4); 689 } 690 691 /* 692 * re-initialize name-value pairs after fork 693 */ 694 695 696 static struct Amemory *inittree(name_vals,nodes,atflag) 697 struct name_value *name_vals; 698 NAMPTR nodes; 699 { 700 register struct Amemory *treep; 701 register NAMPTR np; 702 register struct name_value *nv; 703 int flag; 704 treep = gettree (MEMSIZE); 705 for(np=nodes,nv=name_vals;*nv->nv_name;nv++,np++) 706 { 707 np->namid = nv->nv_name; 708 np->value.namval.cp = nv->nv_value; 709 flag = 0; 710 #ifdef apollo 711 if(*nv->nv_value==0) 712 np->value.namval.cp = 0; 713 else 714 #else 715 if(nv->nv_value) 716 #endif /* apollo */ 717 { 718 flag = atflag|N_FREE; 719 if(atflag && *nv->nv_value=='/') 720 flag |= T_FLAG; 721 } 722 sattrib(np,flag); 723 np->namsz = 10; 724 linknod (np, treep); 725 } 726 return(treep); 727 } 728 729 /* 730 * create a new environment scope 731 */ 732 733 void mem_scope(envlist) 734 ARGPTR envlist; 735 { 736 register struct Amemory *sav_namep = namep; 737 register struct Amemory *newscope; 738 newscope = gettree(MEMSIZE/8); 739 newscope->nexttree = sav_namep; 740 namep = newscope; 741 setlist(envlist,N_EXPORT|S_FLAG); 742 newscope->nexttree = NULL; 743 namep = sav_namep; 744 scan_all(no_export,newscope); 745 newscope->nexttree = sav_namep; 746 namep = newscope; 747 } 748 749 /* 750 * Temporarily remove name from export list of previous scopes 751 */ 752 753 static void no_export(nnod) 754 register struct Namnod *nnod; 755 { 756 register struct Namnod *np = checkfor(nnod->namid,namep); 757 if(np && attest(np,N_EXPORT)) 758 { 759 pattrib(np,~N_EXPORT); 760 attrib(np,E_FLAG); 761 } 762 } 763 764 /* 765 * free up top environment scope 766 */ 767 768 void mem_unscope() 769 { 770 register struct Amemory *ap = namep; 771 if((namep = ap->nexttree)==NULL) 772 namep = namebase; 773 scan_all(rm_node,ap); 774 free((char*)ap); 775 } 776 777 /* 778 * free up all environment scopes except the first 779 */ 780 781 void name_unscope() 782 { 783 while(namep->nexttree) 784 mem_unscope(); 785 } 786 787 /* 788 * Remove a node and free up all the space 789 * Restate export attribute for hidden nodes if necessary 790 */ 791 static void rm_node(nnod) 792 register struct Namnod *nnod; 793 { 794 register struct Namnod *np = checkfor(nnod->namid,namep); 795 if(np && attest(np,E_FLAG)) 796 { 797 pattrib(np,~E_FLAG); 798 attrib(np,N_EXPORT); 799 } 800 pattrib(nnod,~N_EXPORT); 801 rmlocal(nnod); 802 free((char*)nnod); 803 } 804 805 /* 806 * Remove freeable local space associated with the namval field 807 * of nnod. This includes any strings representing the value(s) of the 808 * node, as well as its dope vector, if it is an array. 809 */ 810 811 void rmlocal (nnod) 812 register struct Namnod *nnod; 813 { 814 register int i; 815 register struct Nodval *nv; 816 register struct Namaray *ap; 817 register union Namval *up = &nnod->value.namval; 818 819 /* return if the node is global or unfreeable */ 820 821 if (attest (nnod, N_EXPORT|N_FREE)) 822 return; 823 /* 824 * If the node is a freeable array, then free both the stringspace 825 * associated with it and its dope vector. 826 */ 827 828 else if (attest (nnod, ARRAY)) 829 { 830 ap = up->aray; 831 i = ap->maxi; 832 while(i >= 0) 833 { 834 nv = ap->val[i--]; 835 if (nv) 836 { 837 if (freeble (nv)) 838 rmnval (unmark (nv)); 839 else 840 { 841 up = &nv->namval; 842 if ((up->cp) && ((nv->namflg & (N_FREE|N_ALLOC)) == 0)) 843 free ((nv->namflg & IN_DIR)?up->up->cp:up->cp); 844 } 845 } 846 } 847 free ((char*)(arayp(nnod))); 848 nnod->value.namval.cp = NULL; 849 } 850 /* 851 * otherwise node is a freeable scalar, so free the string 852 * representing its value. 853 */ 854 else 855 { 856 unassign (nnod); 857 } 858 sattrib (nnod, N_DEFAULT); 859 } 860 861 /* 862 * Get the value of a built-in node 863 * A lookup may not be necessary 864 */ 865 866 char *qvalup(n) 867 register NAMPTR n; 868 { 869 if(namep->nexttree) 870 n = lookup((node_names+(n-bltin_nodes))->nv_name); 871 return(valup(n)); 872 } 873 874 /* 875 * lookup name in trees root and return Namnod pointer with this name. 876 * If none exists, it will not be created. 877 */ 878 879 NAMPTR checkfor(name,root) 880 char *name; 881 struct Amemory *root; 882 { 883 register struct Namnod *np = NULL; 884 register struct Amemory *app = root; 885 struct Namnod *findnod(); 886 while(app && np==NULL) 887 { 888 np = findnod(name,app,0); 889 app = app->nexttree; 890 } 891 return((np==NULL||isnull(np))?NULL:np); 892 } 893 894 /* 895 * for the whence command 896 */ 897 898 void do_whence(com,flag) 899 char **com; 900 register int flag; 901 { 902 register char *a1; 903 register struct Namnod *np; 904 register char *cp; 905 struct Namnod *fp; 906 while(a1 = *++com) 907 { 908 if(flag) 909 fputs(a1,output); 910 np = NULL; 911 /* reserved words first */ 912 if(syslook(a1,reserved)) 913 { 914 if(flag) 915 a1 = is_reserved; 916 } 917 /* non-tracked aliases */ 918 else if((np=findnod(a1,alias,CHK_FOR)) && !isnull(np) 919 && attest(np,T_FLAG)==0 && (a1=valup(np))) 920 { 921 if(flag) 922 { 923 if(attest(np,N_EXPORT)) 924 cp = is_xalias; 925 else 926 cp = is_alias; 927 fputs(cp,output); 928 } 929 } 930 /* built-in commands next */ 931 else if(syslook(a1,commands)) 932 { 933 if(flag) 934 a1 = is_builtin; 935 } 936 /* functions next */ 937 else if((fp=findnod(a1,prnames,CHK_FOR))&& !isnull(fp)) 938 { 939 if(flag) 940 a1=attest(fp,N_EXPORT)?is_xfunction:is_function; 941 } 942 else 943 { 944 /* find full pathname */ 945 a1 = fullname(a1); 946 if(a1) 947 { 948 if(flag) 949 { 950 /* tracked aliases next */ 951 if(np && attest(np,T_FLAG) && *a1 == '/') 952 fputs(is_talias,output); 953 else 954 fputs(is_,output); 955 } 956 } 957 else 958 { 959 a1 = (flag?notfound:nullstr); 960 exitval |= 1; 961 } 962 } 963 p_str(a1,NL); 964 } 965 } 966 967 /* 968 * these functions are used to get and set the SECONDS variable 969 */ 970 971 static long sec_offset; 972 973 static int set_second(n) 974 long n; 975 { 976 sec_offset = time((long*)0) - n ; 977 } 978 979 static long get_second() 980 { 981 return(time((long*)0)-sec_offset); 982 } 983 984 /* 985 * These functions are used to get and set the RANDOM variable 986 */ 987 988 static int set_rand(n) 989 long n; 990 { 991 srand((int)n); 992 } 993 994 static long get_rand() 995 { 996 return((long)rand()); 997 } 998 999 #ifdef ECHO_N 1000 char *echo_mode() 1001 { 1002 register char *cp; 1003 optflag savopts; 1004 if(echo_arg==0) 1005 { 1006 #ifdef apollo 1007 register NAMPTR np = checkfor("SYSTYPE",namep); 1008 if(np && (cp=valup(np))) 1009 { 1010 echo_arg = (*cp=='b'?echo_opt:minus); 1011 return(echo_arg); 1012 } 1013 #endif /* apollo */ 1014 savopts = flags; 1015 off_option(HASHALL); 1016 cp = fullname(echo_bin+5); 1017 flags = savopts; 1018 if(eq(cp,echo_bin)) 1019 echo_arg = echo_opt; 1020 else 1021 echo_arg = minus; 1022 } 1023 return(echo_arg); 1024 } 1025 #endif /* ECHO_N */ 1026