Annotation of OpenXM/src/kan96xx/Kan/shell.c, Revision 1.4
1.4 ! takayama 1: /* $OpenXM: OpenXM/src/kan96xx/Kan/shell.c,v 1.3 2003/12/03 09:00:46 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);
25: static char *oxsVarToFile(char *v,char *extension,char *comamnd,int tmp);
26: static int oxsFileToVar(char *v,char *fname);
27: static char **oxsBuildArgv(struct object ob);
28: static struct object testmain(struct object ob);
29:
30: #define mymalloc(n) sGC_malloc(n)
31: #define nomemory(n) errorKan1("%s\n","No more memory in shell.c");
32:
33: #define MAXFILES 256
34: static char *AfterReadFile[MAXFILES];
35: static char *AfterSetVar[MAXFILES];
36: static int AfterPt=0;
37: static char *AfterDeleteFile[MAXFILES];
38: static int AfterD=0;
1.2 takayama 39:
40: struct object KoxShell(struct object ob) {
41: return KoxShell_test1(ob);
42: }
43:
1.3 takayama 44: /* A temporary help system */
45: void KoxShellHelp(char *key,FILE *fp) {
46: char *keys[]={"command","export","which","@@@@gatekeeper"};
47: int i;
48: #define HSIZE 20
49: char *s[HSIZE];
50: if (key == NULL) {
51: for (i=0; strcmp(keys[i],"@@@@gatekeeper") != 0; i++) {
52: fprintf(fp,"%s\n",keys[i]);
53: KoxShellHelp(keys[i],fp);
54: fprintf(fp,"\n",keys[i]);
55: }
56: return;
57: }
58: for (i=0; i<HSIZE; i++) s[i] = NULL;
59: if (strcmp(key,"export")==0) {
60: s[0] = "export env_name = value";
61: s[1] = "export env_name = ";
62: s[2] = "Example: [(export) (PATH) (=) (/usr/new/bin:${PATH})] oxshell";
63: s[3] = NULL;
64: }else if (strcmp(key,"which")==0) {
65: s[0] = "which cmd_name";
66: s[1] = "which cmd_name path";
67: s[2] = "Example: [(which) (ls)] oxshell";
68: s[3] = NULL;
69: }else if (strcmp(key,"command")==0) {
70: s[0] = "Executing a command";
71: s[1] = "cmdname arg1 arg2 ... ";
72: s[2] = "Example 1: /afo (Hello! ) def [(cat) (stringIn://afo)] oxshell";
73: s[3] = "Example 2: [(polymake) (stringInOut://afo.poly) (FACETS)] oxshell";
74: s[4] = NULL;
75: }else{
76: }
77: i = 0;
78: while (s[i] != NULL) {
79: fprintf(fp,"%s\n",s[i++]);
80: }
81: }
82:
83:
1.2 takayama 84: static struct object KoxShell_test1(struct object ob) {
85: /* A simple shell. It does not implement a parser. */
86: struct object rob;
87: char *cmd;
88: char *arg1,*arg2;
89: int i,n;
90: rob = NullObject; cmd = NULL; arg1=NULL; arg2=NULL;
91: if (ob.tag != Sarray) errorKan1("%s\n","KoxShell requires an array as an argument.");
92: n = getoaSize(ob);
93: for (i=0; i<n; i++) {
94: if (getoa(ob,i).tag != Sdollar) errorKan1("%s\n","KoxShell requires an array of string as an argument.");
95: }
96:
97: if (n == 0) return(rob);
98: cmd = KopString(getoa(ob,0));
1.3 takayama 99: if (strcmp(cmd,"testmain")==0) {
100: rob = testmain(ob);
101: }else if (strcmp(cmd,"which")==0) {
1.2 takayama 102: if (n == 2) {
103: rob = KoxWhich(getoa(ob,1),KpoInteger(0));
104: }else if (n==3) {
105: rob = KoxWhich(getoa(ob,1),getoa(ob,2));
106: }else{
107: errorKan1("%s\n","shell: << which command-name >> or << which command-name path >>");
108: }
109: return(rob);
110: }else if (strcmp(cmd,"export")==0) {
1.3 takayama 111: rob=oxsSetenv(ob);
1.2 takayama 112: }else{
1.3 takayama 113: rob = oxsExecuteBlocked(ob);
1.2 takayama 114: }
115: return(rob);
116: }
1.1 takayama 117:
118: /* Functions for ox_shell */
119: struct object KoxWhich(struct object cmdo,struct object patho) {
120: struct object rob;
121: char *sss;
122: rob = NullObject;
123: if (cmdo.tag != Sdollar) errorKan1("%s\n","KoxWhich(str-obj,str-obj)");
124: if (patho.tag == Sdollar) {
125: sss=oxWhich(KopString(cmdo),KopString(patho));
126: if (sss != NULL) rob=KpoString(sss);
127: else{
128: sss=getCommandPath(KopString(cmdo));
129: if (sss != NULL) rob=KpoString(sss);
130: }
131: }else{
132: sss=getCommandPath(KopString(cmdo));
133: if (sss != NULL) rob=KpoString(sss);
134: }
135: return(rob);
136: }
137:
1.3 takayama 138: /* Example. [(export) (PATH) (=) (/usr/new/bin:$PATH)] */
139: static struct object oxsSetenv(struct object ob) {
140: struct object rob;
141: int i,n;
142: char *envp;
143: char *new;
144: int r;
145: rob = NullObject;
146: if (ob.tag != Sarray) errorKan1("%s\n","oxsSetenv requires an array of srings.");
147: n = getoaSize(ob);
148: if ((n != 4) && (n != 3)) errorKan1("%s\n","oxsSetenv requires an array of srings. Length must be 3 or 4.");
149: for (i=0; i<n; i++) {
150: if (getoa(ob,i).tag != Sdollar) errorKan1("%s\n","oxsSetenv requires an array of srings. Length must be 3 or 4.");
151: }
152:
153: if (strcmp(KopString(getoa(ob,2)),"=") != 0) {
154: errorKan1("%s\n","oxsSetenv, example [(export) (PATH) (=) (/usr/new/bin:$PATH)] oxshell");
155: }
156: envp = KopString(getoa(ob,1));
157: if (n == 4) {
158: new = KopString(getoa(ob,3));
159: /* printf("%s\n",new); */
160: new = oxEvalEnvVar(new);
161: /* printf("%s\n",new); */
162: r = setenv(envp,new,1);
163: }else{
164: unsetenv(envp); r = 0;
165: }
166: if (r != 0) errorKan1("%s\n","setenv failed.");
167: new = (char *) getenv(envp);
168: if (new != NULL) {
169: rob = KpoString((char *) getenv(envp));
170: }
171: return(rob);
172: }
173:
174: /* s="stringIn://abc.poly" ==> stringIn
175: s="stringInOut://abc.poly" ==> stringInOut
176: */
177: char *oxsIsURI(char *s) {
178: int n,i,j;
179: char *u;
180: if (s == NULL) return((char *)NULL);
181: n = strlen(s);
182: for (i=0; i<n-3;i++) {
183: if ((s[i] == ':') && (s[i+1] == '/') && (s[i+2] == '/')) {
184: u = (char *) mymalloc(i+1);
185: if (u == NULL) nomemory(1);
186: u[0]=0;
187: for (j=0; j<i; j++) {
188: u[j] = s[j]; u[j+1]=0;
189: }
190: return(u);
191: }
192: }
193: return(NULL);
194: }
1.1 takayama 195:
1.3 takayama 196: /* s="stringIn://abc.poly" ==> abc
197: s="stringInOut://abc.poly" ==> abc
198: s="stringInOut://abc" ==> abc
199: */
200: char *oxsURIgetVarName(char *s) {
201: int n,i,j;
202: char *u;
203: if (s == NULL) return((char *)NULL);
204: n = strlen(s);
205: for (i=0; i<n-3;i++) {
206: if ((s[i] == ':') && (s[i+1] == '/') && (s[i+2] == '/')) {
207: u = (char *) mymalloc(n-i+1);
208: if (u == NULL) nomemory(1);
209: u[0]=0;
210: for (j=i+3; j<n; j++) {
211: if (s[j] == '.') break;
212: u[j-i-3] = s[j]; u[j-i-3+1]=0;
213: }
214: return(u);
215: }
216: }
217: return(NULL);
218: }
219:
220: /* s="stringIn://abc.poly" ==> poly
221: s="stringInOut://abc.poly" ==> poly
222: s="stringInOut://abc" ==> NULL
223: */
224: char *oxsURIgetExtension(char *s) {
225: int n,i,j,k;
226: char *u;
227: if (s == NULL) return((char *)NULL);
228: n = strlen(s);
229: for (i=0; i<n-3;i++) {
230: if ((s[i] == ':') && (s[i+1] == '/') && (s[i+2] == '/')) {
231: for (j=i+3; j<n; j++) {
232: if (s[j] == '.') {
233: u = (char *) mymalloc(n-j+2);
234: if (u == NULL) nomemory(1);
235: u[0]=0;
236: for (k=j+1; k<n; k++) {
237: u[k-j-1] = s[k]; u[k-j] = 0;
238: }
239: return(u);
240: }
241: }
242: }
243: }
244: return(NULL);
245: }
246:
247: static struct object testmain(struct object ob) {
248: struct object rob;
249: char *s;
250: struct object ot;
251: char **av;
252: int i;
253: rob = NullObject;
254:
255: /* Try sm1 -s " /hoge (hogehoge) def [(testmain)] oxshell afo message " */
256:
257: ot = newObjectArray(3);
258: getoa(ot,0)=KpoString("cat");
259: getoa(ot,1)=KpoString("stringInOut://hoge.poly");
260: getoa(ot,2)=KpoString("${HOME}/t.t");
261: av=oxsBuildArgv(ot);
262: for (i=0; av[i] != NULL; i++) {
263: printf("%s\n",av[i]);
264: }
265: printf("------------------------------\n");
266:
267: s=oxsVarToFile("hoge","poly","polymake",0);
268: printf("%s\n",s);
269: oxsFileToVar("afo",s);
270: return(rob);
271: }
272:
273: char *oxsVarToFile(char *v,char *ext,char *command,int usetmp) {
274: char *fname;
275: int winname;
276: FILE *fp;
277: int n,i,prevc,c;
278: char *prog;
279: struct object vv;
280:
281: /*bug; winname must be automatically set by looking at command.
282: If command is win32-native-application, then winname=1; else winname=0.
283: For example, if command=="gnuplot32" then winmame=1; else winname=0;
284: */
285: winname = 0;
286:
287: fname = generateTMPfileName2(v,ext,usetmp,winname);
288: if (fname == NULL) errorKan1("%s\n","generateTMPfileName2() is failed.");
289: if (v == NULL) errorKan1("%s\n","oxsVarToFile(), v is NULL.");
290: vv = KfindUserDictionary(v);
291: if (vv.tag != Sdollar) errorKan1("%s\n","oxsVarToFile(), value is not a string object or the object is not found in the dictionary.");
292: prog = KopString(vv);
293:
294: fp = fopen(fname,"w");
295: if (fp == NULL) errorKan1("%s\n","oxsVarToFile(), fail to open a file.");
296: n = strlen(prog);
297: prevc = 0;
298: for (i=0; i<n ; i++) {
299: c = prog[i];
300: if (winname) {
301: if ((c == '\n') && (prevc != 0xd)) {
302: fputc(0xd,fp); fputc(c,fp);
303: }
304: }else{
305: fputc(c,fp);
306: }
307: prevc = c;
308: }
309: if (fclose(fp) != 0) errorKan1("%s\n","oxsVarToFile(), fail to close the file.");
310:
311: return(fname);
312: }
313:
314: int oxsFileToVar(char *v,char *fname) {
315: FILE *fp;
316: char *s, *sold;
317: int limit;
318: int c,i;
319:
320: if (v == NULL) errorKan1("%s\n","oxsFileToVar(), v is NULL.");
321: limit = 1024;
322: fp = fopen(fname,"r");
323: if (fp == NULL) {
324: fprintf(stderr,"Filename=%s\n",fname);
325: errorKan1("%s\n","oxsFileToVar(), the file cannot be opened.");
326: }
327: s = (char *)mymalloc(limit);
328: if (s == NULL) errorKan1("%s\n","No more memory in oxsFileToVar().");
329:
330: i = 0;
331: while ((c=fgetc(fp)) != EOF) {
332: s[i] = c; s[i+1] = 0;
333: if (i > limit - 10) {
334: sold = s; limit *= 2;
335: s = (char *)mymalloc(limit);
336: if (s == NULL) errorKan1("%s\n","No more memory in oxsFileToVar().");
337: strcpy(s,sold);
338: }
339: i++;
340: }
341: fclose(fp);
342:
343: KputUserDictionary(v,KpoString(s));
344: return(0);
345: }
346:
347: static char **oxsBuildArgv(struct object ob) {
348: int n,i;
349: char **argv;
350: char *s;
351: char *type;
352: char *ext, *v;
353: int usetmp=1;
354: int win=0;
1.4 ! takayama 355: struct object ocmd;
1.3 takayama 356:
357: /* bug: win variable must be properly set on windows native. */
358:
359: if (ob.tag != Sarray) errorKan1("%s\n","oxsBuildArgv() requires an array as an argument.");
360: n = getoaSize(ob);
361: for (i=0; i<n; i++) {
362: if (getoa(ob,i).tag != Sdollar) errorKan1("%s\n","oxsBuildArgv() requires an array of string as an argument.");
363: }
364:
365: argv = (char **) mymalloc(sizeof(char *)*(n+2));
366: argv[0] = (char *)NULL;
367: if (n == 0) return(argv);
368:
369: s = KopString(getoa(ob,0));
370: s = oxEvalEnvVar(s);
1.4 ! takayama 371: ocmd = KoxWhich(KpoString(s),KpoInteger(0));
! 372: if (ocmd.tag != Sdollar) {
! 373: argv[0] = NULL;
! 374: }else{
! 375: argv[0] = KopString(ocmd);
! 376: }
1.3 takayama 377: argv[1] = (char *)NULL;
378: if (argv[0] == NULL) {
379: fprintf(stderr,"cmdname=%s\n",s);
380: errorKan1("%s\n","oxsBuildArgv() Command is not found.\n");
381: }
382: for (i=1; i<n; i++) {
383: argv[i] = argv[i+1] = NULL;
384: s = KopString(getoa(ob,i));
385: s = oxEvalEnvVar(s);
386: type = oxsIsURI(s);
387: if (type == NULL) {
388: argv[i] = s;
389: }else{
390: /* Case when argv[i] is like "stringInOut:abc.poly" */
391: v = oxsURIgetVarName(s);
392: ext = oxsURIgetExtension(s);
393: if (strcmp(type,"stringIn") == 0) {
394: argv[i] = oxsVarToFile(v,ext,argv[0],usetmp);
395: AfterDeleteFile[AfterD++] = argv[i];
396: }else if (strcmp(type,"stringInOut") == 0) {
397: argv[i] = oxsVarToFile(v,ext,argv[0],usetmp);
398: AfterDeleteFile[AfterD++] = argv[i];
399: AfterReadFile[AfterPt] = argv[i];
400: AfterSetVar[AfterPt] = v;
401: AfterPt++;
402: if (AfterPt >= MAXFILES) {
403: AfterPt=0;
404: errorKan1("%s\n","oxsBuildArgv(), Too may files to open.");
405: }
406: }else if (strcmp(type,"stringOut") == 0) {
407: argv[i] = generateTMPfileName2(v,ext,usetmp,win);
408: AfterDeleteFile[AfterD++] = argv[i];
409: AfterReadFile[AfterPt] = argv[i];
410: AfterSetVar[AfterPt] = v;
411: AfterPt++;
412: if (AfterPt >= MAXFILES) {
413: AfterPt=0;
414: errorKan1("%s\n","oxsBuildArgv(), Too may files to open.");
415: }
416: }else {
417: errorKan1("%s\n","This URI type has not yet been implemented.");
418: }
419: if (AfterD >= MAXFILES) {
420: AfterD=0;
421: errorKan1("%s\n","oxsBuildArgv(), Too may files to open.");
422: }
423: }
424: }
425: return(argv);
426: }
427:
428:
429: static struct object oxsExecuteBlocked(struct object ob)
430: {
431: int r,i,n;
432: char **argv;
433:
434: /* bug: Set stdout, stderr to result variables. */
435: argv = oxsBuildArgv(ob);
436: r=oxForkExecBlocked(argv); /* bug: what happen when NoX? */
437: /*
438: if (1) {
439: for (i=0; argv[i] != NULL; i++) {
440: fprintf(stderr,"argv[%d]=%s\n",i,argv[i]);
441: }
442: errorKan1("%s\n","ForkExecBlocked failed.");
443: }
444: */
445: if (AfterPt > 0) {
446: for (i=0; i< AfterPt; i++) {
447: oxsFileToVar(AfterSetVar[i],AfterReadFile[i]);
448: }
449: }
450: AfterPt = 0;
451:
452: if (AfterD > 0) {
453: for (i=0; i< AfterD; i++) {
454: /* oxDeleteFile(AfterDeleteFile[i]); not implemented. */
455: }
456: }
457: AfterD = 0;
458:
459: return(KpoInteger(r));
460: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>