1 /* ---------------------------------------------------------------------
2    $Id: redparent.c 3642 2016-05-02 21:54:38Z arthurcnorman $
3    ---------------------------------------------------------------------
4    (c) 1999-2009 A. Dolzmann and T. Sturm, 1999-2014 T. Sturm
5    ---------------------------------------------------------------------
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9 
10    * Redistributions of source code must retain the relevant
11    copyright notice, this list of conditions and the following
12    disclaimer.
13    * Redistributions in binary form must reproduce the above
14    copyright notice, this list of conditions and the following
15    disclaimer in the documentation and/or other materials provided
16    with the distribution.
17 
18    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22    OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 
31 #include "redfront.h"
32 
33 #define SYSMAXBUFFER 198
34 
35 #define READING_OUTPUT 1
36 #define READING_PROMPT 2
37 #define FINISHED 0
38 
39 extern int debug;
40 extern int verbose;
41 extern int unicode;
42 
43 extern int redfrontcolor;
44 extern int normalcolor;
45 extern int promptcolor;
46 extern int inputcolor;
47 extern int outputcolor;
48 extern int debugcolor;
49 
50 void parent(void);
51 void atoploop(void);
52 char *load_package(const char *);
53 void read_until_first_prompt(char *);
54 char *read_valid_line(char *);
55 int is_too_long(const char *);
56 int badline(const char *);
57 char *append_line(char *,char *);
58 void send_reduce(char *);
59 void read_until_prompt(char *);
60 
61 #include <fcntl.h>
62 
parent(void)63 void parent(void) {
64   sig_installHandlers();
65 
66 #ifdef HAVE_SETLINEBUF
67   setlinebuf(stdout);
68 #endif
69 
70   redclose(MeToReduce[0]);
71   redclose(ReduceToMe[1]);
72 
73   deb_fprintf(stderr,"child: MeToReduce[1]= %d, ReduceToMe[0] = %d\n",
74 	   MeToReduce[1], ReduceToMe[0]);
75 
76   atoploop();
77 }
78 
atoploop(void)79 void atoploop(void) {
80   char der_prompt[50],old_prompt[50];
81   char *line = (char *)NULL;
82   char *this_command = (char *)NULL;
83 
84   load_package(unicode ? "redfront,utf8": "redfront");
85 
86   read_until_first_prompt(der_prompt);
87 
88   deb_fprintf(stderr,"parent: read first prompt\n");
89 
90   line_learn_completion(der_prompt);
91 
92   while (1) {
93 
94     signal(SIGINT,SIG_IGN);
95 
96     line = read_valid_line(der_prompt);
97 
98     signal(SIGINT,sig_sigInt);
99 
100     this_command = append_line(this_command,line);
101 
102     send_reduce(line);
103 
104     strcpy(old_prompt,der_prompt);
105 
106     read_until_prompt(der_prompt);
107 
108     if (strcmp(old_prompt,der_prompt) != 0) {
109       line_add_history(this_command);
110       this_command = NULL;
111     }
112   }
113 }
114 
load_package(const char * package)115 char *load_package(const char *package) {
116   char *cmd;
117   int len;
118 
119   len = strlen(package)+strlen("load_package $");
120   cmd = (char *)malloc(len + 1);
121   sprintf(cmd,"load_package %s$",package);
122   send_reduce(cmd);
123 
124   deb_fprintf(stderr,"parent: sending %s\n",cmd);
125 
126   return cmd;
127 }
128 
read_until_first_prompt(char der_prompt[])129 void read_until_first_prompt(char der_prompt[]) {
130   int status=READING_OUTPUT;
131   char buffer[1000];
132   int ncharread;
133   int ii;
134   int pii=0;
135   char ch;
136   struct strbuf *b=(struct strbuf *)0,*t=(struct strbuf *)0;
137 
138   textcolor(normalcolor);
139 
140   while(status != FINISHED) {
141     ncharread = redread(ReduceToMe[0],buffer,1000);
142     for (ii=0; ii < ncharread; ii++) {
143       ch = buffer[ii];
144       if (ch == (char) 0x01 ) {
145 	status = READING_PROMPT;
146 	pii = 0;
147       } else if (ch == (char) 0x02) {
148 	status = FINISHED;
149       }
150       if (status == READING_OUTPUT) {
151 	b = addchar(ch,b);
152       } else if (status == READING_PROMPT) {
153 	if ((int) ch > 31) {
154 	  der_prompt[pii++] = ch;
155 	  t = addchar(ch,t);
156 	}
157       } else {	/* (status == FINISHED) */
158 	der_prompt[pii] = 0x00;
159       }
160     }
161   }
162   b = remtail(t,b);
163   prtbuf(b);
164   fflush(stdout);
165 }
166 
read_valid_line(char der_prompt[])167 char *read_valid_line(char der_prompt[]) {
168   char orig_prompt[50];
169   char *line;
170 
171   strcpy(orig_prompt,der_prompt);
172 
173   der_prompt = line_color_prompt(der_prompt);
174 
175   line = line_read(der_prompt);
176 
177   if (line)
178     while (is_too_long(line)) {
179       line = line_read(der_prompt);
180     }
181   else {
182     if (strcmp(orig_prompt,"?") == 0) {
183       line = line_quit("n");
184     } else if (orig_prompt[strlen(orig_prompt) - 2] == '%') {
185       line = line_quit("(exit)");
186     } else if (orig_prompt[strlen(orig_prompt) - 2] == '>') {
187       line = line_quit("q");
188     } else if (orig_prompt[strlen(orig_prompt) - 2] == ':') {
189       line = line_quit("quit;");
190     } else if (orig_prompt[strlen(orig_prompt) - 2] == '*') {
191       line = line_quit("quit;");
192     } else {
193       line = line_quit("");
194     }
195   }
196 
197   strcpy(der_prompt,orig_prompt);
198 
199   return line;
200 }
201 
is_too_long(const char line[])202 int is_too_long(const char line[]) {
203 #if PSL
204   if (badline(line)) {
205     textcolor(redfrontcolor);
206     printf("redfront: overlong input line\n");
207     textcolor(inputcolor);
208     return 1;
209   }
210 #endif
211   return 0;
212 }
213 
badline(const char line[])214 int badline(const char line[]) {
215   int i=0,n=0;
216 
217   while (n <= SYSMAXBUFFER && line[i]) {
218     if (line[i] == 0x0a)
219       n = 0;
220     i++;
221     n++;
222   }
223   return (n > SYSMAXBUFFER);
224 }
225 
226 
append_line(char * c,char * l)227 char *append_line(char *c,char *l) {
228   char *s;
229   int lenc,lenl;
230 
231   deb_fprintf(stderr,"parent: entering append_line() ... c=%s, l=%s\n",
232 	   (c != (char *)NULL) ? c : "NULL",(l != (char *)NULL) ? l : "NULL");
233 
234   lenc = (c != (char *)NULL) ? strlen(c) : 0;
235   lenl = (l != (char *)NULL) ? strlen(l) : 0;
236 
237   s = malloc((lenc + lenl + 2) * sizeof(char)); /* 2 >= [ |\x0a| ] + |\0| */
238   *s = 0;
239   if (c != (char *)NULL) {
240     strcpy(s,c);
241     if (lenc != 0 && lenl != 0) strcat(s,"\x0a");
242   }
243 
244   if (l != (char *)NULL)
245     strcat(s,l);
246 
247   deb_fprintf(stderr,"parent: s=%s ... leaving append_line()\n",s);
248 
249   return s;
250 }
251 
send_reduce(char line[])252 void send_reduce(char line[]) {
253   char dummy_prompt[50];
254   char ch;
255   int ii;
256   ssize_t ret;
257 
258   deb_fprintf(stderr,"parent: entering send_reduce() ... line=%s\n",line);
259 
260   if (line == (char *)NULL) {
261     ch=0x04;
262     ret = redwrite(MeToReduce[1],&ch,1);
263     ch = 0x0a;
264     ret = redwrite(MeToReduce[1],&ch,1);
265   } else {
266     for (ii=0; line[ii] != 0; ii++) {
267       ch = line[ii] & 0x7f;
268       ret = redwrite(MeToReduce[1],&ch,1);
269       if (ch == 0x0a) {
270 	strcpy(dummy_prompt,"dummy_prompt");
271 	read_until_prompt(dummy_prompt);
272       }
273     }
274     ch = 0x0a;
275     ret = redwrite(MeToReduce[1],&ch,1);
276   }
277 
278   deb_fprintf(stderr,"parent: ... leaving send_reduce()\n");
279 }
280 
read_until_prompt(char der_prompt[])281 void read_until_prompt(char der_prompt[]){
282   int status=READING_OUTPUT;
283   char buffer[1000];
284   int ncharread;
285   int ii;
286   int pii=0;
287   char ch;
288 
289   deb_fprintf(stderr,"parent: entering read_until_prompt() ... der_prompt=%s\n",
290 	   der_prompt);
291 
292   textcolor(normalcolor);
293 
294   while(status != FINISHED) {
295     ncharread = redread(ReduceToMe[0],buffer,1000);
296     if (ncharread < 0) {
297       perror("read_until_prompt");
298       rf_exit(-1);
299     }
300     if (ncharread == 0) {
301 #ifndef NATIVE_WINDOWS
302       /* There is a SIGCHLD in the air, but I already know that it is over. */
303       signal(SIGCHLD, SIG_IGN);
304 #endif
305       line_end_history();
306       line_end();
307       if (verbose) {
308 	textcolor(redfrontcolor);
309 	printf("Redfront normally exiting on EOF from Reduce.\n");
310       }
311       rf_exit(0);
312     }
313     for (ii=0; ii < ncharread; ii++) {
314       ch = buffer[ii];
315       if (ch == (char) 0x01) {
316 	status = READING_PROMPT;
317 	pii = 0;
318       } else if (ch == (char) 0x02) {
319 	status = FINISHED;
320       }
321       if (status == READING_OUTPUT) {
322 	if (ch == (char) 0x03 ) {
323 	  textcolor(outputcolor);
324 	}
325 	else if (ch == (char) 0x04 ) {
326 	  textcolor(normalcolor);
327 	}
328 	else {
329 	  printf("%c",ch);
330 	}
331       } else if (status == READING_PROMPT) {
332 	if ((int) ch > 31)
333 	  der_prompt[pii++] = ch;
334       } else {	/* (status == FINISHED) */
335 	der_prompt[pii] = 0x00;
336       }
337     }
338     fflush(stdout);
339   }
340 
341   deb_fprintf(stderr,"parent: ... leaving read_until_prompt()\n");
342 }
343 
344 /* end of redparent.c */
345