xref: /plan9/sys/src/cmd/rc/here.c (revision 8cc1c73ac888c72077712859b03e7c83105a4b4f)
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