1 /* ---------------------------------------------------------------------
2    $Id: redfront.c 3960 2017-03-19 08:01:16Z 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 /* Exportable variables */
34 
35 int dist=0;
36 
37 int reduceProcessID;
38 
39 int MeToReduce[2];
40 int ReduceToMe[2];
41 
42 int verbose = 0;
43 int unicode = 0;
44 int color = 1;
45 char *memory=NULL;
46 int xargstart;
47 
48 #define DEFAULT_REDFRONTCOLOR MAGENTA /* REDFRONT output */
49 #define DEFAULT_NORMALCOLOR USER      /* REDUCE terminal output */
50 #define DEFAULT_PROMPTCOLOR BLACK     /* REDUCE prompt */
51 #define DEFAULT_INPUTCOLOR RED	      /* REDUCE input line */
52 #define DEFAULT_OUTPUTCOLOR BLUE      /* REDUCE mathprint output */
53 #define DEFAULT_DEBUGCOLOR CYAN	      /* REDFRONT DEBUG output" */
54 
55 int redfrontcolor = DEFAULT_REDFRONTCOLOR; /* REDFRONT output */
56 int normalcolor = DEFAULT_NORMALCOLOR;	   /* REDUCE terminal output */
57 int promptcolor = DEFAULT_PROMPTCOLOR;	   /* REDUCE prompt */
58 int inputcolor = DEFAULT_INPUTCOLOR;	   /* REDUCE input line */
59 int outputcolor = DEFAULT_OUTPUTCOLOR;	   /* REDUCE mathprint output */
60 int debugcolor = DEFAULT_DEBUGCOLOR;	   /* REDFRONT DEBUG output */
61 
62 int det_dist(char *);
63 void parse_args(int,char **);
64 void init_channels(void);
65 void print_banner(int);
66 int parse_colarg(char *);
67 int map_colour(int);
68 char *parse_memarg(char *,char *);
69 void print_usage(char *);
70 void print_help(char *);
71 int textcolor(int);
72 void textcolor1(int,int,int);
73 void stextcolor1(char *,int,int,int);
74 void resetcolor(void);
75 int vbprintf(const char *,...);
76 void rf_exit(int);
77 char **create_call(int, char **);
78 
main(int argc,char ** argv,char ** envp)79 int main(int argc,char **argv,char **envp) {
80   char **nargv;
81 
82   dist = det_dist(argv[0]);
83 
84   parse_args(argc,argv);
85 
86   deb_init();
87 
88   print_banner(verbose);
89 
90   line_init();
91 
92   line_init_history();
93 
94   init_channels();
95 
96   /* I am preparing the argument for the child's execv() here, because malloc()
97      after fork() might be problematic. */
98   nargv = create_call(argc,argv);
99 
100   if ((reduceProcessID = fork())) {  /* I am not the child */
101 
102     if (reduceProcessID < 0) {  /* Failure */
103       perror("cannot fork()");
104       rf_exit(-1);
105     }
106 
107     deb_fprintf(stderr,"parent: process alive - fork()=%d\n",reduceProcessID);
108 
109     free(nargv);
110 
111     parent();
112 
113   } else {  /* I am the child */
114 
115     deb_fprintf(stderr,"child: process alive - fork()=%d\n",reduceProcessID);
116 
117     child(nargv);
118   }
119 
120   return -1;
121 }
122 
det_dist(char * argv0)123 int det_dist(char *argv0) {
124   char *fn,*bn;
125   int dist = -1;
126   char d[1024] = "";
127 
128   fn = (char *)malloc((strlen(argv0)+1)*sizeof(char));
129   strcpy(fn,argv0);
130   bn = basename(fn);
131   if (strcmp(bn,"rfpsl") == 0)
132     dist = PSL;
133   else if (strcmp(bn,"rfcsl") == 0)
134     dist = CSL;
135   else if (strcmp(bn,"rfcslb") == 0)
136     dist = CSLB;
137   else {
138     printf("Select distribution [csl/cslb/psl] ");
139     scanf("%s",d);
140     if (strcmp(d,"cslb") == 0)
141       dist = CSLB;
142     else if (strcmp(d,"csl") == 0)
143       dist = CSL;
144     else if (strcmp(d,"psl") == 0)
145       dist = PSL;
146   }
147   free(fn);
148   if (dist == -1)
149     exit(-1);
150   return dist;
151 }
152 
parse_args(int argc,char ** argv)153 void parse_args(int argc,char **argv) {
154   int c;
155   extern char *optarg;
156   extern int optind;
157   const char *os;
158   int errflg=0;
159 
160   os = (dist == PSL) ? "bc:huvVm:" : "bc:huvV";
161 
162   while ((c = getopt(argc, argv, os)) != EOF)
163     switch (c) {
164     case 'h':
165       print_help(argv[0]);
166       rf_exit(1);
167       break;
168     case 'b':
169       color = 0;
170       break;
171     case 'c':
172       errflg += parse_colarg(optarg);
173       break;
174     case 'u':
175       unicode = 1;
176       break;
177     case 'v':
178     case 'V':
179       verbose = 1;
180       break;
181     case 'm':
182       memory = optarg;
183       break;
184     case '?':
185       errflg++;
186     }
187 
188   if (errflg) {
189     print_usage(argv[0]);
190     rf_exit(2);
191   }
192 
193   if (strcmp(argv[optind - 1],"--") == 0) {
194     // <options> + "--"
195     xargstart = optind;
196   } else if (dist == PSL && memory == NULL && optind == argc - 1) {
197     // <options> + <memarg>
198     memory = argv[optind];
199     xargstart = argc;
200   } else if (dist == PSL && memory == NULL &&
201 	   optind < argc - 1 && strcmp(argv[optind + 1],"--") == 0) {
202     // <options> + <memarg> + "--"
203     memory = argv[optind];
204     xargstart = optind + 2;
205   } else if (optind == argc) {
206     // <options>
207     xargstart = argc;
208   } else {
209     print_usage(argv[0]);
210     rf_exit(2);
211   }
212 
213   if (dist == PSL) {
214     memory = parse_memarg(memory==NULL ? MEMORY : memory,argv[0]);
215   }
216 }
217 
parse_colarg(char * s)218 int parse_colarg(char *s) {
219   /* Parse the parameter of -c as a string similar to LSCOLORS
220      documented in the ls manpage. The order is redfrontcolor,
221      normalcolor, promptcolor, inputcolor, outputcolor, debugcolor. The
222      default choice corresponds to "fxxxxxbxexgx". At present,
223      background specifications are ignored and upper case (bold face) is
224      mapped to lower case. */
225   int c;
226 
227   c = map_colour(*s++);
228   redfrontcolor = (c<0) ? DEFAULT_REDFRONTCOLOR : c;
229   if (*s == 0) return 0;
230 
231   s++;
232   if (*s == 0) return 0;
233 
234   c = map_colour(*s++);
235   normalcolor = (c<0) ? DEFAULT_NORMALCOLOR : c;
236   if (*s == 0) return 0;
237 
238   s++;
239   if (*s == 0) return 0;
240 
241   c = map_colour(*s++);
242   promptcolor = (c<0) ? DEFAULT_PROMPTCOLOR : c;
243   if (*s == 0) return 0;
244 
245   s++;
246   if (*s == 0) return 0;
247 
248   c = map_colour(*s++);
249   inputcolor = (c<0) ? DEFAULT_INPUTCOLOR : c;
250   if (*s == 0) return 0;
251 
252   s++;
253   if (*s == 0) return 0;
254 
255   c = map_colour(*s++);
256   outputcolor = (c<0) ? DEFAULT_OUTPUTCOLOR : c;
257   if (*s == 0) return 0;
258 
259   s++;
260   if (*s == 0) return 0;
261 
262   c = map_colour(*s++);
263   debugcolor = (c<0) ? DEFAULT_DEBUGCOLOR : c;
264   if (*s == 0) return 0;
265 
266   s++;
267   if (*s == 0) return 0;
268 
269   return 1;
270 }
271 
map_colour(int ch)272 int map_colour(int ch) {
273   switch (ch) {
274   case 'a': case 'A': return BLACK;
275   case 'b': case 'B': return RED;
276   case 'c': case 'C': return GREEN;
277   case 'd': case 'D': return YELLOW;
278   case 'e': case 'E': return BLUE;
279   case 'f': case 'F': return MAGENTA;
280   case 'g': case 'G': return CYAN;
281   case 'h': case 'H': return WHITE;
282   case 'x':           return USER;
283   default:            return -1;
284   }
285 }
286 
parse_memarg(char * argstr,char * name)287 char *parse_memarg(char *argstr,char *name) {
288   /* Only used for PSL */
289   char *nargv2;
290   char lchar;
291   int i;
292 
293   i = strlen(argstr) - 1;
294   lchar = tolower(argstr[i]);
295   if (!isdigit(lchar) && lchar != 'm' && lchar != 'k') {
296     print_usage(name);
297     rf_exit(1);
298   }
299   i--;
300 
301   for (; i >= 0; i--)
302     if (!isdigit(argstr[i])) {
303       print_usage(name);
304       rf_exit(1);
305     }
306 
307   if (lchar == 'm' ) {
308     nargv2 = (char *)malloc(strlen(argstr)-1+6+1);
309     strncpy(nargv2,argstr,strlen(argstr)-1);
310     nargv2[strlen(argstr)-1] = '\0';
311     sprintf(nargv2,"%s000000",nargv2);
312     return nargv2;
313   }
314 
315   if (lchar == 'k' ) {
316     nargv2 = (char *)malloc(strlen(argstr)-1+3+1);
317     strncpy(nargv2,argstr,strlen(argstr)-1);
318     nargv2[strlen(argstr)-1] = '\0';
319     sprintf(nargv2,"%s000",nargv2);
320     return nargv2;
321   }
322 
323   return argstr;
324 }
325 
print_usage(char name[])326 void print_usage(char name[]) {
327   if (dist == PSL)
328     fprintf(stderr,
329 	    "usage: %s [-bhuvV] [-c COLORSPEC] [[-m] NUMBER[kKmM]]\n",name);
330   else
331     fprintf(stderr,"usage: %s [-bhuvV] [-c COLORSPEC]\n",name);
332 }
333 
print_help(char name[])334 void print_help(char name[]) {
335   int w=color;
336 
337   color = 0;
338   print_banner(1);
339   color=w;
340 
341   fprintf(stderr,"A REDUCE frontend\n\n");
342 
343   print_usage(name);
344 
345   fprintf(stderr,"       -b\t\t\
346 black and white mode, i.e. do not use ANSI colors\n");
347   fprintf(stderr,"       -c COLORSPEC\t\
348 specify colors for redfront output, normal output,\n");
349   fprintf(stderr,"         \t\t\
350 prompt, input, math output, debug output. The default\n");
351   fprintf(stderr,"         \t\t\
352 is fxxxxxbxexgx - see LSCOLORS in the ls manpage for\n");
353   fprintf(stderr,"         \t\tdetails\n");
354   fprintf(stderr,"       -h\t\tthis help message\n");
355   if (dist == PSL)
356     fprintf(stderr,"       -m NUMBER [kKmM]\t\
357 memory allocation in Bytes [KB|MB]\n");
358   fprintf(stderr,"       -u\t\tuse unicode characters\n");
359   fprintf(stderr,"       -v, -V\t\tverbose\n\n");
360 
361   fprintf(stderr,"Examples: %s -uv\n",name);
362   if (dist == PSL)
363     fprintf(stderr,"          %s -c xxxxxxbxexgx -m 96m.\n\n",name);
364   else
365     fprintf(stderr,"          %s -c xxxxxxbxexgx -v\n\n",name);
366   fprintf(stderr,"Use TAB for completion of filenames and Reduce switches.\n");
367   fprintf(stderr,"There is a manpage available.\n");
368 }
369 
print_banner(int vb)370 void print_banner(int vb) {
371   textcolor(redfrontcolor);
372 
373   if (vb) {
374     int ur=0;
375 #ifdef USE_READLINE
376     ur=1;
377 #endif
378     printf("%s %s/%d, built %s ...\n",
379 	   PACKAGE_NAME,
380 	   PACKAGE_VERSION,
381 	   4*ur + 2*USE_PIPES + STATIC,
382 	   BUILDTIME);
383     //    if (unicode) printf("%c%c",0xC2,0xA9); else printf("(C)");
384     printf("(C)");
385     printf(" 1999-2008 A. Dolzmann, 1999-2014 T. Sturm\n");
386     printf("Based on earlier projects by C. Cannam and W. Neun\n");
387     printf("Reports bugs to <%s>\n\n",PACKAGE_BUGREPORT);
388   } else {
389     printf("%s %s, built %s ...\n",PACKAGE_NAME,PACKAGE_VERSION,BUILDTIME);
390   }
391   textcolor(normalcolor);
392 }
393 
init_channels(void)394 void init_channels(void) {
395   if (USE_PIPES) {
396     if (pipe(MeToReduce) < 0) {
397       perror("failed to create pipe MeToReduce\n");
398       sig_killChild();
399       rf_exit(-1);
400     }
401     if (pipe(ReduceToMe) < 0) {
402       perror("failed to create pipe ReduceToMe\n");
403       sig_killChild();
404       rf_exit(-1);
405     }
406   } else {
407     if (socketpair(AF_UNIX, SOCK_STREAM, 0, MeToReduce) < 0) {
408       perror("cannot open socket MeToReduce");
409       sig_killChild();
410       rf_exit(-1);
411     }
412     if (socketpair(AF_UNIX, SOCK_STREAM, 0, ReduceToMe) < 0) {
413       perror("cannot open socket ReduceToMe");
414       sig_killChild();
415       rf_exit(-1);
416     }
417   }
418 }
419 
textcolor(int fg)420 int textcolor(int fg) {
421   static int currentcolor=DEFAULT_REDFRONTCOLOR;
422   int oldcolor;
423 
424   oldcolor = currentcolor;
425   currentcolor = fg;
426   if (fg == 9)
427     resetcolor();
428   else
429     textcolor1(0,fg,9);
430   return oldcolor;
431 }
432 
textcolor1(int attr,int fg,int bg)433 void textcolor1(int attr, int fg, int bg) {
434   if (color && HAVE_COLOR) {
435     char command[13];
436 
437     stextcolor1(command,attr,fg,bg);
438     printf("%s", command);
439     fflush(stdout);
440   }
441 }
442 
stextcolor1(char command[],int attr,int fg,int bg)443 void stextcolor1(char command[],int attr,int fg,int bg) {
444   sprintf(command,"%c[%d;%d;%dm", 0x1B, attr, fg + 30, bg + 40);
445 }
446 
resetcolor(void)447 void resetcolor(void) {
448   if (color && HAVE_COLOR) {
449     printf("%c[0m",0x1B);
450     fflush(stdout);
451   }
452 }
453 
vbprintf(const char * msg,...)454 int vbprintf(const char *msg,...) {
455   int ecode=0;
456   int oldcolor;
457   va_list ap;
458 
459   if (!verbose)
460     return 0;
461 
462   va_start(ap,msg);
463   oldcolor = textcolor(redfrontcolor);
464   ecode = vprintf(msg,ap);
465   textcolor(oldcolor);
466   va_end(ap);
467 
468   return ecode;
469 }
470 
rf_exit(int ecode)471 void rf_exit(int ecode) {
472   deb_cleanup();
473   resetcolor();
474   exit(ecode);
475 }
476 
create_call(int argc,char * argv[])477 char **create_call(int argc,char *argv[]) {
478   char **nargv;
479   int tempfd;
480   int i,xa0;
481 
482   deb_fprintf(stderr,"entering create_call\n");
483 
484   nargv = (char **)malloc((argc - xargstart + 6)*sizeof(char *));
485 
486   if (dist == PSL) {
487     if ((tempfd = open(BPSL,O_RDONLY)) == -1) {  /* Does not check x */
488       char errstr[1024];
489       sprintf(errstr,"cannot open %s",BPSL);
490       perror(errstr);
491       rf_exit(-1);
492     } else
493       close(tempfd);
494 
495     if ((tempfd = open(REDIMG,O_RDONLY)) == -1) {
496       char errstr[1024];
497       sprintf(errstr,"cannot open %s",REDIMG);
498       perror(errstr);
499       rf_exit(-1);
500     } else
501       close(tempfd);
502 
503     if (strcmp(memory,"0") == 0) {
504       char *sixtyfour;
505       int i;
506       /* malloc one more in case the name of bpsl is only 1 char: */
507       sixtyfour = (char *)malloc((strlen(BPSL)+1+1)*sizeof(char));
508       strcpy(sixtyfour,BPSL);
509       i = strlen(BPSL);
510       while (sixtyfour[i-1] != '/')
511 	i--;
512       sixtyfour[i++] = '6';
513       sixtyfour[i++] = '4';
514       sixtyfour[i] = (char)0;
515       deb_fprintf(stderr,"checking for %s ... ",sixtyfour);
516       if ((tempfd = open(sixtyfour,O_RDONLY)) != -1) {
517 	close(tempfd);
518 	deb_fprintf(stderr,"positive\n");
519 	memory = "2000";
520       } else {
521 	deb_fprintf(stderr,"negative\n");
522 	memory = "16000000";
523       }
524     }
525 
526     nargv[0] = BPSL;
527     nargv[1] = "-td";
528     nargv[2] = memory;
529     nargv[3] = "-f";
530     nargv[4] = REDIMG;
531     for (i = xargstart; i < argc; i++)
532       nargv[i - xargstart + 5] = argv[i];
533     nargv[argc - xargstart + 5] = (char *)0;
534   } else {  // dist == CSL || dist == CSLB
535     nargv[0] = dist == CSLB ? BOOTSTRAPREDUCE : REDUCE;
536 
537     if ((tempfd = open(nargv[0], O_RDONLY)) == -1) {  /* Does not check x */
538       char errstr[1024];
539       sprintf(errstr, "cannot open %s", nargv[0]);
540       perror(errstr);
541       rf_exit(-1);
542     } else
543       close(tempfd);
544 
545     nargv[1] = "-w";
546     nargv[2] = "-b";
547     if (verbose) {
548       nargv[3] = "-V";
549       xa0 = 4;
550     } else
551       xa0 = 3;
552     for (i = xargstart; i < argc; i++)
553       nargv[i - xargstart + xa0] = argv[i];
554     for (i = xa0; i <= 5; i++)
555       nargv[argc - xargstart + i] = (char *)0;
556   }
557 
558   for (i = 0; i <= argc - xargstart + 5; i++)
559     deb_fprintf(stderr,"argv[%d]=%s\n",i,nargv[i]);
560 
561   deb_fprintf(stderr,"leaving create_call\n");
562 
563   return nargv;
564 }
565