version 1.1, 2003/11/24 12:38:17 |
version 1.5, 2003/12/04 05:27:19 |
|
|
/* $OpenXM$ */ |
/* $OpenXM: OpenXM/src/kan96xx/Kan/shell.c,v 1.4 2003/12/03 23:26:39 takayama Exp $ */ |
#include <stdio.h> |
#include <stdio.h> |
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <sys/stat.h> |
|
|
#include <ctype.h> |
#include <ctype.h> |
#include "ox_pathfinder.h" |
#include "ox_pathfinder.h" |
|
|
|
static struct object KoxShell_test1(struct object ob); |
|
static struct object oxsExecuteBlocked(struct object ob); |
|
static struct object oxsSetenv(struct object ob); |
|
static char *oxsIsURI(char *s); |
|
static char *oxsURIgetVarName(char *s); |
|
static char *oxsURIgetExtension(char *s); |
|
static char *oxsURIgetFileName(char *s); |
|
static char *oxsRemoveOpt(char *s); |
|
static char *oxsGetOpt(char *s); |
|
static char *oxsVarToFile(char *v,char *extension,char *comamnd,int tmp); |
|
static int oxsFileToVar(char *v,char *fname); |
|
static char **oxsBuildArgv(struct object ob); |
|
static char **oxsBuildArgvRedirect(char **argv); |
|
static struct object testmain(struct object ob); |
|
|
|
#define mymalloc(n) sGC_malloc(n) |
|
#define nomemory(n) errorKan1("%s\n","No more memory in shell.c"); |
|
|
|
#define MAXFILES 256 |
|
static char *AfterReadFile[MAXFILES]; |
|
static char *AfterSetVar[MAXFILES]; |
|
static int AfterPt=0; |
|
static char *AfterDeleteFile[MAXFILES]; |
|
static int AfterD=0; |
|
|
|
static int KeepTmpFiles = 1; |
|
|
|
extern int OX_P_stdin; |
|
extern int OX_P_stdout; |
|
extern int OX_P_stderr; |
|
|
|
struct object KoxShell(struct object ob) { |
|
return KoxShell_test1(ob); |
|
} |
|
|
|
/* A temporary help system */ |
|
void KoxShellHelp(char *key,FILE *fp) { |
|
char *keys[]={"command","export","which","redirect","@@@@gatekeeper"}; |
|
int i; |
|
#define HSIZE 20 |
|
char *s[HSIZE]; |
|
if (key == NULL) { |
|
fprintf(fp,"\n"); |
|
for (i=0; strcmp(keys[i],"@@@@gatekeeper") != 0; i++) { |
|
fprintf(fp,"%s\n",keys[i]); |
|
KoxShellHelp(keys[i],fp); |
|
fprintf(fp,"\n",keys[i]); |
|
} |
|
return; |
|
} |
|
for (i=0; i<HSIZE; i++) s[i] = NULL; |
|
if (strcmp(key,"export")==0) { |
|
s[0] = "export env_name = value"; |
|
s[1] = "export env_name = "; |
|
s[2] = "Example: [(export) (PATH) (=) (/usr/new/bin:${PATH})] oxshell"; |
|
s[3] = NULL; |
|
}else if (strcmp(key,"which")==0) { |
|
s[0] = "which cmd_name"; |
|
s[1] = "which cmd_name path"; |
|
s[2] = "Example: [(which) (ls)] oxshell"; |
|
s[3] = NULL; |
|
}else if (strcmp(key,"command")==0) { |
|
s[0] = "Executing a command"; |
|
s[1] = "cmdname arg1 arg2 ... "; |
|
s[2] = "Example 1: /afo (Hello! ) def [(cat) (stringIn://afo)] oxshell"; |
|
s[3] = "Example 2: [(polymake) (stringInOut://afo.poly) (FACETS)] oxshell"; |
|
s[4] = NULL; |
|
}else if (strcmp(key,"redirect")==0) { |
|
s[0] = "The following redirect operators are implemented."; |
|
s[1] = "< > 2>"; |
|
s[2] = "Example 1: [(ls) (hoge) (2>) (stringOut://afo)] oxshell\n afo ::"; |
|
s[3] = "Example 2: [(cp) ] addStdoutStderr oxshell\n [@@@stdout @@@stderr] ::"; |
|
s[4] = NULL; |
|
}else{ |
|
} |
|
i = 0; |
|
while (s[i] != NULL) { |
|
fprintf(fp,"%s\n",s[i++]); |
|
} |
|
} |
|
|
|
|
|
static struct object KoxShell_test1(struct object ob) { |
|
/* A simple shell. It does not implement a parser. */ |
|
struct object rob; |
|
char *cmd; |
|
char *arg1,*arg2; |
|
int i,n; |
|
rob = NullObject; cmd = NULL; arg1=NULL; arg2=NULL; |
|
if (ob.tag != Sarray) errorKan1("%s\n","KoxShell requires an array as an argument."); |
|
n = getoaSize(ob); |
|
for (i=0; i<n; i++) { |
|
if (getoa(ob,i).tag != Sdollar) errorKan1("%s\n","KoxShell requires an array of string as an argument."); |
|
} |
|
|
|
if (n == 0) return(rob); |
|
cmd = KopString(getoa(ob,0)); |
|
if (strcmp(cmd,"testmain")==0) { |
|
rob = testmain(ob); |
|
}else if (strcmp(cmd,"which")==0) { |
|
if (n == 2) { |
|
rob = KoxWhich(getoa(ob,1),KpoInteger(0)); |
|
}else if (n==3) { |
|
rob = KoxWhich(getoa(ob,1),getoa(ob,2)); |
|
}else{ |
|
errorKan1("%s\n","shell: << which command-name >> or << which command-name path >>"); |
|
} |
|
return(rob); |
|
}else if (strcmp(cmd,"export")==0) { |
|
rob=oxsSetenv(ob); |
|
}else{ |
|
rob = oxsExecuteBlocked(ob); |
|
} |
|
return(rob); |
|
} |
|
|
/* Functions for ox_shell */ |
/* Functions for ox_shell */ |
struct object KoxWhich(struct object cmdo,struct object patho) { |
struct object KoxWhich(struct object cmdo,struct object patho) { |
struct object rob; |
struct object rob; |
Line 37 struct object KoxWhich(struct object cmdo,struct objec |
|
Line 152 struct object KoxWhich(struct object cmdo,struct objec |
|
return(rob); |
return(rob); |
} |
} |
|
|
|
/* Example. [(export) (PATH) (=) (/usr/new/bin:$PATH)] */ |
|
static struct object oxsSetenv(struct object ob) { |
|
struct object rob; |
|
int i,n; |
|
char *envp; |
|
char *new; |
|
int r; |
|
rob = NullObject; |
|
if (ob.tag != Sarray) errorKan1("%s\n","oxsSetenv requires an array of srings."); |
|
n = getoaSize(ob); |
|
if ((n != 4) && (n != 3)) errorKan1("%s\n","oxsSetenv requires an array of srings. Length must be 3 or 4."); |
|
for (i=0; i<n; i++) { |
|
if (getoa(ob,i).tag != Sdollar) errorKan1("%s\n","oxsSetenv requires an array of srings. Length must be 3 or 4."); |
|
} |
|
|
|
if (strcmp(KopString(getoa(ob,2)),"=") != 0) { |
|
errorKan1("%s\n","oxsSetenv, example [(export) (PATH) (=) (/usr/new/bin:$PATH)] oxshell"); |
|
} |
|
envp = KopString(getoa(ob,1)); |
|
if (n == 4) { |
|
new = KopString(getoa(ob,3)); |
|
/* printf("%s\n",new); */ |
|
new = oxEvalEnvVar(new); |
|
/* printf("%s\n",new); */ |
|
r = setenv(envp,new,1); |
|
}else{ |
|
unsetenv(envp); r = 0; |
|
} |
|
if (r != 0) errorKan1("%s\n","setenv failed."); |
|
new = (char *) getenv(envp); |
|
if (new != NULL) { |
|
rob = KpoString((char *) getenv(envp)); |
|
} |
|
return(rob); |
|
} |
|
|
|
/* s="stringIn://abc.poly" ==> stringIn |
|
s="stringInOut://abc.poly" ==> stringInOut |
|
*/ |
|
char *oxsIsURI(char *s) { |
|
int n,i,j; |
|
char *u; |
|
if (s == NULL) return((char *)NULL); |
|
s = oxsRemoveOpt(s); |
|
n = strlen(s); |
|
for (i=0; i<n-3;i++) { |
|
if ((s[i] == ':') && (s[i+1] == '/') && (s[i+2] == '/')) { |
|
u = (char *) mymalloc(i+1); |
|
if (u == NULL) nomemory(1); |
|
u[0]=0; |
|
for (j=0; j<i; j++) { |
|
u[j] = s[j]; u[j+1]=0; |
|
} |
|
return(u); |
|
} |
|
} |
|
return(NULL); |
|
} |
|
|
|
/* s="stringIn://abc.poly" ==> abc |
|
s="stringInOut://abc.poly" ==> abc |
|
s="stringInOut://abc" ==> abc |
|
*/ |
|
char *oxsURIgetVarName(char *s) { |
|
int n,i,j; |
|
char *u; |
|
if (s == NULL) return((char *)NULL); |
|
s = oxsRemoveOpt(s); |
|
n = strlen(s); |
|
for (i=0; i<n-3;i++) { |
|
if ((s[i] == ':') && (s[i+1] == '/') && (s[i+2] == '/')) { |
|
u = (char *) mymalloc(n-i+1); |
|
if (u == NULL) nomemory(1); |
|
u[0]=0; |
|
for (j=i+3; j<n; j++) { |
|
if (s[j] == '.') break; |
|
u[j-i-3] = s[j]; u[j-i-3+1]=0; |
|
} |
|
return(u); |
|
} |
|
} |
|
return(NULL); |
|
} |
|
|
|
/* s="stringIn://abc.poly" ==> poly |
|
s="stringInOut://abc.poly" ==> poly |
|
s="stringInOut://abc" ==> NULL |
|
*/ |
|
char *oxsURIgetExtension(char *s) { |
|
int n,i,j,k; |
|
char *u; |
|
if (s == NULL) return((char *)NULL); |
|
s = oxsRemoveOpt(s); |
|
n = strlen(s); |
|
for (i=0; i<n-3;i++) { |
|
if ((s[i] == ':') && (s[i+1] == '/') && (s[i+2] == '/')) { |
|
for (j=i+3; j<n; j++) { |
|
if (s[j] == '.') { |
|
u = (char *) mymalloc(n-j+2); |
|
if (u == NULL) nomemory(1); |
|
u[0]=0; |
|
for (k=j+1; k<n; k++) { |
|
u[k-j-1] = s[k]; u[k-j] = 0; |
|
} |
|
return(u); |
|
} |
|
} |
|
} |
|
} |
|
return(NULL); |
|
} |
|
|
|
/* stringInOut://abc.poly=:file://pqr.txt */ |
|
static char *oxsRemoveOpt(char *s) { |
|
int n,i,j; |
|
char *u; |
|
if (s == NULL) return((char *)NULL); |
|
n = strlen(s); |
|
for (i=0; i<n-1;i++) { |
|
if ((s[i] == '=') && (s[i+1] == ':')) { |
|
u = (char *) mymalloc(i+1); |
|
if (u == NULL) nomemory(1); |
|
u[0]=0; |
|
for (j=0; j<i; j++) { |
|
u[j] = s[j]; u[j+1]=0; |
|
} |
|
return(u); |
|
} |
|
} |
|
return(s); |
|
} |
|
|
|
/* stringInOut://abc.poly=:file://pqr.txt */ |
|
/* stringInOut://abc.poly */ |
|
char *oxsGetOpt(char *s) { |
|
int n,i,j; |
|
char *u; |
|
if (s == NULL) return((char *)NULL); |
|
n = strlen(s); |
|
for (i=0; i<n-1;i++) { |
|
if ((s[i] == '=') && (s[i+1] == ':')) { |
|
u = (char *) mymalloc(n-i+1); |
|
if (u == NULL) nomemory(1); |
|
u[0]=0; |
|
for (j=i+2; j<n; j++) { |
|
u[j-i-2] = s[j]; u[j-i-2+1]=0; |
|
} |
|
return(u); |
|
} |
|
} |
|
return(NULL); |
|
} |
|
|
|
char *oxsURIgetFileName(char *s) { |
|
int n,i,j; |
|
char *u; |
|
if (s == NULL) return((char *)NULL); |
|
s = oxsRemoveOpt(s); |
|
n = strlen(s); |
|
for (i=0; i<n-3;i++) { |
|
if ((s[i] == ':') && (s[i+1] == '/') && (s[i+2] == '/')) { |
|
u = (char *) mymalloc(n-i+1); |
|
if (u == NULL) nomemory(1); |
|
u[0]=0; |
|
for (j=i+3; j<n; j++) { |
|
u[j-i-3] = s[j]; u[j-i-3+1]=0; |
|
} |
|
return(u); |
|
} |
|
} |
|
return(NULL); |
|
} |
|
|
|
|
|
static struct object testmain(struct object ob) { |
|
struct object rob; |
|
char *s; |
|
struct object ot; |
|
char **av; |
|
int i; |
|
rob = NullObject; |
|
|
|
/* Try sm1 -s " /hoge (hogehoge) def [(testmain)] oxshell afo message " */ |
|
|
|
ot = newObjectArray(3); |
|
getoa(ot,0)=KpoString("cat"); |
|
getoa(ot,1)=KpoString("stringInOut://hoge.poly"); |
|
getoa(ot,2)=KpoString("${HOME}/t.t"); |
|
av=oxsBuildArgv(ot); |
|
for (i=0; av[i] != NULL; i++) { |
|
printf("%s\n",av[i]); |
|
} |
|
printf("------------------------------\n"); |
|
|
|
s=oxsVarToFile("hoge","poly","polymake",0); |
|
printf("%s\n",s); |
|
oxsFileToVar("afo",s); |
|
return(rob); |
|
} |
|
|
|
char *oxsVarToFile(char *v,char *ext,char *command,int usetmp) { |
|
char *fname; |
|
int winname; |
|
FILE *fp; |
|
int n,i,prevc,c; |
|
char *prog; |
|
struct object vv; |
|
|
|
/*bug; winname must be automatically set by looking at command. |
|
If command is win32-native-application, then winname=1; else winname=0. |
|
For example, if command=="gnuplot32" then winmame=1; else winname=0; |
|
*/ |
|
winname = 0; |
|
|
|
fname = generateTMPfileName2(v,ext,usetmp,winname); |
|
if (fname == NULL) errorKan1("%s\n","generateTMPfileName2() is failed."); |
|
if (v == NULL) errorKan1("%s\n","oxsVarToFile(), v is NULL."); |
|
vv = KfindUserDictionary(v); |
|
if (vv.tag != Sdollar) errorKan1("%s\n","oxsVarToFile(), value is not a string object or the object is not found in the dictionary."); |
|
prog = KopString(vv); |
|
|
|
fp = fopen(fname,"w"); |
|
if (fp == NULL) errorKan1("%s\n","oxsVarToFile(), fail to open a file."); |
|
n = strlen(prog); |
|
prevc = 0; |
|
for (i=0; i<n ; i++) { |
|
c = prog[i]; |
|
if (winname) { |
|
if ((c == '\n') && (prevc != 0xd)) { |
|
fputc(0xd,fp); fputc(c,fp); |
|
} |
|
}else{ |
|
fputc(c,fp); |
|
} |
|
prevc = c; |
|
} |
|
if (fclose(fp) != 0) errorKan1("%s\n","oxsVarToFile(), fail to close the file."); |
|
|
|
return(fname); |
|
} |
|
|
|
int oxsFileToVar(char *v,char *fname) { |
|
FILE *fp; |
|
char *s, *sold; |
|
int limit; |
|
int c,i; |
|
|
|
if (v == NULL) errorKan1("%s\n","oxsFileToVar(), v is NULL."); |
|
limit = 1024; |
|
fp = fopen(fname,"r"); |
|
if (fp == NULL) { |
|
fprintf(stderr,"Filename=%s\n",fname); |
|
errorKan1("%s\n","oxsFileToVar(), the file cannot be opened."); |
|
} |
|
s = (char *)mymalloc(limit); |
|
if (s == NULL) errorKan1("%s\n","No more memory in oxsFileToVar()."); |
|
|
|
i = 0; |
|
while ((c=fgetc(fp)) != EOF) { |
|
s[i] = c; s[i+1] = 0; |
|
if (i > limit - 10) { |
|
sold = s; limit *= 2; |
|
s = (char *)mymalloc(limit); |
|
if (s == NULL) errorKan1("%s\n","No more memory in oxsFileToVar()."); |
|
strcpy(s,sold); |
|
} |
|
i++; |
|
} |
|
fclose(fp); |
|
|
|
KputUserDictionary(v,KpoString(s)); |
|
return(0); |
|
} |
|
|
|
static char **oxsBuildArgv(struct object ob) { |
|
int n,i; |
|
char **argv; |
|
char *s; |
|
char *type; |
|
char *ext, *v; |
|
int usetmp=1; |
|
int win=0; |
|
struct object ocmd; |
|
|
|
/* bug: win variable must be properly set on windows native. */ |
|
|
|
if (ob.tag != Sarray) errorKan1("%s\n","oxsBuildArgv() requires an array as an argument."); |
|
n = getoaSize(ob); |
|
for (i=0; i<n; i++) { |
|
if (getoa(ob,i).tag != Sdollar) errorKan1("%s\n","oxsBuildArgv() requires an array of string as an argument."); |
|
} |
|
|
|
argv = (char **) mymalloc(sizeof(char *)*(n+2)); |
|
argv[0] = (char *)NULL; |
|
if (n == 0) return(argv); |
|
|
|
s = KopString(getoa(ob,0)); |
|
s = oxEvalEnvVar(s); |
|
ocmd = KoxWhich(KpoString(s),KpoInteger(0)); |
|
if (ocmd.tag != Sdollar) { |
|
argv[0] = NULL; |
|
}else{ |
|
argv[0] = KopString(ocmd); |
|
} |
|
argv[1] = (char *)NULL; |
|
if (argv[0] == NULL) { |
|
fprintf(stderr,"cmdname=%s\n",s); |
|
errorKan1("%s\n","oxsBuildArgv() Command is not found.\n"); |
|
} |
|
for (i=1; i<n; i++) { |
|
argv[i] = argv[i+1] = NULL; |
|
s = KopString(getoa(ob,i)); |
|
s = oxEvalEnvVar(s); |
|
type = oxsIsURI(s); |
|
if (type == NULL) { |
|
argv[i] = s; |
|
}else{ |
|
/* Case when argv[i] is like "stringInOut:abc.poly" */ |
|
v = oxsURIgetVarName(s); |
|
ext = oxsURIgetExtension(s); |
|
if (strcmp(type,"stringIn") == 0) { |
|
argv[i] = oxsVarToFile(v,ext,argv[0],usetmp); |
|
AfterDeleteFile[AfterD++] = argv[i]; |
|
}else if (strcmp(type,"stringInOut") == 0) { |
|
argv[i] = oxsVarToFile(v,ext,argv[0],usetmp); |
|
AfterDeleteFile[AfterD++] = argv[i]; |
|
AfterReadFile[AfterPt] = argv[i]; |
|
AfterSetVar[AfterPt] = v; |
|
AfterPt++; |
|
if (AfterPt >= MAXFILES) { |
|
AfterPt=0; |
|
errorKan1("%s\n","oxsBuildArgv(), Too may files to open."); |
|
} |
|
}else if (strcmp(type,"stringOut") == 0) { |
|
argv[i] = generateTMPfileName2(v,ext,usetmp,win); |
|
AfterDeleteFile[AfterD++] = argv[i]; |
|
AfterReadFile[AfterPt] = argv[i]; |
|
AfterSetVar[AfterPt] = v; |
|
AfterPt++; |
|
if (AfterPt >= MAXFILES) { |
|
AfterPt=0; |
|
errorKan1("%s\n","oxsBuildArgv(), Too may files to open."); |
|
} |
|
}else { |
|
errorKan1("%s\n","This URI type has not yet been implemented."); |
|
} |
|
if (AfterD >= MAXFILES) { |
|
AfterD=0; |
|
errorKan1("%s\n","oxsBuildArgv(), Too may files to open."); |
|
} |
|
} |
|
} |
|
return(argv); |
|
} |
|
|
|
|
|
static struct object oxsExecuteBlocked(struct object ob) |
|
{ |
|
int r,i,n; |
|
char **argv; |
|
|
|
argv = oxsBuildArgv(ob); |
|
argv = oxsBuildArgvRedirect(argv); |
|
r=oxForkExecBlocked(argv); /* bug: what happen when NoX? */ |
|
/* |
|
if (1) { |
|
for (i=0; argv[i] != NULL; i++) { |
|
fprintf(stderr,"argv[%d]=%s\n",i,argv[i]); |
|
} |
|
errorKan1("%s\n","ForkExecBlocked failed."); |
|
} |
|
*/ |
|
if (AfterPt > 0) { |
|
for (i=0; i< AfterPt; i++) { |
|
oxsFileToVar(AfterSetVar[i],AfterReadFile[i]); |
|
} |
|
} |
|
AfterPt = 0; |
|
|
|
if (AfterD > 0) { |
|
for (i=0; i< AfterD; i++) { |
|
if (!KeepTmpFiles) { |
|
oxDeleteFile(AfterDeleteFile[i]); |
|
} |
|
} |
|
} |
|
AfterD = 0; |
|
|
|
return(KpoInteger(r)); |
|
} |
|
|
|
static char **oxsBuildArgvRedirect(char **argv) { |
|
char **newargv; |
|
int n,i,j; |
|
FILE *fp; |
|
char *fname; |
|
|
|
n = 0; while (argv[n] != NULL) n++; |
|
newargv = (char **) mymalloc(sizeof(char *)*(n+1)); |
|
for (i=0; i<=n; i++) newargv[i]=(char *)NULL; |
|
j=0; |
|
/* bug: Critical area, do not make an interruption. */ |
|
for (i=0; i<n; i++) { |
|
if (strcmp(argv[i],"<")==0) { |
|
fname=argv[i+1]; |
|
OX_P_stdin = open(fname,O_RDONLY); |
|
if (OX_P_stdin < 0) { |
|
OX_P_stdin = -1; |
|
oxResetRedirect(); |
|
errorKan1("%s\n","oxsBuildArgvRedirect fails to open the input file."); |
|
} |
|
i++; |
|
}else if (strcmp(argv[i],">")==0) { |
|
fname = argv[i+1]; |
|
fp == NULL; |
|
if (fname != NULL) { |
|
fp = fopen(fname,"w"); |
|
} |
|
if (fp == NULL) { |
|
oxResetRedirect(); |
|
errorKan1("%s\n","oxsBuildArgvRedirect, cannot open the output file.\n"); |
|
} |
|
fclose(fp); /* touch */ |
|
OX_P_stdout = open(fname,O_WRONLY); |
|
i++; |
|
}else if (strcmp(argv[i],"2>") == 0) { |
|
fname = argv[i+1]; |
|
fp == NULL; |
|
if (fname != NULL) { |
|
fp = fopen(fname,"w"); |
|
} |
|
if (fp == NULL) { |
|
oxResetRedirect(); |
|
errorKan1("%s\n","oxsBuildArgvRedirect, cannot open the output (stderr) file.\n"); |
|
} |
|
fclose(fp); /* touch */ |
|
OX_P_stderr = open(fname,O_WRONLY); |
|
i++; |
|
}else{ |
|
newargv[j++] = argv[i]; |
|
} |
|
} |
|
return( newargv ); |
|
} |