1 /* ---------------------------------------------------------------------
2    $Id: redparent.c 3050 2015-03-26 15:26:28Z thomas-sturm $
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 dist;
40 extern int MeToReduce[];
41 extern int ReduceToMe[];
42 extern int debug;
43 extern int verbose;
44 extern int unicode;
45 
46 extern int redfrontcolor;
47 extern int normalcolor;
48 extern int promptcolor;
49 extern int inputcolor;
50 extern int outputcolor;
51 extern int debugcolor;
52 
53 void parent(void);
54 void atoploop(void);
55 char *load_package(const char *);
56 void read_until_first_prompt(char *);
57 char *read_valid_line(char *);
58 int is_too_long(const char *);
59 int badline(const char *);
60 char *append_line(char *,char *);
61 void send_reduce(char *);
62 void read_until_prompt(char *);
63 
64 #include <fcntl.h>
65 
parent(void)66 void parent(void) {
67   sig_installHandlers();
68 
69 #ifdef HAVE_SETLINEBUF
70   setlinebuf(stdout);
71 #endif
72 
73   close(MeToReduce[0]);
74   close(ReduceToMe[1]);
75 
76   deb_fprintf(stderr,"child: MeToReduce[1]= %d, ReduceToMe[0] = %d\n",
77 	   MeToReduce[1], ReduceToMe[0]);
78 
79   atoploop();
80 }
81 
atoploop(void)82 void atoploop(void) {
83   char der_prompt[50],old_prompt[50];
84   char *line = (char *)NULL;
85   char *this_command = (char *)NULL;
86 
87   load_package(unicode ? "redfront,utf8": "redfront");
88 
89   read_until_first_prompt(der_prompt);
90 
91   deb_fprintf(stderr,"parent: read first prompt\n");
92 
93   line_learn_completion(der_prompt);
94 
95   while (1) {
96 
97     //    if (dist == PSL)
98       signal(SIGINT,SIG_IGN);
99 
100     line = read_valid_line(der_prompt);
101 
102     //    if (dist == PSL)
103       signal(SIGINT,sig_sigInt);
104 
105     this_command = append_line(this_command,line);
106 
107     send_reduce(line);
108 
109     strcpy(old_prompt,der_prompt);
110 
111     read_until_prompt(der_prompt);
112 
113     if (!CMDHIST || strcmp(old_prompt,der_prompt) != 0) {
114       line_add_history(this_command);
115       this_command = NULL;
116     }
117   }
118 }
119 
load_package(const char * package)120 char *load_package(const char *package) {
121   char *cmd;
122   int len;
123 
124   len = strlen(package)+strlen("load_package $");
125   cmd = (char *)malloc(len + 1);
126   sprintf(cmd,"load_package %s$",package);
127   send_reduce(cmd);
128 
129   deb_fprintf(stderr,"parent: sending %s\n",cmd);
130 
131   return cmd;
132 }
133 
read_until_first_prompt(char der_prompt[])134 void read_until_first_prompt(char der_prompt[]) {
135   int status=READING_OUTPUT;
136   char buffer[1000];
137   int ncharread;
138   int ii;
139   int pii=0;
140   char ch;
141   struct strbuf *b=(struct strbuf *)0,*t=(struct strbuf *)0;
142 
143   textcolor(normalcolor);
144 
145   while(status != FINISHED) {
146     ncharread = read(ReduceToMe[0],buffer,1000);
147     for (ii=0; ii < ncharread; ii++) {
148       ch = buffer[ii];
149       if (ch == (char) 0x01 ) {
150 	status = READING_PROMPT;
151 	pii = 0;
152       } else if (ch == (char) 0x02) {
153 	status = FINISHED;
154       }
155       if (status == READING_OUTPUT) {
156 	b = addchar(ch,b);
157       } else if (status == READING_PROMPT) {
158 	if ((int) ch > 31) {
159 	  der_prompt[pii++] = ch;
160 	  t = addchar(ch,t);
161 	}
162       } else {	/* (status == FINISHED) */
163 	der_prompt[pii] = 0x00;
164       }
165     }
166   }
167   b = remtail(t,b);
168   prtbuf(b);
169   fflush(stdout);
170 }
171 
read_valid_line(char der_prompt[])172 char *read_valid_line(char der_prompt[]) {
173   char orig_prompt[50];
174   char *line;
175 
176   strcpy(orig_prompt,der_prompt);
177 
178   der_prompt = line_color_prompt(der_prompt);
179 
180   line = line_read(der_prompt);
181 
182   if (line)
183     while (is_too_long(line)) {
184       line = line_read(der_prompt);
185     }
186   else {
187     if (strcmp(orig_prompt,"?") == 0) {
188       line = line_quit("n");
189     } else if (orig_prompt[strlen(orig_prompt) - 2] == '%') {
190       line = line_quit("(exit)");
191     } else if (orig_prompt[strlen(orig_prompt) - 2] == '>') {
192       line = line_quit("q");
193     } else if (orig_prompt[strlen(orig_prompt) - 2] == ':') {
194       line = line_quit("quit;");
195     } else if (orig_prompt[strlen(orig_prompt) - 2] == '*') {
196       line = line_quit("quit;");
197     } else {
198       line = line_quit("");
199     }
200   }
201 
202   strcpy(der_prompt,orig_prompt);
203 
204   return line;
205 }
206 
is_too_long(const char line[])207 int is_too_long(const char line[]) {
208   if (dist == PSL && badline(line)) {
209     textcolor(redfrontcolor);
210     printf("redfront: overlong input line\n");
211     textcolor(inputcolor);
212     return 1;
213   }
214   return 0;
215 }
216 
badline(const char line[])217 int badline(const char line[]) {
218   int i=0,n=0;
219 
220   while (n <= SYSMAXBUFFER && line[i]) {
221     if (line[i] == 0x0a)
222       n = 0;
223     i++;
224     n++;
225   }
226   return (n > SYSMAXBUFFER);
227 }
228 
229 
append_line(char * c,char * l)230 char *append_line(char *c,char *l) {
231 #ifdef HAVE_HISTORY
232   char *s;
233   int lenc,lenl;
234 
235   deb_fprintf(stderr,"parent: entering append_line() ... c=%s, l=%s\n",
236 	   (c != (char *)NULL) ? c : "NULL",(l != (char *)NULL) ? l : "NULL");
237 
238   lenc = (c != (char *)NULL) ? strlen(c) : 0;
239   lenl = (l != (char *)NULL) ? strlen(l) : 0;
240 
241   s = malloc((lenc + lenl + 2) * sizeof(char)); /* 2 >= [ |\x0a| ] + |\0| */
242   *s = 0;
243   if (c != (char *)NULL) {
244     strcpy(s,c);
245     if (CMDHIST  && lenc != 0 && lenl != 0) {
246       if (LITHIST)
247 	strcat(s,"\x0a");
248       else {
249 	strcat(s," ");
250 	while (l && isspace(*l))
251 	  l++;
252       }
253     }
254   }
255 
256   if (l != (char *)NULL)
257     strcat(s,l);
258 
259   deb_fprintf(stderr,"parent: s=%s ... leaving append_line()\n",s);
260 
261   return s;
262 #endif
263 }
264 
send_reduce(char line[])265 void send_reduce(char line[]) {
266   char dummy_prompt[50];
267   char ch;
268   int ii;
269   ssize_t ret;
270 
271   deb_fprintf(stderr,"parent: entering send_reduce() ... line=%s\n",line);
272 
273   if (line == (char *)NULL) {
274     ch=0x04;
275     ret = write(MeToReduce[1],&ch,1);
276     ch = 0x0a;
277     ret = write(MeToReduce[1],&ch,1);
278   } else {
279     for (ii=0; line[ii] != 0; ii++) {
280       ch = line[ii] & 0x7f;
281       ret = write(MeToReduce[1],&ch,1);
282       if (ch == 0x0a) {
283 	strcpy(dummy_prompt,"dummy_prompt");
284 	read_until_prompt(dummy_prompt);
285       }
286     }
287     ch = 0x0a;
288     ret = write(MeToReduce[1],&ch,1);
289   }
290 
291   deb_fprintf(stderr,"parent: ... leaving send_reduce()\n");
292 }
293 
read_until_prompt(char der_prompt[])294 void read_until_prompt(char der_prompt[]){
295   int status=READING_OUTPUT;
296   char buffer[1000];
297   int ncharread;
298   int ii;
299   int pii=0;
300   char ch;
301 
302   deb_fprintf(stderr,"parent: entering read_until_prompt() ... der_prompt=%s\n",
303 	   der_prompt);
304 
305   textcolor(normalcolor);
306 
307   while(status != FINISHED) {
308     ncharread = read(ReduceToMe[0],buffer,1000);
309     if (ncharread < 0) {
310       perror("read_until_prompt");
311       rf_exit(-1);
312     }
313     if (ncharread == 0) {
314       /* There is a SIGCHLD in the air, but I already know that it is over. */
315       signal(SIGCHLD, SIG_IGN);
316       line_end_history();
317       line_end();
318       if (verbose) {
319 	textcolor(redfrontcolor);
320 	printf("Redfront normally exiting on EOF from Reduce.\n");
321       }
322       rf_exit(0);
323     }
324     for (ii=0; ii < ncharread; ii++) {
325       ch = buffer[ii];
326       if (ch == (char) 0x01) {
327 	status = READING_PROMPT;
328 	pii = 0;
329       } else if (ch == (char) 0x02) {
330 	status = FINISHED;
331       }
332       if (status == READING_OUTPUT) {
333 	if (ch == (char) 0x03 ) {
334 	  textcolor(outputcolor);
335 	}
336 	else if (ch == (char) 0x04 ) {
337 	  textcolor(normalcolor);
338 	}
339 	else {
340 	  printf("%c",ch);
341 	}
342       } else if (status == READING_PROMPT) {
343 	if ((int) ch > 31)
344 	  der_prompt[pii++] = ch;
345       } else {	/* (status == FINISHED) */
346 	der_prompt[pii] = 0x00;
347       }
348     }
349     fflush(stdout);
350   }
351 
352   deb_fprintf(stderr,"parent: ... leaving read_until_prompt()\n");
353 }
354