BSD 2 development
[unix-history] / src / csh / sh.exec.c
CommitLineData
41c680d7
BJ
1/* Copyright (c) 1979 Regents of the University of California */
2#include "sh.h"
3
4/*
5 * C shell
6 */
7
8/*
9 * System level search and execute of a command.
10 * We look in each directory for the specified command name.
11 * If the name contains a '/' then we execute only the full path name.
12 * If there is no search path then we execute only full path names.
13 */
14
15/*
16 * As we search for the command we note the first non-trivial error
17 * message for presentation to the user. This allows us often
18 * to show that a file has the wrong mode/no access when the file
19 * is not in the last component of the search path, so we must
20 * go on after first detecting the error.
21 */
22char *exerr; /* Execution error message */
23char *expath; /* Path for exerr */
24
25/* Dummy search path for just absolute search when no path */
26char *justabs[] = { "", 0 };
27
28doexec(t)
29 register struct command *t;
30{
31 char *sav;
32 register char *dp, **pv, **av;
33 register struct varent *v;
34 bool slash = any('/', t->t_dcom[0]);
35 char *blk[2];
36
37 /*
38 * Glob the command name. If this does anything, then we
39 * will execute the command only relative to ".". One special
40 * case: if there is no PATH, then we execute only commands
41 * which start with '/'.
42 */
43 dp = globone(t->t_dcom[0]);
44 xfree(t->t_dcom[0]);
45 exerr = 0; expath = t->t_dcom[0] = dp;
46 v = adrof("path");
47 if (v == 0 && expath[0] != '/')
48 pexerr();
49 slash |= gflag;
50
51 /*
52 * Glob the argument list, if necessary.
53 * Otherwise trim off the quote bits.
54 */
55 gflag = 0; av = &t->t_dcom[1];
56 rscan(av, tglob);
57 if (gflag) {
58 av = glob(av);
59 if (av == 0)
60 error("No match");
61 }
62 blk[0] = t->t_dcom[0];
63 blk[1] = 0;
64 av = blkspl(blk, av);
65 scan(av, trim);
66
67 xechoit(av); /* Echo command if -x */
68 closech(); /* Close random fd's */
69
70 /*
71 * If no path, no words in path, or a / in the filename
72 * then restrict the command search.
73 */
74 if (v == 0 || v->vec[0] == 0 || slash)
75 pv = justabs;
76 else
77 pv = v->vec;
78 sav = strspl("/", *av); /* / command name for postpending */
79 do {
80 if (pv[0][0] == 0 || eq(pv[0], ".")) /* don't make ./xxx */
81 texec(*av, av);
82 else {
83 dp = strspl(*pv, sav);
84 texec(dp, av);
85 xfree(dp);
86 }
87 pv++;
88 } while (*pv);
89 xfree(sav);
90 xfree(av);
91 pexerr();
92}
93
94pexerr()
95{
96
97 /* Couldn't find the damn thing */
98 setname(expath);
99 xfree(expath);
100 if (exerr)
101 bferr(exerr);
102 bferr("Command not found");
103}
104
105/* Last resort shell */
106char *lastsh[] = { SHELLPATH, 0 };
107
108/*
109 * Execute command f, arg list t.
110 * Record error message if not found.
111 * Also do shell scripts here.
112 */
113texec(f, t)
114 char *f;
115 register char **t;
116{
117 register struct varent *v;
118 register char **vp;
119 extern char *sys_errlist[];
120
121 execv(f, t);
122 switch (errno) {
123
124 case ENOEXEC:
125 /*
126 * If there is an alias for shell, then
127 * put the words of the alias in front of the
128 * argument list replacing the command name.
129 * Note no interpretation of the words at this point.
130 */
131 v = adrof1("shell", &aliases);
132 if (v == 0) {
133#ifdef OTHERSH
134 register int ff = open(f, 0);
135 char ch;
136#endif
137
138 vp = lastsh;
139 vp[0] = adrof("shell") ? value("shell") : SHELLPATH;
140#ifdef OTHERSH
141 if (ff != -1 && read(ff, &ch, 1) == 1 && ch != '#')
142 vp[0] = OTHERSH;
143 close(ff);
144#endif
145 } else
146 vp = v->vec;
147 t[0] = f;
148 t = blkspl(vp, t); /* Splice up the new arglst */
149 f = *t;
150 execv(f, t);
151 xfree(t);
152 /* The sky is falling, the sky is falling! */
153
154 case ENOMEM:
155 Perror(f);
156
157 case ENOENT:
158 break;
159
160 default:
161 if (exerr == 0) {
162 exerr = sys_errlist[errno];
163 expath = savestr(f);
164 }
165 }
166}
167
168execash(t, kp)
169 register struct command *kp;
170{
171
172 didcch++;
173 lshift(kp->t_dcom, 1);
174 doexec(kp);
175 /*NOTREACHED*/
176}
177
178xechoit(t)
179 char **t;
180{
181
182 if (adrof("echo")) {
183 flush();
184 haderr = 1;
185 blkpr(t), printf("\n");
186 haderr = 0;
187 }
188}