1 #include "rc.h"
2 #include "exec.h"
3 #include "io.h"
4 #include "fns.h"
5
6 struct here *here, **ehere;
7 int ser = 0;
8 char tmp[] = "/tmp/here0000.0000";
9 char hex[] = "0123456789abcdef";
10
11 void psubst(io*, uchar*);
12 void pstrs(io*, word*);
13
14 void
hexnum(char * p,int n)15 hexnum(char *p, int n)
16 {
17 *p++ = hex[(n>>12)&0xF];
18 *p++ = hex[(n>>8)&0xF];
19 *p++ = hex[(n>>4)&0xF];
20 *p = hex[n&0xF];
21 }
22
23 tree*
heredoc(tree * tag)24 heredoc(tree *tag)
25 {
26 struct here *h = new(struct here);
27
28 if(tag->type != WORD)
29 yyerror("Bad here tag");
30 h->next = 0;
31 if(here)
32 *ehere = h;
33 else
34 here = h;
35 ehere = &h->next;
36 h->tag = tag;
37 hexnum(&tmp[9], getpid());
38 hexnum(&tmp[14], ser++);
39 h->name = strdup(tmp);
40 return token(tmp, WORD);
41 }
42
43 /*
44 * bug: lines longer than NLINE get split -- this can cause spurious
45 * missubstitution, or a misrecognized EOF marker.
46 */
47 #define NLINE 4096
48
49 void
readhere(void)50 readhere(void)
51 {
52 int c, subst;
53 char *s, *tag;
54 char line[NLINE+1];
55 io *f;
56 struct here *h, *nexth;
57
58 for(h = here; h; h = nexth){
59 subst = !h->tag->quoted;
60 tag = h->tag->str;
61 c = Creat(h->name);
62 if(c < 0)
63 yyerror("can't create here document");
64 f = openfd(c);
65 s = line;
66 pprompt();
67 while((c = rchr(runq->cmdfd)) != EOF){
68 if(c == '\n' || s == &line[NLINE]){
69 *s = '\0';
70 if(tag && strcmp(line, tag) == 0)
71 break;
72 if(subst)
73 psubst(f, (uchar *)line);
74 else
75 pstr(f, line);
76 s = line;
77 if(c == '\n'){
78 pprompt();
79 pchr(f, c);
80 }else
81 *s++ = c;
82 }else
83 *s++ = c;
84 }
85 flush(f);
86 closeio(f);
87 cleanhere(h->name);
88 nexth = h->next;
89 efree((char *)h);
90 }
91 here = 0;
92 doprompt = 1;
93 }
94
95 void
psubst(io * f,uchar * s)96 psubst(io *f, uchar *s)
97 {
98 int savec, n;
99 uchar *t, *u;
100 Rune r;
101 word *star;
102
103 while(*s){
104 if(*s != '$'){ /* copy plain text rune */
105 if(*s < Runeself)
106 pchr(f, *s++);
107 else{
108 n = chartorune(&r, (char *)s);
109 while(n-- > 0)
110 pchr(f, *s++);
111 }
112 }else{ /* $something -- perform substitution */
113 t = ++s;
114 if(*t == '$')
115 pchr(f, *t++);
116 else{
117 while(*t && idchr(*t))
118 t++;
119 savec = *t;
120 *t = '\0';
121 n = 0;
122 for(u = s; *u && '0' <= *u && *u <= '9'; u++)
123 n = n*10 + *u - '0';
124 if(n && *u == '\0'){
125 star = vlook("*")->val;
126 if(star && 1 <= n && n <= count(star)){
127 while(--n)
128 star = star->next;
129 pstr(f, star->word);
130 }
131 }else
132 pstrs(f, vlook((char *)s)->val);
133 *t = savec;
134 if(savec == '^')
135 t++;
136 }
137 s = t;
138 }
139 }
140 }
141
142 void
pstrs(io * f,word * a)143 pstrs(io *f, word *a)
144 {
145 if(a){
146 while(a->next && a->next->word){
147 pstr(f, a->word);
148 pchr(f, ' ');
149 a = a->next;
150 }
151 pstr(f, a->word);
152 }
153 }
154