1#define Extern extern 2#include <sys/types.h> 3#include <signal.h> 4#define _NSIG NSIG 5#include <errno.h> 6#include <setjmp.h> 7#include "sh.h" 8 9/* -------- io.c -------- */ 10/* #include "sh.h" */ 11 12/* 13 * shell IO 14 */ 15 16static struct iobuf sharedbuf = {AFID_NOBUF}; 17static struct iobuf mainbuf = {AFID_NOBUF}; 18static unsigned bufid = AFID_ID; /* buffer id counter */ 19 20struct ioarg temparg = {0, 0, 0, AFID_NOBUF, 0}; 21 22_PROTOTYPE(static void readhere, (char **name, char *s, int ec )); 23_PROTOTYPE(void pushio, (struct ioarg *argp, int (*fn)())); 24_PROTOTYPE(static int xxchar, (struct ioarg *ap )); 25_PROTOTYPE(void tempname, (char *tname )); 26 27int 28getc(ec) 29register int ec; 30{ 31 register int c; 32 33 if(e.linep > elinep) { 34 while((c=readc()) != '\n' && c) 35 ; 36 err("input line too long"); 37 gflg++; 38 return(c); 39 } 40 c = readc(); 41 if (ec != '\'' && e.iop->task != XGRAVE) { 42 if(c == '\\') { 43 c = readc(); 44 if (c == '\n' && ec != '\"') 45 return(getc(ec)); 46 c |= QUOTE; 47 } 48 } 49 return(c); 50} 51 52void 53unget(c) 54int c; 55{ 56 if (e.iop >= e.iobase) 57 e.iop->peekc = c; 58} 59 60int 61eofc() 62 63{ 64 return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0); 65} 66 67int 68readc() 69{ 70 register c; 71 72 for (; e.iop >= e.iobase; e.iop--) 73 if ((c = e.iop->peekc) != '\0') { 74 e.iop->peekc = 0; 75 return(c); 76 } 77 else { 78 if (e.iop->prev != 0) { 79 if ((c = (*e.iop->iofn)(e.iop->argp, e.iop)) != '\0') { 80 if (c == -1) { 81 e.iop++; 82 continue; 83 } 84 if (e.iop == iostack) 85 ioecho(c); 86 return(e.iop->prev = c); 87 } 88 else if (e.iop->task == XIO && e.iop->prev != '\n') { 89 e.iop->prev = 0; 90 if (e.iop == iostack) 91 ioecho('\n'); 92 return '\n'; 93 } 94 } 95 if (e.iop->task == XIO) { 96 if (multiline) 97 return e.iop->prev = 0; 98 if (talking && e.iop == iostack+1) 99 prs(prompt->value); 100 } 101 } 102 if (e.iop >= iostack) 103 return(0); 104 leave(); 105 /* NOTREACHED */ 106} 107 108void 109ioecho(c) 110char c; 111{ 112 if (flag['v']) 113 write(2, &c, sizeof c); 114} 115 116void 117pushio(argp, fn) 118struct ioarg *argp; 119int (*fn)(); 120{ 121 if (++e.iop >= &iostack[NPUSH]) { 122 e.iop--; 123 err("Shell input nested too deeply"); 124 gflg++; 125 return; 126 } 127 e.iop->iofn = fn; 128 129 if (argp->afid != AFID_NOBUF) 130 e.iop->argp = argp; 131 else { 132 e.iop->argp = ioargstack + (e.iop - iostack); 133 *e.iop->argp = *argp; 134 e.iop->argp->afbuf = e.iop == &iostack[0] ? &mainbuf : &sharedbuf; 135 if (isatty(e.iop->argp->afile) == 0 && 136 (e.iop == &iostack[0] || 137 lseek(e.iop->argp->afile, 0L, 1) != -1)) { 138 if (++bufid == AFID_NOBUF) 139 bufid = AFID_ID; 140 e.iop->argp->afid = bufid; 141 } 142 } 143 144 e.iop->prev = ~'\n'; 145 e.iop->peekc = 0; 146 e.iop->xchar = 0; 147 e.iop->nlcount = 0; 148 if (fn == filechar || fn == linechar) 149 e.iop->task = XIO; 150 else if (fn == gravechar || fn == qgravechar) 151 e.iop->task = XGRAVE; 152 else 153 e.iop->task = XOTHER; 154} 155 156struct io * 157setbase(ip) 158struct io *ip; 159{ 160 register struct io *xp; 161 162 xp = e.iobase; 163 e.iobase = ip; 164 return(xp); 165} 166 167/* 168 * Input generating functions 169 */ 170 171/* 172 * Produce the characters of a string, then a newline, then EOF. 173 */ 174int 175nlchar(ap) 176register struct ioarg *ap; 177{ 178 register int c; 179 180 if (ap->aword == NULL) 181 return(0); 182 if ((c = *ap->aword++) == 0) { 183 ap->aword = NULL; 184 return('\n'); 185 } 186 return(c); 187} 188 189/* 190 * Given a list of words, produce the characters 191 * in them, with a space after each word. 192 */ 193int 194wdchar(ap) 195register struct ioarg *ap; 196{ 197 register char c; 198 register char **wl; 199 200 if ((wl = ap->awordlist) == NULL) 201 return(0); 202 if (*wl != NULL) { 203 if ((c = *(*wl)++) != 0) 204 return(c & 0177); 205 ap->awordlist++; 206 return(' '); 207 } 208 ap->awordlist = NULL; 209 return('\n'); 210} 211 212/* 213 * Return the characters of a list of words, 214 * producing a space between them. 215 */ 216int 217dolchar(ap) 218register struct ioarg *ap; 219{ 220 register char *wp; 221 222 if ((wp = *ap->awordlist++) != NULL) { 223 PUSHIO(aword, wp, *ap->awordlist == NULL? strchar: xxchar); 224 return(-1); 225 } 226 return(0); 227} 228 229static int 230xxchar(ap) 231register struct ioarg *ap; 232{ 233 register int c; 234 235 if (ap->aword == NULL) 236 return(0); 237 if ((c = *ap->aword++) == '\0') { 238 ap->aword = NULL; 239 return(' '); 240 } 241 return(c); 242} 243 244/* 245 * Produce the characters from a single word (string). 246 */ 247int 248strchar(ap) 249register struct ioarg *ap; 250{ 251 register int c; 252 253 if (ap->aword == NULL || (c = *ap->aword++) == 0) 254 return(0); 255 return(c); 256} 257 258/* 259 * Produce quoted characters from a single word (string). 260 */ 261int 262qstrchar(ap) 263register struct ioarg *ap; 264{ 265 register int c; 266 267 if (ap->aword == NULL || (c = *ap->aword++) == 0) 268 return(0); 269 return(c|QUOTE); 270} 271 272/* 273 * Return the characters from a file. 274 */ 275int 276filechar(ap) 277register struct ioarg *ap; 278{ 279 register int i; 280 char c; 281 struct iobuf *bp = ap->afbuf; 282 283 if (ap->afid != AFID_NOBUF) { 284 if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) { 285 if (i) 286 lseek(ap->afile, ap->afpos, 0); 287 do { 288 i = read(ap->afile, bp->buf, sizeof(bp->buf)); 289 } while (i < 0 && errno == EINTR); 290 if (i <= 0) { 291 closef(ap->afile); 292 return 0; 293 } 294 bp->id = ap->afid; 295 bp->ebufp = (bp->bufp = bp->buf) + i; 296 } 297 ap->afpos++; 298 return *bp->bufp++ & 0177; 299 } 300 301 do { 302 i = read(ap->afile, &c, sizeof(c)); 303 } while (i < 0 && errno == EINTR); 304 return(i == sizeof(c)? c&0177: (closef(ap->afile), 0)); 305} 306 307/* 308 * Return the characters from a here temp file. 309 */ 310int 311herechar(ap) 312register struct ioarg *ap; 313{ 314 char c; 315 316 317 if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) { 318 close(ap->afile); 319 c = 0; 320 } 321 return (c); 322 323} 324 325/* 326 * Return the characters produced by a process (`...`). 327 * Quote them if required, and remove any trailing newline characters. 328 */ 329int 330gravechar(ap, iop) 331struct ioarg *ap; 332struct io *iop; 333{ 334 register int c; 335 336 if ((c = qgravechar(ap, iop)&~QUOTE) == '\n') 337 c = ' '; 338 return(c); 339} 340 341int 342qgravechar(ap, iop) 343register struct ioarg *ap; 344struct io *iop; 345{ 346 register int c; 347 348 if (iop->xchar) { 349 if (iop->nlcount) { 350 iop->nlcount--; 351 return('\n'|QUOTE); 352 } 353 c = iop->xchar; 354 iop->xchar = 0; 355 } else if ((c = filechar(ap)) == '\n') { 356 iop->nlcount = 1; 357 while ((c = filechar(ap)) == '\n') 358 iop->nlcount++; 359 iop->xchar = c; 360 if (c == 0) 361 return(c); 362 iop->nlcount--; 363 c = '\n'; 364 } 365 return(c!=0? c|QUOTE: 0); 366} 367 368/* 369 * Return a single command (usually the first line) from a file. 370 */ 371int 372linechar(ap) 373register struct ioarg *ap; 374{ 375 register int c; 376 377 if ((c = filechar(ap)) == '\n') { 378 if (!multiline) { 379 closef(ap->afile); 380 ap->afile = -1; /* illegal value */ 381 } 382 } 383 return(c); 384} 385 386void 387prs(s) 388register char *s; 389{ 390 if (*s) 391 write(2, s, strlen(s)); 392} 393 394void 395putc(c) 396char c; 397{ 398 write(2, &c, sizeof c); 399} 400 401void 402prn(u) 403unsigned u; 404{ 405 prs(itoa(u, 0)); 406} 407 408void 409closef(i) 410register int i; 411{ 412 if (i > 2) 413 close(i); 414} 415 416void 417closeall() 418{ 419 register u; 420 421 for (u=NUFILE; u<NOFILE;) 422 close(u++); 423} 424 425/* 426 * remap fd into Shell's fd space 427 */ 428int 429remap(fd) 430register int fd; 431{ 432 register int i; 433 int map[NOFILE]; 434 435 if (fd < e.iofd) { 436 for (i=0; i<NOFILE; i++) 437 map[i] = 0; 438 do { 439 map[fd] = 1; 440 fd = dup(fd); 441 } while (fd >= 0 && fd < e.iofd); 442 for (i=0; i<NOFILE; i++) 443 if (map[i]) 444 close(i); 445 if (fd < 0) 446 err("too many files open in shell"); 447 } 448 return(fd); 449} 450 451int 452openpipe(pv) 453register int *pv; 454{ 455 register int i; 456 457 if ((i = pipe(pv)) < 0) 458 err("can't create pipe - try again"); 459 return(i); 460} 461 462void 463closepipe(pv) 464register int *pv; 465{ 466 if (pv != NULL) { 467 close(*pv++); 468 close(*pv); 469 } 470} 471 472/* -------- here.c -------- */ 473/* #include "sh.h" */ 474 475/* 476 * here documents 477 */ 478 479struct here { 480 char *h_tag; 481 int h_dosub; 482 struct ioword *h_iop; 483 struct here *h_next; 484}; 485 486static struct here *inhere; /* list of hear docs while parsing */ 487static struct here *acthere; /* list of active here documents */ 488 489void 490markhere(s, iop) 491register char *s; 492struct ioword *iop; 493{ 494 register struct here *h, *lh; 495 496 h = (struct here *) space(sizeof(struct here)); 497 if (h == 0) 498 return; 499 h->h_tag = evalstr(s, DOSUB); 500 if (h->h_tag == 0) 501 return; 502 h->h_iop = iop; 503 iop->io_name = 0; 504 h->h_next = NULL; 505 if (inhere == 0) 506 inhere = h; 507 else 508 for (lh = inhere; lh!=NULL; lh = lh->h_next) 509 if (lh->h_next == 0) { 510 lh->h_next = h; 511 break; 512 } 513 iop->io_flag |= IOHERE|IOXHERE; 514 for (s = h->h_tag; *s; s++) 515 if (*s & QUOTE) { 516 iop->io_flag &= ~ IOXHERE; 517 *s &= ~ QUOTE; 518 } 519 h->h_dosub = iop->io_flag & IOXHERE; 520} 521 522void 523gethere() 524{ 525 register struct here *h, *hp; 526 527 /* Scan here files first leaving inhere list in place */ 528 for (hp = h = inhere; h != NULL; hp = h, h = h->h_next) 529 readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub? 0: '\''); 530 531 /* Make inhere list active - keep list intact for scraphere */ 532 if (hp != NULL) { 533 hp->h_next = acthere; 534 acthere = inhere; 535 inhere = NULL; 536 } 537} 538 539static void 540readhere(name, s, ec) 541char **name; 542register char *s; 543int ec; 544{ 545 int tf; 546 char tname[30]; 547 register c; 548 jmp_buf ev; 549 char line [LINELIM+1]; 550 char *next; 551 552 tempname(tname); 553 *name = strsave(tname, areanum); 554 tf = creat(tname, 0600); 555 if (tf < 0) 556 return; 557 if (newenv(setjmp(errpt = ev)) != 0) 558 unlink(tname); 559 else { 560 pushio(e.iop->argp, e.iop->iofn); 561 e.iobase = e.iop; 562 for (;;) { 563 if (talking && e.iop <= iostack) 564 prs(cprompt->value); 565 next = line; 566 while ((c = getc(ec)) != '\n' && c) { 567 if (ec == '\'') 568 c &= ~ QUOTE; 569 if (next >= &line[LINELIM]) { 570 c = 0; 571 break; 572 } 573 *next++ = c; 574 } 575 *next = 0; 576 if (strcmp(s, line) == 0 || c == 0) 577 break; 578 *next++ = '\n'; 579 write (tf, line, (int)(next-line)); 580 } 581 if (c == 0) { 582 prs("here document `"); prs(s); err("' unclosed"); 583 } 584 quitenv(); 585 } 586 close(tf); 587} 588 589/* 590 * open here temp file. 591 * if unquoted here, expand here temp file into second temp file. 592 */ 593int 594herein(hname, xdoll) 595char *hname; 596int xdoll; 597{ 598 register hf, tf; 599 600 if (hname == 0) 601 return(-1); 602 hf = open(hname, 0); 603 if (hf < 0) 604 return (-1); 605 if (xdoll) { 606 char c; 607 char tname[30]; 608 jmp_buf ev; 609 610 tempname(tname); 611 if ((tf = creat(tname, 0600)) < 0) 612 return (-1); 613 if (newenv(setjmp(errpt = ev)) == 0) { 614 PUSHIO(afile, hf, herechar); 615 setbase(e.iop); 616 while ((c = subgetc(0, 0)) != 0) { 617 c &= ~ QUOTE; 618 write(tf, &c, sizeof c); 619 } 620 quitenv(); 621 } else 622 unlink(tname); 623 close(tf); 624 tf = open(tname, 0); 625 unlink(tname); 626 return (tf); 627 } else 628 return (hf); 629} 630 631void 632scraphere() 633{ 634 register struct here *h; 635 636 for (h = inhere; h != NULL; h = h->h_next) { 637 if (h->h_iop && h->h_iop->io_name) 638 unlink(h->h_iop->io_name); 639 } 640 inhere = NULL; 641} 642 643/* unlink here temp files before a freearea(area) */ 644void 645freehere(area) 646int area; 647{ 648 register struct here *h, *hl; 649 650 hl = NULL; 651 for (h = acthere; h != NULL; h = h->h_next) 652 if (getarea((char *) h) >= area) { 653 if (h->h_iop->io_name != NULL) 654 unlink(h->h_iop->io_name); 655 if (hl == NULL) 656 acthere = h->h_next; 657 else 658 hl->h_next = h->h_next; 659 } else 660 hl = h; 661} 662 663void 664tempname(tname) 665char *tname; 666{ 667 static int inc; 668 register char *cp, *lp; 669 670 for (cp = tname, lp = "/tmp/shtm"; (*cp = *lp++) != '\0'; cp++) 671 ; 672 lp = putn(getpid()*1000 + inc++); 673 for (; (*cp = *lp++) != '\0'; cp++) 674 ; 675} 676