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