Annotation of OpenXM/src/kan96xx/Kan/shell.c, Revision 1.5
1.5 ! takayama 1: /* $OpenXM: OpenXM/src/kan96xx/Kan/shell.c,v 1.4 2003/12/03 23:26:39 takayama Exp $ */
1.1 takayama 2: #include <stdio.h>
3: #include <sys/types.h>
4: #include <sys/stat.h>
5: #include <fcntl.h>
6: #include <stdlib.h>
7: #include <unistd.h>
8: #include <sys/wait.h>
9: #include "datatype.h"
10: #include "stackm.h"
11: #include "extern.h"
12: #include "extern2.h"
13: #include <signal.h>
14: #include "plugin.h"
15: #include "kclass.h"
16: #include <ctype.h>
17: #include "ox_pathfinder.h"
18:
1.2 takayama 19: static struct object KoxShell_test1(struct object ob);
1.3 takayama 20: static struct object oxsExecuteBlocked(struct object ob);
21: static struct object oxsSetenv(struct object ob);
22: static char *oxsIsURI(char *s);
23: static char *oxsURIgetVarName(char *s);
24: static char *oxsURIgetExtension(char *s);
1.5 ! takayama 25: static char *oxsURIgetFileName(char *s);
! 26: static char *oxsRemoveOpt(char *s);
! 27: static char *oxsGetOpt(char *s);
1.3 takayama 28: static char *oxsVarToFile(char *v,char *extension,char *comamnd,int tmp);
29: static int oxsFileToVar(char *v,char *fname);
30: static char **oxsBuildArgv(struct object ob);
1.5 ! takayama 31: static char **oxsBuildArgvRedirect(char **argv);
1.3 takayama 32: static struct object testmain(struct object ob);
33:
34: #define mymalloc(n) sGC_malloc(n)
35: #define nomemory(n) errorKan1("%s\n","No more memory in shell.c");
36:
37: #define MAXFILES 256
38: static char *AfterReadFile[MAXFILES];
39: static char *AfterSetVar[MAXFILES];
40: static int AfterPt=0;
41: static char *AfterDeleteFile[MAXFILES];
42: static int AfterD=0;
1.2 takayama 43:
1.5 ! takayama 44: static int KeepTmpFiles = 1;
! 45:
! 46: extern int OX_P_stdin;
! 47: extern int OX_P_stdout;
! 48: extern int OX_P_stderr;
! 49:
1.2 takayama 50: struct object KoxShell(struct object ob) {
51: return KoxShell_test1(ob);
52: }
53:
1.3 takayama 54: /* A temporary help system */
55: void KoxShellHelp(char *key,FILE *fp) {
1.5 ! takayama 56: char *keys[]={"command","export","which","redirect","@@@@gatekeeper"};
1.3 takayama 57: int i;
58: #define HSIZE 20
59: char *s[HSIZE];
60: if (key == NULL) {
1.5 ! takayama 61: fprintf(fp,"\n");
1.3 takayama 62: for (i=0; strcmp(keys[i],"@@@@gatekeeper") != 0; i++) {
63: fprintf(fp,"%s\n",keys[i]);
64: KoxShellHelp(keys[i],fp);
65: fprintf(fp,"\n",keys[i]);
66: }
67: return;
68: }
69: for (i=0; i<HSIZE; i++) s[i] = NULL;
70: if (strcmp(key,"export")==0) {
71: s[0] = "export env_name = value";
72: s[1] = "export env_name = ";
73: s[2] = "Example: [(export) (PATH) (=) (/usr/new/bin:${PATH})] oxshell";
74: s[3] = NULL;
75: }else if (strcmp(key,"which")==0) {
76: s[0] = "which cmd_name";
77: s[1] = "which cmd_name path";
78: s[2] = "Example: [(which) (ls)] oxshell";
79: s[3] = NULL;
80: }else if (strcmp(key,"command")==0) {
81: s[0] = "Executing a command";
82: s[1] = "cmdname arg1 arg2 ... ";
83: s[2] = "Example 1: /afo (Hello! ) def [(cat) (stringIn://afo)] oxshell";
84: s[3] = "Example 2: [(polymake) (stringInOut://afo.poly) (FACETS)] oxshell";
85: s[4] = NULL;
1.5 ! takayama 86: }else if (strcmp(key,"redirect")==0) {
! 87: s[0] = "The following redirect operators are implemented.";
! 88: s[1] = "< > 2>";
! 89: s[2] = "Example 1: [(ls) (hoge) (2>) (stringOut://afo)] oxshell\n afo ::";
! 90: s[3] = "Example 2: [(cp) ] addStdoutStderr oxshell\n [@@@stdout @@@stderr] ::";
! 91: s[4] = NULL;
1.3 takayama 92: }else{
93: }
94: i = 0;
95: while (s[i] != NULL) {
96: fprintf(fp,"%s\n",s[i++]);
97: }
98: }
99:
100:
1.2 takayama 101: static struct object KoxShell_test1(struct object ob) {
102: /* A simple shell. It does not implement a parser. */
103: struct object rob;
104: char *cmd;
105: char *arg1,*arg2;
106: int i,n;
107: rob = NullObject; cmd = NULL; arg1=NULL; arg2=NULL;
108: if (ob.tag != Sarray) errorKan1("%s\n","KoxShell requires an array as an argument.");
109: n = getoaSize(ob);
110: for (i=0; i<n; i++) {
111: if (getoa(ob,i).tag != Sdollar) errorKan1("%s\n","KoxShell requires an array of string as an argument.");
112: }
113:
114: if (n == 0) return(rob);
115: cmd = KopString(getoa(ob,0));
1.3 takayama 116: if (strcmp(cmd,"testmain")==0) {
117: rob = testmain(ob);
118: }else if (strcmp(cmd,"which")==0) {
1.2 takayama 119: if (n == 2) {
120: rob = KoxWhich(getoa(ob,1),KpoInteger(0));
121: }else if (n==3) {
122: rob = KoxWhich(getoa(ob,1),getoa(ob,2));
123: }else{
124: errorKan1("%s\n","shell: << which command-name >> or << which command-name path >>");
125: }
126: return(rob);
127: }else if (strcmp(cmd,"export")==0) {
1.3 takayama 128: rob=oxsSetenv(ob);
1.2 takayama 129: }else{
1.3 takayama 130: rob = oxsExecuteBlocked(ob);
1.2 takayama 131: }
132: return(rob);
133: }
1.1 takayama 134:
135: /* Functions for ox_shell */
136: struct object KoxWhich(struct object cmdo,struct object patho) {
137: struct object rob;
138: char *sss;
139: rob = NullObject;
140: if (cmdo.tag != Sdollar) errorKan1("%s\n","KoxWhich(str-obj,str-obj)");
141: if (patho.tag == Sdollar) {
142: sss=oxWhich(KopString(cmdo),KopString(patho));
143: if (sss != NULL) rob=KpoString(sss);
144: else{
145: sss=getCommandPath(KopString(cmdo));
146: if (sss != NULL) rob=KpoString(sss);
147: }
148: }else{
149: sss=getCommandPath(KopString(cmdo));
150: if (sss != NULL) rob=KpoString(sss);
151: }
152: return(rob);
153: }
154:
1.3 takayama 155: /* Example. [(export) (PATH) (=) (/usr/new/bin:$PATH)] */
156: static struct object oxsSetenv(struct object ob) {
157: struct object rob;
158: int i,n;
159: char *envp;
160: char *new;
161: int r;
162: rob = NullObject;
163: if (ob.tag != Sarray) errorKan1("%s\n","oxsSetenv requires an array of srings.");
164: n = getoaSize(ob);
165: if ((n != 4) && (n != 3)) errorKan1("%s\n","oxsSetenv requires an array of srings. Length must be 3 or 4.");
166: for (i=0; i<n; i++) {
167: if (getoa(ob,i).tag != Sdollar) errorKan1("%s\n","oxsSetenv requires an array of srings. Length must be 3 or 4.");
168: }
169:
170: if (strcmp(KopString(getoa(ob,2)),"=") != 0) {
171: errorKan1("%s\n","oxsSetenv, example [(export) (PATH) (=) (/usr/new/bin:$PATH)] oxshell");
172: }
173: envp = KopString(getoa(ob,1));
174: if (n == 4) {
175: new = KopString(getoa(ob,3));
176: /* printf("%s\n",new); */
177: new = oxEvalEnvVar(new);
178: /* printf("%s\n",new); */
179: r = setenv(envp,new,1);
180: }else{
181: unsetenv(envp); r = 0;
182: }
183: if (r != 0) errorKan1("%s\n","setenv failed.");
184: new = (char *) getenv(envp);
185: if (new != NULL) {
186: rob = KpoString((char *) getenv(envp));
187: }
188: return(rob);
189: }
190:
191: /* s="stringIn://abc.poly" ==> stringIn
192: s="stringInOut://abc.poly" ==> stringInOut
193: */
194: char *oxsIsURI(char *s) {
195: int n,i,j;
196: char *u;
197: if (s == NULL) return((char *)NULL);
1.5 ! takayama 198: s = oxsRemoveOpt(s);
1.3 takayama 199: n = strlen(s);
200: for (i=0; i<n-3;i++) {
201: if ((s[i] == ':') && (s[i+1] == '/') && (s[i+2] == '/')) {
202: u = (char *) mymalloc(i+1);
203: if (u == NULL) nomemory(1);
204: u[0]=0;
205: for (j=0; j<i; j++) {
206: u[j] = s[j]; u[j+1]=0;
207: }
208: return(u);
209: }
210: }
211: return(NULL);
212: }
1.1 takayama 213:
1.3 takayama 214: /* s="stringIn://abc.poly" ==> abc
215: s="stringInOut://abc.poly" ==> abc
216: s="stringInOut://abc" ==> abc
217: */
218: char *oxsURIgetVarName(char *s) {
219: int n,i,j;
220: char *u;
221: if (s == NULL) return((char *)NULL);
1.5 ! takayama 222: s = oxsRemoveOpt(s);
1.3 takayama 223: n = strlen(s);
224: for (i=0; i<n-3;i++) {
225: if ((s[i] == ':') && (s[i+1] == '/') && (s[i+2] == '/')) {
226: u = (char *) mymalloc(n-i+1);
227: if (u == NULL) nomemory(1);
228: u[0]=0;
229: for (j=i+3; j<n; j++) {
230: if (s[j] == '.') break;
231: u[j-i-3] = s[j]; u[j-i-3+1]=0;
232: }
233: return(u);
234: }
235: }
236: return(NULL);
237: }
238:
239: /* s="stringIn://abc.poly" ==> poly
240: s="stringInOut://abc.poly" ==> poly
241: s="stringInOut://abc" ==> NULL
242: */
243: char *oxsURIgetExtension(char *s) {
244: int n,i,j,k;
245: char *u;
246: if (s == NULL) return((char *)NULL);
1.5 ! takayama 247: s = oxsRemoveOpt(s);
1.3 takayama 248: n = strlen(s);
249: for (i=0; i<n-3;i++) {
250: if ((s[i] == ':') && (s[i+1] == '/') && (s[i+2] == '/')) {
251: for (j=i+3; j<n; j++) {
252: if (s[j] == '.') {
253: u = (char *) mymalloc(n-j+2);
254: if (u == NULL) nomemory(1);
255: u[0]=0;
256: for (k=j+1; k<n; k++) {
257: u[k-j-1] = s[k]; u[k-j] = 0;
258: }
259: return(u);
260: }
261: }
262: }
263: }
264: return(NULL);
265: }
266:
1.5 ! takayama 267: /* stringInOut://abc.poly=:file://pqr.txt */
! 268: static char *oxsRemoveOpt(char *s) {
! 269: int n,i,j;
! 270: char *u;
! 271: if (s == NULL) return((char *)NULL);
! 272: n = strlen(s);
! 273: for (i=0; i<n-1;i++) {
! 274: if ((s[i] == '=') && (s[i+1] == ':')) {
! 275: u = (char *) mymalloc(i+1);
! 276: if (u == NULL) nomemory(1);
! 277: u[0]=0;
! 278: for (j=0; j<i; j++) {
! 279: u[j] = s[j]; u[j+1]=0;
! 280: }
! 281: return(u);
! 282: }
! 283: }
! 284: return(s);
! 285: }
! 286:
! 287: /* stringInOut://abc.poly=:file://pqr.txt */
! 288: /* stringInOut://abc.poly */
! 289: char *oxsGetOpt(char *s) {
! 290: int n,i,j;
! 291: char *u;
! 292: if (s == NULL) return((char *)NULL);
! 293: n = strlen(s);
! 294: for (i=0; i<n-1;i++) {
! 295: if ((s[i] == '=') && (s[i+1] == ':')) {
! 296: u = (char *) mymalloc(n-i+1);
! 297: if (u == NULL) nomemory(1);
! 298: u[0]=0;
! 299: for (j=i+2; j<n; j++) {
! 300: u[j-i-2] = s[j]; u[j-i-2+1]=0;
! 301: }
! 302: return(u);
! 303: }
! 304: }
! 305: return(NULL);
! 306: }
! 307:
! 308: char *oxsURIgetFileName(char *s) {
! 309: int n,i,j;
! 310: char *u;
! 311: if (s == NULL) return((char *)NULL);
! 312: s = oxsRemoveOpt(s);
! 313: n = strlen(s);
! 314: for (i=0; i<n-3;i++) {
! 315: if ((s[i] == ':') && (s[i+1] == '/') && (s[i+2] == '/')) {
! 316: u = (char *) mymalloc(n-i+1);
! 317: if (u == NULL) nomemory(1);
! 318: u[0]=0;
! 319: for (j=i+3; j<n; j++) {
! 320: u[j-i-3] = s[j]; u[j-i-3+1]=0;
! 321: }
! 322: return(u);
! 323: }
! 324: }
! 325: return(NULL);
! 326: }
! 327:
! 328:
1.3 takayama 329: static struct object testmain(struct object ob) {
330: struct object rob;
331: char *s;
332: struct object ot;
333: char **av;
334: int i;
335: rob = NullObject;
336:
337: /* Try sm1 -s " /hoge (hogehoge) def [(testmain)] oxshell afo message " */
338:
339: ot = newObjectArray(3);
340: getoa(ot,0)=KpoString("cat");
341: getoa(ot,1)=KpoString("stringInOut://hoge.poly");
342: getoa(ot,2)=KpoString("${HOME}/t.t");
343: av=oxsBuildArgv(ot);
344: for (i=0; av[i] != NULL; i++) {
345: printf("%s\n",av[i]);
346: }
347: printf("------------------------------\n");
348:
349: s=oxsVarToFile("hoge","poly","polymake",0);
350: printf("%s\n",s);
351: oxsFileToVar("afo",s);
352: return(rob);
353: }
354:
355: char *oxsVarToFile(char *v,char *ext,char *command,int usetmp) {
356: char *fname;
357: int winname;
358: FILE *fp;
359: int n,i,prevc,c;
360: char *prog;
361: struct object vv;
362:
363: /*bug; winname must be automatically set by looking at command.
364: If command is win32-native-application, then winname=1; else winname=0.
365: For example, if command=="gnuplot32" then winmame=1; else winname=0;
366: */
367: winname = 0;
368:
369: fname = generateTMPfileName2(v,ext,usetmp,winname);
370: if (fname == NULL) errorKan1("%s\n","generateTMPfileName2() is failed.");
371: if (v == NULL) errorKan1("%s\n","oxsVarToFile(), v is NULL.");
372: vv = KfindUserDictionary(v);
373: if (vv.tag != Sdollar) errorKan1("%s\n","oxsVarToFile(), value is not a string object or the object is not found in the dictionary.");
374: prog = KopString(vv);
375:
376: fp = fopen(fname,"w");
377: if (fp == NULL) errorKan1("%s\n","oxsVarToFile(), fail to open a file.");
378: n = strlen(prog);
379: prevc = 0;
380: for (i=0; i<n ; i++) {
381: c = prog[i];
382: if (winname) {
383: if ((c == '\n') && (prevc != 0xd)) {
384: fputc(0xd,fp); fputc(c,fp);
385: }
386: }else{
387: fputc(c,fp);
388: }
389: prevc = c;
390: }
391: if (fclose(fp) != 0) errorKan1("%s\n","oxsVarToFile(), fail to close the file.");
392:
393: return(fname);
394: }
395:
396: int oxsFileToVar(char *v,char *fname) {
397: FILE *fp;
398: char *s, *sold;
399: int limit;
400: int c,i;
401:
402: if (v == NULL) errorKan1("%s\n","oxsFileToVar(), v is NULL.");
403: limit = 1024;
404: fp = fopen(fname,"r");
405: if (fp == NULL) {
406: fprintf(stderr,"Filename=%s\n",fname);
407: errorKan1("%s\n","oxsFileToVar(), the file cannot be opened.");
408: }
409: s = (char *)mymalloc(limit);
410: if (s == NULL) errorKan1("%s\n","No more memory in oxsFileToVar().");
411:
412: i = 0;
413: while ((c=fgetc(fp)) != EOF) {
414: s[i] = c; s[i+1] = 0;
415: if (i > limit - 10) {
416: sold = s; limit *= 2;
417: s = (char *)mymalloc(limit);
418: if (s == NULL) errorKan1("%s\n","No more memory in oxsFileToVar().");
419: strcpy(s,sold);
420: }
421: i++;
422: }
423: fclose(fp);
424:
425: KputUserDictionary(v,KpoString(s));
426: return(0);
427: }
428:
429: static char **oxsBuildArgv(struct object ob) {
430: int n,i;
431: char **argv;
432: char *s;
433: char *type;
434: char *ext, *v;
435: int usetmp=1;
436: int win=0;
1.4 takayama 437: struct object ocmd;
1.3 takayama 438:
439: /* bug: win variable must be properly set on windows native. */
440:
441: if (ob.tag != Sarray) errorKan1("%s\n","oxsBuildArgv() requires an array as an argument.");
442: n = getoaSize(ob);
443: for (i=0; i<n; i++) {
444: if (getoa(ob,i).tag != Sdollar) errorKan1("%s\n","oxsBuildArgv() requires an array of string as an argument.");
445: }
446:
447: argv = (char **) mymalloc(sizeof(char *)*(n+2));
448: argv[0] = (char *)NULL;
449: if (n == 0) return(argv);
450:
451: s = KopString(getoa(ob,0));
452: s = oxEvalEnvVar(s);
1.4 takayama 453: ocmd = KoxWhich(KpoString(s),KpoInteger(0));
454: if (ocmd.tag != Sdollar) {
455: argv[0] = NULL;
456: }else{
457: argv[0] = KopString(ocmd);
458: }
1.3 takayama 459: argv[1] = (char *)NULL;
460: if (argv[0] == NULL) {
461: fprintf(stderr,"cmdname=%s\n",s);
462: errorKan1("%s\n","oxsBuildArgv() Command is not found.\n");
463: }
464: for (i=1; i<n; i++) {
465: argv[i] = argv[i+1] = NULL;
466: s = KopString(getoa(ob,i));
467: s = oxEvalEnvVar(s);
468: type = oxsIsURI(s);
469: if (type == NULL) {
470: argv[i] = s;
471: }else{
472: /* Case when argv[i] is like "stringInOut:abc.poly" */
473: v = oxsURIgetVarName(s);
474: ext = oxsURIgetExtension(s);
475: if (strcmp(type,"stringIn") == 0) {
476: argv[i] = oxsVarToFile(v,ext,argv[0],usetmp);
477: AfterDeleteFile[AfterD++] = argv[i];
478: }else if (strcmp(type,"stringInOut") == 0) {
479: argv[i] = oxsVarToFile(v,ext,argv[0],usetmp);
480: AfterDeleteFile[AfterD++] = argv[i];
481: AfterReadFile[AfterPt] = argv[i];
482: AfterSetVar[AfterPt] = v;
483: AfterPt++;
484: if (AfterPt >= MAXFILES) {
485: AfterPt=0;
486: errorKan1("%s\n","oxsBuildArgv(), Too may files to open.");
487: }
488: }else if (strcmp(type,"stringOut") == 0) {
489: argv[i] = generateTMPfileName2(v,ext,usetmp,win);
490: AfterDeleteFile[AfterD++] = argv[i];
491: AfterReadFile[AfterPt] = argv[i];
492: AfterSetVar[AfterPt] = v;
493: AfterPt++;
494: if (AfterPt >= MAXFILES) {
495: AfterPt=0;
496: errorKan1("%s\n","oxsBuildArgv(), Too may files to open.");
497: }
498: }else {
499: errorKan1("%s\n","This URI type has not yet been implemented.");
500: }
501: if (AfterD >= MAXFILES) {
502: AfterD=0;
503: errorKan1("%s\n","oxsBuildArgv(), Too may files to open.");
504: }
505: }
506: }
507: return(argv);
508: }
509:
510:
511: static struct object oxsExecuteBlocked(struct object ob)
512: {
513: int r,i,n;
514: char **argv;
515:
516: argv = oxsBuildArgv(ob);
1.5 ! takayama 517: argv = oxsBuildArgvRedirect(argv);
1.3 takayama 518: r=oxForkExecBlocked(argv); /* bug: what happen when NoX? */
519: /*
520: if (1) {
521: for (i=0; argv[i] != NULL; i++) {
522: fprintf(stderr,"argv[%d]=%s\n",i,argv[i]);
523: }
524: errorKan1("%s\n","ForkExecBlocked failed.");
525: }
526: */
527: if (AfterPt > 0) {
528: for (i=0; i< AfterPt; i++) {
529: oxsFileToVar(AfterSetVar[i],AfterReadFile[i]);
530: }
531: }
532: AfterPt = 0;
533:
534: if (AfterD > 0) {
535: for (i=0; i< AfterD; i++) {
1.5 ! takayama 536: if (!KeepTmpFiles) {
! 537: oxDeleteFile(AfterDeleteFile[i]);
! 538: }
1.3 takayama 539: }
540: }
541: AfterD = 0;
542:
543: return(KpoInteger(r));
1.5 ! takayama 544: }
! 545:
! 546: static char **oxsBuildArgvRedirect(char **argv) {
! 547: char **newargv;
! 548: int n,i,j;
! 549: FILE *fp;
! 550: char *fname;
! 551:
! 552: n = 0; while (argv[n] != NULL) n++;
! 553: newargv = (char **) mymalloc(sizeof(char *)*(n+1));
! 554: for (i=0; i<=n; i++) newargv[i]=(char *)NULL;
! 555: j=0;
! 556: /* bug: Critical area, do not make an interruption. */
! 557: for (i=0; i<n; i++) {
! 558: if (strcmp(argv[i],"<")==0) {
! 559: fname=argv[i+1];
! 560: OX_P_stdin = open(fname,O_RDONLY);
! 561: if (OX_P_stdin < 0) {
! 562: OX_P_stdin = -1;
! 563: oxResetRedirect();
! 564: errorKan1("%s\n","oxsBuildArgvRedirect fails to open the input file.");
! 565: }
! 566: i++;
! 567: }else if (strcmp(argv[i],">")==0) {
! 568: fname = argv[i+1];
! 569: fp == NULL;
! 570: if (fname != NULL) {
! 571: fp = fopen(fname,"w");
! 572: }
! 573: if (fp == NULL) {
! 574: oxResetRedirect();
! 575: errorKan1("%s\n","oxsBuildArgvRedirect, cannot open the output file.\n");
! 576: }
! 577: fclose(fp); /* touch */
! 578: OX_P_stdout = open(fname,O_WRONLY);
! 579: i++;
! 580: }else if (strcmp(argv[i],"2>") == 0) {
! 581: fname = argv[i+1];
! 582: fp == NULL;
! 583: if (fname != NULL) {
! 584: fp = fopen(fname,"w");
! 585: }
! 586: if (fp == NULL) {
! 587: oxResetRedirect();
! 588: errorKan1("%s\n","oxsBuildArgvRedirect, cannot open the output (stderr) file.\n");
! 589: }
! 590: fclose(fp); /* touch */
! 591: OX_P_stderr = open(fname,O_WRONLY);
! 592: i++;
! 593: }else{
! 594: newargv[j++] = argv[i];
! 595: }
! 596: }
! 597: return( newargv );
1.3 takayama 598: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>