summaryrefslogtreecommitdiff
path: root/usr/src/cmd/sh/bltin.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/sh/bltin.c')
-rw-r--r--usr/src/cmd/sh/bltin.c480
1 files changed, 480 insertions, 0 deletions
diff --git a/usr/src/cmd/sh/bltin.c b/usr/src/cmd/sh/bltin.c
new file mode 100644
index 0000000000..ec84f7cf06
--- /dev/null
+++ b/usr/src/cmd/sh/bltin.c
@@ -0,0 +1,480 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright (c) 1996, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.3.8.1 */
+/*
+ *
+ * UNIX shell
+ *
+ */
+
+
+#include "defs.h"
+#include <errno.h>
+#include "sym.h"
+#include "hash.h"
+#include <sys/types.h>
+#include <sys/times.h>
+
+builtin(type, argc, argv, t)
+int type, argc;
+unsigned char **argv;
+struct trenod *t;
+{
+ short index = initio(t->treio, (type != SYSEXEC));
+ unsigned char *a1 = argv[1];
+
+ switch (type)
+ {
+
+ case SYSSUSP:
+ syssusp(argc,argv);
+ break;
+
+ case SYSSTOP:
+ sysstop(argc,argv);
+ break;
+
+ case SYSKILL:
+ syskill(argc,argv);
+ break;
+
+ case SYSFGBG:
+ sysfgbg(argc,argv);
+ break;
+
+ case SYSJOBS:
+ sysjobs(argc,argv);
+ break;
+
+ case SYSDOT:
+ if (a1)
+ {
+ register int f;
+
+ if ((f = pathopen(getpath(a1), a1)) < 0)
+ failed(a1, notfound);
+ else
+ execexp(0, f);
+ }
+ break;
+
+ case SYSTIMES:
+ {
+ struct tms tms;
+
+ times(&tms);
+ prt(tms.tms_cutime);
+ prc_buff(SPACE);
+ prt(tms.tms_cstime);
+ prc_buff(NL);
+ }
+ break;
+
+ case SYSEXIT:
+ if ( tried_to_exit++ || endjobs(JOB_STOPPED) ){
+ flags |= forcexit; /* force exit */
+ exitsh(a1 ? stoi(a1) : retval);
+ }
+ break;
+
+ case SYSNULL:
+ t->treio = 0;
+ break;
+
+ case SYSCONT:
+ if (loopcnt)
+ {
+ execbrk = breakcnt = 1;
+ if (a1)
+ breakcnt = stoi(a1);
+ if (breakcnt > loopcnt)
+ breakcnt = loopcnt;
+ else
+ breakcnt = -breakcnt;
+ }
+ break;
+
+ case SYSBREAK:
+ if (loopcnt)
+ {
+ execbrk = breakcnt = 1;
+ if (a1)
+ breakcnt = stoi(a1);
+ if (breakcnt > loopcnt)
+ breakcnt = loopcnt;
+ }
+ break;
+
+ case SYSTRAP:
+ systrap(argc,argv);
+ break;
+
+ case SYSEXEC:
+ argv++;
+ ioset = 0;
+ if (a1 == 0) {
+ setmode(0);
+ break;
+ }
+ /* FALLTHROUGH */
+
+#ifdef RES /* Research includes login as part of the shell */
+
+ case SYSLOGIN:
+ if (!endjobs(JOB_STOPPED|JOB_RUNNING))
+ break;
+ oldsigs();
+ execa(argv, -1);
+ done(0);
+#else
+
+ case SYSNEWGRP:
+ if (flags & rshflg)
+ failed(argv[0], restricted);
+ else if (!endjobs(JOB_STOPPED|JOB_RUNNING))
+ break;
+ else
+ {
+ flags |= forcexit; /* bad exec will terminate shell */
+ oldsigs();
+ rmtemp(0);
+ rmfunctmp();
+#ifdef ACCT
+ doacct();
+#endif
+ execa(argv, -1);
+ done(0);
+ }
+
+#endif
+
+ case SYSCD:
+ if (flags & rshflg)
+ failed(argv[0], restricted);
+ else if ((a1 && *a1) || (a1 == 0 && (a1 = homenod.namval)))
+ {
+ unsigned char *cdpath;
+ unsigned char *dir;
+ int f;
+
+ if ((cdpath = cdpnod.namval) == 0 ||
+ *a1 == '/' ||
+ cf(a1, ".") == 0 ||
+ cf(a1, "..") == 0 ||
+ (*a1 == '.' && (*(a1+1) == '/' || *(a1+1) == '.' && *(a1+2) == '/')))
+ cdpath = (unsigned char *)nullstr;
+
+ do
+ {
+ dir = cdpath;
+ cdpath = catpath(cdpath,a1);
+ }
+ while ((f = (chdir((const char *) curstak()) < 0)) &&
+ cdpath);
+
+ if (f) {
+ switch(errno) {
+ case EMULTIHOP:
+ failed(a1, emultihop);
+ break;
+ case ENOTDIR:
+ failed(a1, enotdir);
+ break;
+ case ENOENT:
+ failed(a1, enoent);
+ break;
+ case EACCES:
+ failed(a1, eacces);
+ break;
+ case ENOLINK:
+ failed(a1, enolink);
+ break;
+ default:
+ failed(a1, baddir);
+ break;
+ }
+ }
+ else
+ {
+ cwd(curstak());
+ if (cf(nullstr, dir) &&
+ *dir != ':' &&
+ any('/', curstak()) &&
+ flags & prompt)
+ {
+ prs_buff(cwdget());
+ prc_buff(NL);
+ }
+ }
+ zapcd();
+ }
+ else
+ {
+ if (a1)
+ error(nulldir);
+ else
+ error(nohome);
+ }
+
+ break;
+
+ case SYSSHFT:
+ {
+ int places;
+
+ places = a1 ? stoi(a1) : 1;
+
+ if ((dolc -= places) < 0)
+ {
+ dolc = 0;
+ error(badshift);
+ }
+ else
+ dolv += places;
+ }
+
+ break;
+
+ case SYSWAIT:
+ syswait(argc,argv);
+ break;
+
+ case SYSREAD:
+ if(argc < 2)
+ failed(argv[0],mssgargn);
+ rwait = 1;
+ exitval = readvar(&argv[1]);
+ rwait = 0;
+ break;
+
+ case SYSSET:
+ if (a1)
+ {
+ int cnt;
+
+ cnt = options(argc, argv);
+ if (cnt > 1)
+ setargs(argv + argc - cnt);
+ }
+ else if (comptr(t)->comset == 0)
+ {
+ /*
+ * scan name chain and print
+ */
+ namscan(printnam);
+ }
+ break;
+
+ case SYSRDONLY:
+ exitval = 0;
+ if (a1)
+ {
+ while (*++argv)
+ attrib(lookup(*argv), N_RDONLY);
+ }
+ else
+ namscan(printro);
+
+ break;
+
+ case SYSXPORT:
+ {
+ struct namnod *n;
+
+ exitval = 0;
+ if (a1)
+ {
+ while (*++argv)
+ {
+ n = lookup(*argv);
+ if (n->namflg & N_FUNCTN)
+ error(badexport);
+ else
+ attrib(n, N_EXPORT);
+ }
+ }
+ else
+ namscan(printexp);
+ }
+ break;
+
+ case SYSEVAL:
+ if (a1)
+ execexp(a1, &argv[2]);
+ break;
+
+#ifndef RES
+ case SYSULIMIT:
+ sysulimit(argc, argv);
+ break;
+
+ case SYSUMASK:
+ if (a1)
+ {
+ int c;
+ mode_t i;
+
+ i = 0;
+ while ((c = *a1++) >= '0' && c <= '7')
+ i = (i << 3) + c - '0';
+ umask(i);
+ }
+ else
+ {
+ mode_t i;
+ int j;
+
+ umask(i = umask(0));
+ prc_buff('0');
+ for (j = 6; j >= 0; j -= 3)
+ prc_buff(((i >> j) & 07) +'0');
+ prc_buff(NL);
+ }
+ break;
+
+#endif
+
+ case SYSTST:
+ exitval = test(argc, argv);
+ break;
+
+ case SYSECHO:
+ exitval = echo(argc, argv);
+ break;
+
+ case SYSHASH:
+ exitval = 0;
+
+ if (a1)
+ {
+ if (a1[0] == '-')
+ {
+ if (a1[1] == 'r')
+ zaphash();
+ else
+ error(badopt);
+ }
+ else
+ {
+ while (*++argv)
+ {
+ if (hashtype(hash_cmd(*argv)) == NOTFOUND)
+ failed(*argv, notfound);
+ }
+ }
+ }
+ else
+ hashpr();
+
+ break;
+
+ case SYSPWD:
+ {
+ exitval = 0;
+ cwdprint();
+ }
+ break;
+
+ case SYSRETURN:
+ if (funcnt == 0)
+ error(badreturn);
+
+ execbrk = 1;
+ exitval = (a1 ? stoi(a1) : retval);
+ break;
+
+ case SYSTYPE:
+ exitval = 0;
+ if (a1)
+ {
+ /* return success only if all names are found */
+ while (*++argv)
+ exitval |= what_is_path(*argv);
+ }
+ break;
+
+ case SYSUNS:
+ exitval = 0;
+ if (a1)
+ {
+ while (*++argv)
+ unset_name(*argv);
+ }
+ break;
+
+ case SYSGETOPT: {
+ int getoptval;
+ struct namnod *n;
+ extern unsigned char numbuf[];
+ unsigned char *varnam = argv[2];
+ unsigned char c[2];
+ if(argc < 3) {
+ failure(argv[0],mssgargn);
+ break;
+ }
+ exitval = 0;
+ n = lookup("OPTIND");
+ optind = stoi(n->namval);
+ if(argc > 3) {
+ argv[2] = dolv[0];
+ getoptval = getopt(argc-2, (char **)&argv[2], (char *)argv[1]);
+ }
+ else
+ getoptval = getopt(dolc+1, (char **)dolv, (char *)argv[1]);
+ if(getoptval == -1) {
+ itos(optind);
+ assign(n, numbuf);
+ n = lookup(varnam);
+ assign(n, nullstr);
+ exitval = 1;
+ break;
+ }
+ argv[2] = varnam;
+ itos(optind);
+ assign(n, numbuf);
+ c[0] = getoptval;
+ c[1] = 0;
+ n = lookup(varnam);
+ assign(n, c);
+ n = lookup("OPTARG");
+ assign(n, optarg);
+ }
+ break;
+
+ default:
+ prs_buff("unknown builtin\n");
+ }
+
+
+ flushb();
+ restore(index);
+ chktrap();
+}