source: trunk/minix/commands/sh/sh5.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 10.9 KB
RevLine 
[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
15static struct iobuf sharedbuf = {AFID_NOBUF};
16static struct iobuf mainbuf = {AFID_NOBUF};
17static unsigned bufid = AFID_ID; /* buffer id counter */
18
19struct 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
26int
27getc(ec)
28register 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
51void
52unget(c)
53int c;
54{
55 if (e.iop >= e.iobase)
56 e.iop->peekc = c;
57}
58
59int
60eofc()
61
62{
63 return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
64}
65
66int
67readc()
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
107void
108ioecho(c)
109char c;
110{
111 if (flag['v'])
112 write(2, &c, sizeof c);
113}
114
115void
116pushio(argp, fn)
117struct ioarg *argp;
118int (*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
155struct io *
156setbase(ip)
157struct 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 */
173int
174nlchar(ap)
175register 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 */
192int
193wdchar(ap)
194register 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 */
215int
216dolchar(ap)
217register 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
228static int
229xxchar(ap)
230register 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 */
246int
247strchar(ap)
248register 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 */
260int
261qstrchar(ap)
262register 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 */
274int
275filechar(ap)
276register 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 */
309int
310herechar(ap)
311register 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 */
328int
329gravechar(ap, iop)
330struct ioarg *ap;
331struct io *iop;
332{
333 register int c;
334
335 if ((c = qgravechar(ap, iop)&~QUOTE) == '\n')
336 c = ' ';
337 return(c);
338}
339
340int
341qgravechar(ap, iop)
342register struct ioarg *ap;
343struct 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 */
370int
371linechar(ap)
372register 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
385void
386prs(s)
387register char *s;
388{
389 if (*s)
390 write(2, s, strlen(s));
391}
392
393void
394putc(c)
395char c;
396{
397 write(2, &c, sizeof c);
398}
399
400void
401prn(u)
402unsigned u;
403{
404 prs(itoa(u, 0));
405}
406
407void
408closef(i)
409register int i;
410{
411 if (i > 2)
412 close(i);
413}
414
415void
416closeall()
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 */
427int
428remap(fd)
429register 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
450int
451openpipe(pv)
452register 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
461void
462closepipe(pv)
463register 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
478struct here {
479 char *h_tag;
480 int h_dosub;
481 struct ioword *h_iop;
482 struct here *h_next;
483};
484
485static struct here *inhere; /* list of hear docs while parsing */
486static struct here *acthere; /* list of active here documents */
487
488void
489inithere()
490{
491 inhere=acthere=(struct here*)0;
492}
493
494void
495markhere(s, iop)
496register char *s;
497struct 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
527void
528gethere()
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
544static void
545readhere(name, s, ec)
546char **name;
547register char *s;
548int 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 */
596int
597herein(hname, xdoll)
598char *hname;
599int 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&QUOTE && !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
637void
638scraphere()
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) */
650void
651freehere(area)
652int 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
669void
670tempname(tname)
671char *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}
Note: See TracBrowser for help on using the repository browser.