2 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
5 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
6 /* All Rights Reserved */
9 * Copyright (c) 1980 Regents of the University of California.
10 * All rights reserved. The Berkeley Software License Agreement
11 * specifies the terms and conditions for redistribution.
17 #include "sh.tconst.h"
25 * System level search and execute of a command.
26 * We look in each directory for the specified command name.
27 * If the name contains a '/' then we execute only the full path name.
28 * If there is no search path then we execute only full path names.
32 * As we search for the command we note the first non-trivial error
33 * message for presentation to the user. This allows us often
34 * to show that a file has the wrong mode/no access when the file
35 * is not in the last component of the search path, so we must
36 * go on after first detecting the error.
38 char *exerr
; /* Execution error message */
41 void texec(struct command
*, tchar
*, tchar
**);
42 void xechoit(tchar
**);
45 static void tconvert(struct command
*, tchar
*, tchar
**);
48 extern DIR *opendir_(tchar
*);
51 doexec(struct command
*t
)
54 tchar
*dp
, **pv
, **av
;
57 int hashval
, hashval1
, i
;
60 tprintf("TRACE- doexec()\n");
64 * Glob the command name. If this does anything, then we
65 * will execute the command only relative to ".". One special
66 * case: if there is no PATH, then we execute only commands
67 * which start with '/'.
69 dp
= globone(t
->t_dcom
[0]);
71 exerr
= 0; t
->t_dcom
[0] = dp
;
74 v
= adrof(S_path
/* "path" */);
75 if (v
== 0 && dp
[0] != '/') {
81 * Glob the argument list, if necessary.
82 * Otherwise trim off the quote bits.
84 gflag
= 0; av
= &t
->t_dcom
[1];
91 blk
[0] = t
->t_dcom
[0];
98 slash
|= any('/', av
[0]);
100 xechoit(av
); /* Echo command if -x */
102 * Since all internal file descriptors are set to close on exec,
103 * we don't need to close them explicitly here. Just reorient
104 * ourselves for error messages.
106 SHIN
= 0; SHOUT
= 1; SHDIAG
= 2; OLDSTD
= 0;
109 * We must do this AFTER any possible forking (like `foo`
110 * in glob) so that this shell can still do subprocesses.
112 (void) sigsetmask(0);
115 * If no path, no words in path, or a / in the filename
116 * then restrict the command search.
118 if (v
== 0 || v
->vec
[0] == 0 || slash
)
122 /* / command name for postpending */
123 sav
= strspl(S_SLASH
/* "/" */, *av
);
128 hashval
= hashname(*av
);
134 if (!slash
&& pv
[0][0] == '/' && havhash
) {
135 hashval1
= hash(hashval
, i
);
136 if (!bit(xhash
, hashval1
))
140 /* don't make ./xxx */
141 if (pv
[0][0] == 0 || eq(pv
[0], S_DOT
/* "." */)) {
144 dp
= strspl(*pv
, sav
);
178 tprintf("TRACE- pexerr()\n");
180 /* Couldn't find the damn thing */
183 bferr("Command not found");
187 * Execute command f, arg list t.
188 * Record error message if not found.
189 * Also do shell scripts here.
192 texec(struct command
*cmd
, tchar
*f
, tchar
**t
)
199 tprintf("TRACE- texec()\n");
201 /* convert cfname and cargs from tchar to char */
204 execv(cmd
->cfname
, cmd
->cargs
);
207 * exec returned, free up allocations from above
208 * tconvert(), zero cfname and cargs to prevent
209 * duplicate free() in freesyn()
212 chr_blkfree(cmd
->cargs
);
213 cmd
->cfname
= (char *)0;
214 cmd
->cargs
= (char **)0;
218 /* check that this is not a binary file */
220 int ff
= open_(f
, 0);
221 tchar ch
[MB_LEN_MAX
];
223 if (ff
!= -1 && read_(ff
, ch
, 1) == 1 &&
224 !isprint(ch
[0]) && !isspace(ch
[0])) {
225 printf("Cannot execute binary file.\n");
235 * If there is an alias for shell, then
236 * put the words of the alias in front of the
237 * argument list replacing the command name.
238 * Note no interpretation of the words at this point.
240 v
= adrof1(S_shell
/* "shell" */, &aliases
);
243 int ff
= open_(f
, 0);
244 tchar ch
[MB_LEN_MAX
];
248 vp
[0] = adrof(S_shell
/* "shell" */) ?
249 value(S_shell
/* "shell" */) :
250 S_SHELLPATH
/* SHELLPATH */;
251 vp
[1] = (tchar
*) NULL
;
253 if (ff
!= -1 && read_(ff
, ch
, 1) == 1 && ch
[0] != '#')
254 vp
[0] = S_OTHERSH
/* OTHERSH */;
261 t
= blkspl(vp
, t
); /* Splice up the new arglst */
264 tconvert(cmd
, f
, t
); /* convert tchar to char */
267 * now done with tchar arg list t,
268 * free the space calloc'd by above blkspl()
272 execv(cmd
->cfname
, cmd
->cargs
); /* exec the command */
274 /* exec returned, same free'ing as above */
276 chr_blkfree(cmd
->cargs
);
277 cmd
->cfname
= (char *)0;
278 cmd
->cargs
= (char **)0;
280 /* The sky is falling, the sky is falling! */
290 exerr
= strerror(errno
);
298 tconvert(struct command
*cmd
, tchar
*fname
, tchar
**list
)
303 cmd
->cfname
= tstostr(NULL
, fname
);
306 rc
= cmd
->cargs
= (char **)
307 xcalloc((uint_t
)(len
+ 1), sizeof (char **));
309 *rc
++ = tstostr(NULL
, *list
++);
316 execash(tchar
**t
, struct command
*kp
)
319 tprintf("TRACE- execash()\n");
323 (void) signal(SIGINT
, parintr
);
324 (void) signal(SIGQUIT
, parintr
);
325 (void) signal(SIGTERM
, parterm
); /* if doexec loses, screw */
326 lshift(kp
->t_dcom
, 1);
336 tprintf("TRACE- xechoit()\n");
339 if (adrof(S_echo
/* "echo" */)) {
342 blkpr(t
), Putchar('\n');
348 * This routine called when user enters "rehash".
349 * Both the path and cdpath caching arrays will
350 * be rehashed, via calling dohash. If either
351 * variable is not set with a value, then dohash
362 * Fill up caching arrays for path and cdpath
365 dohash(char cachearray
[])
375 tchar curdir_
[MAXNAMLEN
+1];
378 tprintf("TRACE- dohash()\n");
381 if (cachearray
== xhash
) {
383 v
= adrof(S_path
/* "path" */);
384 } else { /* Caching $cdpath */
386 v
= adrof(S_cdpath
/* "cdpath" */);
389 for (cnt
= 0; cnt
< (HSHSIZ
/ 8); cnt
++)
393 for (pv
= v
->vec
; *pv
; pv
++, i
++) {
396 dirp
= opendir_(*pv
);
399 if (fstat(dirp
->dd_fd
, &stb
) < 0 || !isdir(stb
)) {
400 unsetfd(dirp
->dd_fd
);
404 while ((dp
= readdir(dirp
)) != NULL
) {
407 if (dp
->d_name
[0] == '.' &&
408 (dp
->d_name
[1] == '\0' ||
409 dp
->d_name
[1] == '.' && dp
->d_name
[2] == '\0'))
411 hashval
= hash(hashname(strtots(curdir_
, dp
->d_name
)),
413 bis(cachearray
, hashval
);
415 unsetfd(dirp
->dd_fd
);
425 tprintf("TRACE- dounhash()\n");
436 tprintf("TRACE- hashstat_()\n");
440 printf("%d hits, %d misses, %d%%\n",
441 hits
, misses
, 100 * hits
/ (hits
+ misses
));
446 * Hash a command name.
454 tprintf("TRACE- hashname()\n");