4
** Written by Kiem-Phong Vo.
11
#define EXIT_NOTFOUND 127
19
static char Meta[1<<CHAR_BIT], **Path;
21
/* execute command directly if possible; else use the shell */
23
static void execute(const char* argcmd)
25
static void execute(argcmd)
29
reg char *s, *cmd, **argv, **p, *interp;
32
/* define interpreter */
33
if(!(interp = getenv("SHELL")) || !interp[0])
36
if(strcmp(interp,"/bin/sh") != 0 && strcmp(interp,"/bin/ksh") != 0 )
37
{ if(access(interp,X_OK) == 0)
39
else interp = "/bin/sh";
42
/* if there is a meta character, let the shell do it */
43
for(s = (char*)argcmd; *s; ++s)
47
/* try to construct argv */
48
if(!(cmd = (char*)malloc(strlen(argcmd)+1)) )
51
if(!(argv = (char**)malloc(16*sizeof(char*))) )
53
for(n = 0, s = cmd;; )
54
{ while(isspace(s[0]))
61
if((n%16) == 0 && !(argv = (char**)realloc(argv,(n+16)*sizeof(char*))) )
64
/* make this into a C string */
65
while(s[0] && !isspace(s[0]))
74
/* get the command name */
76
for(s = cmd+strlen(cmd)-1; s >= cmd; --s)
81
/* Non-standard pathnames as in nDFS should be handled by the shell */
82
for(s = cmd+strlen(cmd)-1; s >= cmd+2; --s)
83
if(s[0] == '.' && s[-1] == '.' && s[-2] == '.')
87
(cmd[0] == '.' && cmd[1] == '/') ||
88
(cmd[0] == '.' && cmd[1] == '.' && cmd[2] == '/') )
89
{ if(access(cmd,X_OK) != 0)
94
{ for(p = Path; *p; ++p)
95
{ s = sfprints("%s/%s", *p, cmd);
96
if(access(s,X_OK) == 0)
101
/* if get here, let the interpreter do it */
103
for(s = interp+strlen(interp)-1; s >= interp; --s)
106
execl(interp, s+1, "-c", argcmd, NIL(char*));
107
_exit(EXIT_NOTFOUND);
110
#endif /*_PACKAGE_ast*/
113
Sfio_t* sfpopen(Sfio_t* f, const char* command, const char* mode)
115
Sfio_t* sfpopen(f,command,mode)
117
char* command; /* command to execute */
118
char* mode; /* mode of the stream */
128
if (!command || !command[0] || !(sflags = _sftype(mode, NiL, NiL)))
131
if(f == (Sfio_t*)(-1))
132
{ /* stdio compatibility mode */
139
if (sflags & SF_READ)
141
if (sflags & SF_WRITE)
145
av[2] = (char*)command;
147
if (!(proc = procopen(0, av, 0, 0, flags)))
149
if (!(f = sfnew(f, NIL(Void_t*), (size_t)SF_UNBOUND,
150
(sflags&SF_READ) ? proc->rfd : proc->wfd, sflags)) ||
152
_sfpopen(f, (sflags&SF_READ) ? proc->wfd : -1, proc->pid)) < 0)
161
reg int pid, fd, pkeep, ckeep, sflags;
162
int stdio, parent[2], child[2];
165
/* set shell meta characters */
169
for(s = "!@#$%&*(){}[]:;<>~`'|\"\\"; *s; ++s)
170
Meta[(uchar)s[0]] = 1;
173
Path = _sfgetpath("PATH");
176
if(!command || !command[0] || !(sflags = _sftype(mode,NIL(int*),NIL(int*))))
180
parent[0] = parent[1] = child[0] = child[1] = -1;
183
if((sflags&SF_RDWR) == SF_RDWR && pipe(child) < 0)
186
switch((pid = fork()) )
188
default : /* in parent process */
190
{ pkeep = READ; ckeep = WRITE; }
191
else { pkeep = WRITE; ckeep = READ; }
193
if(f == (Sfio_t*)(-1))
194
{ /* stdio compatibility mode */
200
/* make the streams */
201
if(!(f = sfnew(f,NIL(Void_t*),(size_t)SF_UNBOUND,parent[pkeep],sflags)))
203
CLOSE(parent[!pkeep]);
204
SETCLOEXEC(parent[pkeep]);
206
if((sflags&SF_RDWR) == SF_RDWR)
207
{ CLOSE(child[!ckeep]);
208
SETCLOEXEC(child[ckeep]);
211
/* save process info */
212
fd = (sflags&SF_RDWR) == SF_RDWR ? child[ckeep] : -1;
213
if(_sfpopen(f,fd,pid,stdio) < 0)
220
case 0 : /* in child process */
221
/* determine what to keep */
223
{ pkeep = WRITE; ckeep = READ; }
224
else { pkeep = READ; ckeep = WRITE; }
226
/* zap fd that we don't need */
227
CLOSE(parent[!pkeep]);
228
if((sflags&SF_RDWR) == SF_RDWR)
229
CLOSE(child[!ckeep]);
231
/* use sfsetfd to make these descriptors the std-ones */
232
SFCLEAR(&sf,NIL(Vtmutex_t*));
234
/* must be careful so not to close something useful */
235
if((sflags&SF_RDWR) == SF_RDWR && pkeep == child[ckeep])
236
if((child[ckeep] = dup(pkeep)) < 0)
237
_exit(EXIT_NOTFOUND);
239
if(parent[pkeep] != pkeep)
240
{ sf.file = parent[pkeep];
242
if(sfsetfd(&sf,pkeep) != pkeep)
243
_exit(EXIT_NOTFOUND);
246
if((sflags&SF_RDWR) == SF_RDWR && child[ckeep] != ckeep)
247
{ sf.file = child[ckeep];
249
if(sfsetfd(&sf,ckeep) != ckeep)
250
_exit(EXIT_NOTFOUND);
256
case -1 : /* error */
259
{ CLOSE(parent[0]); CLOSE(parent[1]); }
261
{ CLOSE(child[0]); CLOSE(child[1]); }
264
#endif /*_PACKAGE_ast*/