1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 #pragma ident "%Z%%M% %I% %E% SMI"
31 /*
32 *
33 * UNIX shell
34 *
35 */
36
37
38 #include "defs.h"
39 #include <errno.h>
40 #include "sym.h"
41 #include "hash.h"
42 #include <sys/types.h>
43 #include <sys/times.h>
44
45 void
builtin(int type,int argc,unsigned char ** argv,struct trenod * t)46 builtin(int type, int argc, unsigned char **argv, struct trenod *t)
47 {
48 short index = initio(t->treio, (type != SYSEXEC));
49 unsigned char *a1 = argv[1];
50
51 switch (type)
52 {
53
54 case SYSSUSP:
55 syssusp(argc,argv);
56 break;
57
58 case SYSSTOP:
59 sysstop(argc,argv);
60 break;
61
62 case SYSKILL:
63 syskill(argc,argv);
64 break;
65
66 case SYSFGBG:
67 sysfgbg(argc,argv);
68 break;
69
70 case SYSJOBS:
71 sysjobs(argc,argv);
72 break;
73
74 case SYSDOT:
75 if (a1)
76 {
77 int f;
78
79 if ((f = pathopen(getpath(a1), a1)) < 0)
80 failed(a1, notfound);
81 else
82 execexp(0, f);
83 }
84 break;
85
86 case SYSTIMES:
87 {
88 struct tms tms;
89
90 times(&tms);
91 prt(tms.tms_cutime);
92 prc_buff(SPACE);
93 prt(tms.tms_cstime);
94 prc_buff(NL);
95 }
96 break;
97
98 case SYSEXIT:
99 if ( tried_to_exit++ || endjobs(JOB_STOPPED) ){
100 flags |= forcexit; /* force exit */
101 exitsh(a1 ? stoi(a1) : retval);
102 }
103 break;
104
105 case SYSNULL:
106 t->treio = 0;
107 break;
108
109 case SYSCONT:
110 if (loopcnt)
111 {
112 execbrk = breakcnt = 1;
113 if (a1)
114 breakcnt = stoi(a1);
115 if (breakcnt > loopcnt)
116 breakcnt = loopcnt;
117 else
118 breakcnt = -breakcnt;
119 }
120 break;
121
122 case SYSBREAK:
123 if (loopcnt)
124 {
125 execbrk = breakcnt = 1;
126 if (a1)
127 breakcnt = stoi(a1);
128 if (breakcnt > loopcnt)
129 breakcnt = loopcnt;
130 }
131 break;
132
133 case SYSTRAP:
134 systrap(argc,argv);
135 break;
136
137 case SYSEXEC:
138 argv++;
139 ioset = 0;
140 if (a1 == 0) {
141 setmode(0);
142 break;
143 }
144 /* FALLTHROUGH */
145
146 #ifdef RES /* Research includes login as part of the shell */
147
148 case SYSLOGIN:
149 if (!endjobs(JOB_STOPPED|JOB_RUNNING))
150 break;
151 oldsigs();
152 execa(argv, -1);
153 done(0);
154 #else
155
156 case SYSNEWGRP:
157 if (flags & rshflg)
158 failed(argv[0], restricted);
159 else if (!endjobs(JOB_STOPPED|JOB_RUNNING))
160 break;
161 else
162 {
163 flags |= forcexit; /* bad exec will terminate shell */
164 oldsigs();
165 rmtemp(0);
166 rmfunctmp();
167 #ifdef ACCT
168 doacct();
169 #endif
170 execa(argv, -1);
171 done(0);
172 }
173
174 #endif
175
176 case SYSCD:
177 if (flags & rshflg)
178 failed(argv[0], restricted);
179 else if ((a1 && *a1) || (a1 == 0 && (a1 = homenod.namval)))
180 {
181 unsigned char *cdpath;
182 unsigned char *dir;
183 int f;
184
185 if ((cdpath = cdpnod.namval) == 0 ||
186 *a1 == '/' ||
187 cf(a1, ".") == 0 ||
188 cf(a1, "..") == 0 ||
189 (*a1 == '.' && (*(a1+1) == '/' || *(a1+1) == '.' && *(a1+2) == '/')))
190 cdpath = (unsigned char *)nullstr;
191
192 do
193 {
194 dir = cdpath;
195 cdpath = catpath(cdpath,a1);
196 }
197 while ((f = (chdir((const char *) curstak()) < 0)) &&
198 cdpath);
199
200 if (f) {
201 switch(errno) {
202 case EMULTIHOP:
203 failed(a1, emultihop);
204 break;
205 case ENOTDIR:
206 failed(a1, enotdir);
207 break;
208 case ENOENT:
209 failed(a1, enoent);
210 break;
211 case EACCES:
212 failed(a1, eacces);
213 break;
214 case ENOLINK:
215 failed(a1, enolink);
216 break;
217 default:
218 failed(a1, baddir);
219 break;
220 }
221 }
222 else
223 {
224 cwd(curstak());
225 if (cf(nullstr, dir) &&
226 *dir != ':' &&
227 any('/', curstak()) &&
228 flags & prompt)
229 {
230 prs_buff(cwdget());
231 prc_buff(NL);
232 }
233 }
234 zapcd();
235 }
236 else
237 {
238 if (a1)
239 error(nulldir);
240 else
241 error(nohome);
242 }
243
244 break;
245
246 case SYSSHFT:
247 {
248 int places;
249
250 places = a1 ? stoi(a1) : 1;
251
252 if ((dolc -= places) < 0)
253 {
254 dolc = 0;
255 error(badshift);
256 }
257 else
258 dolv += places;
259 }
260
261 break;
262
263 case SYSWAIT:
264 syswait(argc,argv);
265 break;
266
267 case SYSREAD:
268 if(argc < 2)
269 failed(argv[0],mssgargn);
270 rwait = 1;
271 exitval = readvar(&argv[1]);
272 rwait = 0;
273 break;
274
275 case SYSSET:
276 if (a1)
277 {
278 int cnt;
279
280 cnt = options(argc, argv);
281 if (cnt > 1)
282 setargs(argv + argc - cnt);
283 }
284 else if (comptr(t)->comset == 0)
285 {
286 /*
287 * scan name chain and print
288 */
289 namscan(printnam);
290 }
291 break;
292
293 case SYSRDONLY:
294 exitval = 0;
295 if (a1)
296 {
297 while (*++argv)
298 attrib(lookup(*argv), N_RDONLY);
299 }
300 else
301 namscan(printro);
302
303 break;
304
305 case SYSXPORT:
306 {
307 struct namnod *n;
308
309 exitval = 0;
310 if (a1)
311 {
312 while (*++argv)
313 {
314 n = lookup(*argv);
315 if (n->namflg & N_FUNCTN)
316 error(badexport);
317 else
318 attrib(n, N_EXPORT);
319 }
320 }
321 else
322 namscan(printexp);
323 }
324 break;
325
326 case SYSEVAL:
327 if (a1)
328 execexp(a1, &argv[2]);
329 break;
330
331 #ifndef RES
332 case SYSULIMIT:
333 sysulimit(argc, argv);
334 break;
335
336 case SYSUMASK:
337 if (a1)
338 {
339 int c;
340 mode_t i;
341
342 i = 0;
343 while ((c = *a1++) >= '0' && c <= '7')
344 i = (i << 3) + c - '0';
345 umask(i);
346 }
347 else
348 {
349 mode_t i;
350 int j;
351
352 umask(i = umask(0));
353 prc_buff('0');
354 for (j = 6; j >= 0; j -= 3)
355 prc_buff(((i >> j) & 07) +'0');
356 prc_buff(NL);
357 }
358 break;
359
360 #endif
361
362 case SYSTST:
363 exitval = test(argc, argv);
364 break;
365
366 case SYSECHO:
367 exitval = echo(argc, argv);
368 break;
369
370 case SYSHASH:
371 exitval = 0;
372
373 if (a1)
374 {
375 if (a1[0] == '-')
376 {
377 if (a1[1] == 'r')
378 zaphash();
379 else
380 error(badopt);
381 }
382 else
383 {
384 while (*++argv)
385 {
386 if (hashtype(hash_cmd(*argv)) == NOTFOUND)
387 failed(*argv, notfound);
388 }
389 }
390 }
391 else
392 hashpr();
393
394 break;
395
396 case SYSPWD:
397 {
398 exitval = 0;
399 cwdprint();
400 }
401 break;
402
403 case SYSRETURN:
404 if (funcnt == 0)
405 error(badreturn);
406
407 execbrk = 1;
408 exitval = (a1 ? stoi(a1) : retval);
409 break;
410
411 case SYSTYPE:
412 exitval = 0;
413 if (a1)
414 {
415 /* return success only if all names are found */
416 while (*++argv)
417 exitval |= what_is_path(*argv);
418 }
419 break;
420
421 case SYSUNS:
422 exitval = 0;
423 if (a1)
424 {
425 while (*++argv)
426 unset_name(*argv);
427 }
428 break;
429
430 case SYSGETOPT: {
431 int getoptval;
432 struct namnod *n;
433 extern unsigned char numbuf[];
434 unsigned char *varnam = argv[2];
435 unsigned char c[2];
436 if(argc < 3) {
437 failure(argv[0],mssgargn);
438 break;
439 }
440 exitval = 0;
441 n = lookup("OPTIND");
442 optind = stoi(n->namval);
443 if(argc > 3) {
444 argv[2] = dolv[0];
445 getoptval = getopt(argc-2, (char **)&argv[2], (char *)argv[1]);
446 }
447 else
448 getoptval = getopt(dolc+1, (char **)dolv, (char *)argv[1]);
449 if(getoptval == -1) {
450 itos(optind);
451 assign(n, numbuf);
452 n = lookup(varnam);
453 assign(n, (unsigned char *)nullstr);
454 exitval = 1;
455 break;
456 }
457 argv[2] = varnam;
458 itos(optind);
459 assign(n, numbuf);
460 c[0] = getoptval;
461 c[1] = 0;
462 n = lookup(varnam);
463 assign(n, c);
464 n = lookup("OPTARG");
465 assign(n, (unsigned char *)optarg);
466 }
467 break;
468
469 default:
470 prs_buff(_gettext("unknown builtin\n"));
471 }
472
473
474 flushb();
475 restore(index);
476 chktrap();
477 }
478