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