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