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