Annotation of OpenXM/src/kan96xx/Kan/shell.c, Revision 1.3
1.3 ! takayama 1: /* $OpenXM: OpenXM/src/kan96xx/Kan/shell.c,v 1.2 2003/12/03 01:21:43 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;
! 355:
! 356: /* bug: win variable must be properly set on windows native. */
! 357:
! 358: if (ob.tag != Sarray) errorKan1("%s\n","oxsBuildArgv() requires an array as an argument.");
! 359: n = getoaSize(ob);
! 360: for (i=0; i<n; i++) {
! 361: if (getoa(ob,i).tag != Sdollar) errorKan1("%s\n","oxsBuildArgv() requires an array of string as an argument.");
! 362: }
! 363:
! 364: argv = (char **) mymalloc(sizeof(char *)*(n+2));
! 365: argv[0] = (char *)NULL;
! 366: if (n == 0) return(argv);
! 367:
! 368: s = KopString(getoa(ob,0));
! 369: s = oxEvalEnvVar(s);
! 370: argv[0] = oxWhich(s,(char *)getenv("PATH"));
! 371: argv[1] = (char *)NULL;
! 372: if (argv[0] == NULL) {
! 373: fprintf(stderr,"cmdname=%s\n",s);
! 374: errorKan1("%s\n","oxsBuildArgv() Command is not found.\n");
! 375: }
! 376: for (i=1; i<n; i++) {
! 377: argv[i] = argv[i+1] = NULL;
! 378: s = KopString(getoa(ob,i));
! 379: s = oxEvalEnvVar(s);
! 380: type = oxsIsURI(s);
! 381: if (type == NULL) {
! 382: argv[i] = s;
! 383: }else{
! 384: /* Case when argv[i] is like "stringInOut:abc.poly" */
! 385: v = oxsURIgetVarName(s);
! 386: ext = oxsURIgetExtension(s);
! 387: if (strcmp(type,"stringIn") == 0) {
! 388: argv[i] = oxsVarToFile(v,ext,argv[0],usetmp);
! 389: AfterDeleteFile[AfterD++] = argv[i];
! 390: }else if (strcmp(type,"stringInOut") == 0) {
! 391: argv[i] = oxsVarToFile(v,ext,argv[0],usetmp);
! 392: AfterDeleteFile[AfterD++] = argv[i];
! 393: AfterReadFile[AfterPt] = argv[i];
! 394: AfterSetVar[AfterPt] = v;
! 395: AfterPt++;
! 396: if (AfterPt >= MAXFILES) {
! 397: AfterPt=0;
! 398: errorKan1("%s\n","oxsBuildArgv(), Too may files to open.");
! 399: }
! 400: }else if (strcmp(type,"stringOut") == 0) {
! 401: argv[i] = generateTMPfileName2(v,ext,usetmp,win);
! 402: AfterDeleteFile[AfterD++] = argv[i];
! 403: AfterReadFile[AfterPt] = argv[i];
! 404: AfterSetVar[AfterPt] = v;
! 405: AfterPt++;
! 406: if (AfterPt >= MAXFILES) {
! 407: AfterPt=0;
! 408: errorKan1("%s\n","oxsBuildArgv(), Too may files to open.");
! 409: }
! 410: }else {
! 411: errorKan1("%s\n","This URI type has not yet been implemented.");
! 412: }
! 413: if (AfterD >= MAXFILES) {
! 414: AfterD=0;
! 415: errorKan1("%s\n","oxsBuildArgv(), Too may files to open.");
! 416: }
! 417: }
! 418: }
! 419: return(argv);
! 420: }
! 421:
! 422:
! 423: static struct object oxsExecuteBlocked(struct object ob)
! 424: {
! 425: int r,i,n;
! 426: char **argv;
! 427:
! 428: /* bug: Set stdout, stderr to result variables. */
! 429: argv = oxsBuildArgv(ob);
! 430: r=oxForkExecBlocked(argv); /* bug: what happen when NoX? */
! 431: /*
! 432: if (1) {
! 433: for (i=0; argv[i] != NULL; i++) {
! 434: fprintf(stderr,"argv[%d]=%s\n",i,argv[i]);
! 435: }
! 436: errorKan1("%s\n","ForkExecBlocked failed.");
! 437: }
! 438: */
! 439: if (AfterPt > 0) {
! 440: for (i=0; i< AfterPt; i++) {
! 441: oxsFileToVar(AfterSetVar[i],AfterReadFile[i]);
! 442: }
! 443: }
! 444: AfterPt = 0;
! 445:
! 446: if (AfterD > 0) {
! 447: for (i=0; i< AfterD; i++) {
! 448: /* oxDeleteFile(AfterDeleteFile[i]); not implemented. */
! 449: }
! 450: }
! 451: AfterD = 0;
! 452:
! 453: return(KpoInteger(r));
! 454: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>