8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sh / service.c
blobe74a35b471ca7f295169d7b99de8fcd4f288c813
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * UNIX shell
33 #include "defs.h"
34 #include <errno.h>
35 #include <fcntl.h>
37 #define ARGMK 01
39 static unsigned char *execs();
40 static void gsort();
41 static int split();
42 extern void makearg(struct argnod *);
43 extern short topfd;
47 * service routines for `execute'
49 short
50 initio(struct ionod *iop, int save)
52 unsigned char *ion;
53 int iof, fd;
54 int ioufd;
55 short lastfd;
56 int newmode;
58 lastfd = topfd;
59 while (iop) {
60 iof = iop->iofile;
61 ion = mactrim(iop->ioname);
62 ioufd = iof & IOUFD;
64 if (*ion && (flags&noexec) == 0) {
65 if (save) {
66 fdmap[topfd].org_fd = ioufd;
67 fdmap[topfd++].dup_fd = savefd(ioufd);
70 if (iof & IODOC_SUBST) {
71 struct tempblk tb;
73 subst(chkopen(ion, 0), (fd = tmpfil(&tb)));
76 * pushed in tmpfil() --
77 * bug fix for problem with
78 * in-line scripts
80 poptemp();
82 fd = chkopen(tmpout, 0);
83 unlink((const char *)tmpout);
84 } else if (iof & IOMOV) {
85 if (eq(minus, ion)) {
86 fd = -1;
87 close(ioufd);
88 } else if ((fd = stoi(ion)) >= USERIO) {
89 failed(ion, badfile);
91 else
92 fd = dup(fd);
93 } else if (((iof & IOPUT) == 0) && ((iof & IORDW) == 0))
94 fd = chkopen(ion, 0);
95 else if (iof & IORDW) /* For <> */ {
96 newmode = O_RDWR|O_CREAT;
97 fd = chkopen(ion, newmode);
98 } else if (flags & rshflg) {
99 failed(ion, restricted);
100 } else if (iof & IOAPP &&
101 (fd = open((char *)ion, 1)) >= 0) {
102 lseek(fd, (off_t)0, SEEK_END);
103 } else {
104 fd = create(ion);
106 if (fd >= 0)
107 renamef(fd, ioufd);
110 iop = iop->ionxt;
112 return (lastfd);
115 unsigned char *
116 simple(s)
117 unsigned char *s;
119 unsigned char *sname;
121 sname = s;
122 while (1) {
123 if (any('/', sname))
124 while (*sname++ != '/')
126 else
127 return (sname);
131 unsigned char *
132 getpath(s)
133 unsigned char *s;
135 unsigned char *path, *newpath;
136 int pathlen;
138 if (any('/', s))
140 if (flags & rshflg)
141 failed(s, restricted);
142 else
143 return ((unsigned char *)nullstr);
144 } else if ((path = pathnod.namval) == 0)
145 return ((unsigned char *)defpath);
146 else {
147 pathlen = length(path)-1;
148 /* Add extra ':' if PATH variable ends in ':' */
149 if (pathlen > 2 && path[pathlen - 1] == ':' &&
150 path[pathlen - 2] != ':') {
151 newpath = locstak();
152 (void) memcpystak(newpath, path, pathlen);
153 newpath[pathlen] = ':';
154 endstak(newpath + pathlen + 1);
155 return (newpath);
156 } else
157 return (cpystak(path));
162 pathopen(unsigned char *path, unsigned char *name)
164 int f;
168 path = catpath(path, name);
169 } while ((f = open((char *)curstak(), 0)) < 0 && path);
170 return (f);
173 unsigned char *
174 catpath(unsigned char *path, unsigned char *name)
177 * leaves result on top of stack
179 unsigned char *scanp = path;
180 unsigned char *argp = locstak();
182 while (*scanp && *scanp != COLON) {
183 if (argp >= brkend)
184 growstak(argp);
185 *argp++ = *scanp++;
187 if (scanp != path) {
188 if (argp >= brkend)
189 growstak(argp);
190 *argp++ = '/';
192 if (*scanp == COLON)
193 scanp++;
194 path = (*scanp ? scanp : 0);
195 scanp = name;
198 if (argp >= brkend)
199 growstak(argp);
201 while (*argp++ = *scanp++)
203 return (path);
206 unsigned char *
207 nextpath(unsigned char *path)
209 unsigned char *scanp = path;
211 while (*scanp && *scanp != COLON)
212 scanp++;
214 if (*scanp == COLON)
215 scanp++;
217 return (*scanp ? scanp : 0);
220 static const char *xecmsg;
221 static unsigned char **xecenv;
223 void
224 execa(unsigned char *at[], short pos)
226 unsigned char *path;
227 unsigned char **t = at;
228 int cnt;
230 if ((flags & noexec) == 0) {
231 xecmsg = notfound;
232 path = getpath(*t);
233 xecenv = local_setenv();
235 if (pos > 0) {
236 cnt = 1;
237 while (cnt != pos) {
238 ++cnt;
239 path = nextpath(path);
241 execs(path, t);
242 path = getpath(*t);
244 while (path = execs(path, t))
246 failed(*t, xecmsg);
250 static unsigned char *
251 execs(unsigned char *ap, unsigned char *t[])
253 unsigned char *p, *prefix;
254 unsigned char *savptr;
256 prefix = catpath(ap, t[0]);
257 trim(p = curstak());
258 sigchk();
260 execve((const char *)p, (char *const *)&t[0],
261 (char *const *)xecenv);
263 switch (errno) {
264 case ENOEXEC: /* could be a shell script */
265 funcnt = 0;
266 flags = 0;
267 *flagadr = 0;
268 comdiv = 0;
269 ioset = 0;
270 clearup(); /* remove open files and for loop junk */
271 if (input)
272 close(input);
273 input = chkopen(p, 0);
275 #ifdef ACCT
276 preacct(p); /* reset accounting */
277 #endif
280 * set up new args
283 setargs(t);
284 longjmp(subshell, 1);
286 case ENOMEM:
287 failed(p, toobig);
289 case E2BIG:
290 failed(p, arglist);
292 case ETXTBSY:
293 failed(p, txtbsy);
295 case ELIBACC:
296 failed(p, libacc);
298 case ELIBBAD:
299 failed(p, libbad);
301 case ELIBSCN:
302 failed(p, libscn);
304 case ELIBMAX:
305 failed(p, libmax);
307 default:
308 xecmsg = badexec;
309 case ENOENT:
310 return (prefix);
314 BOOL nosubst;
316 void
317 trim(unsigned char *at)
319 unsigned char *last;
320 unsigned char *current;
321 unsigned char c;
322 int len;
323 wchar_t wc;
325 nosubst = 0;
326 if (current = at) {
327 last = at;
328 while (c = *current) {
329 if ((len = mbtowc(&wc, (char *)current,
330 MB_LEN_MAX)) <= 0) {
331 *last++ = c;
332 current++;
333 continue;
336 if (wc != '\\') {
337 memcpy(last, current, len);
338 last += len;
339 current += len;
340 continue;
343 /* remove \ and quoted nulls */
344 nosubst = 1;
345 current++;
346 if (c = *current) {
347 if ((len = mbtowc(&wc, (char *)current,
348 MB_LEN_MAX)) <= 0) {
349 *last++ = c;
350 current++;
351 continue;
353 memcpy(last, current, len);
354 last += len;
355 current += len;
356 } else
357 current++;
360 *last = 0;
364 /* Same as trim, but only removes backlashes before slashes */
365 void
366 trims(at)
367 unsigned char *at;
369 unsigned char *last;
370 unsigned char *current;
371 unsigned char c;
372 int len;
373 wchar_t wc;
375 if (current = at)
377 last = at;
378 while (c = *current) {
379 if ((len = mbtowc(&wc, (char *)current,
380 MB_LEN_MAX)) <= 0) {
381 *last++ = c;
382 current++;
383 continue;
386 if (wc != '\\') {
387 memcpy(last, current, len);
388 last += len; current += len;
389 continue;
392 /* remove \ and quoted nulls */
393 current++;
394 if (!(c = *current)) {
395 current++;
396 continue;
399 if (c == '/') {
400 *last++ = c;
401 current++;
402 continue;
405 *last++ = '\\';
406 if ((len = mbtowc(&wc, (char *)current,
407 MB_LEN_MAX)) <= 0) {
408 *last++ = c;
409 current++;
410 continue;
412 memcpy(last, current, len);
413 last += len; current += len;
415 *last = 0;
419 unsigned char *
420 mactrim(s)
421 unsigned char *s;
423 unsigned char *t = macro(s);
425 trim(t);
426 return (t);
429 unsigned char **
430 scan(argn)
431 int argn;
433 struct argnod *argp =
434 (struct argnod *)(Rcheat(gchain) & ~ARGMK);
435 unsigned char **comargn, **comargm;
437 comargn = (unsigned char **)getstak(BYTESPERWORD * argn + BYTESPERWORD);
438 comargm = comargn += argn;
439 *comargn = ENDARGS;
440 while (argp)
442 *--comargn = argp->argval;
444 trim(*comargn);
445 argp = argp->argnxt;
447 if (argp == 0 || Rcheat(argp) & ARGMK)
449 gsort(comargn, comargm);
450 comargm = comargn;
452 argp = (struct argnod *)(Rcheat(argp) & ~ARGMK);
454 return (comargn);
457 static void
458 gsort(from, to)
459 unsigned char *from[], *to[];
461 int k, m, n;
462 int i, j;
464 if ((n = to - from) <= 1)
465 return;
466 for (j = 1; j <= n; j *= 2)
468 for (m = 2 * j - 1; m /= 2; )
470 k = n - m;
471 for (j = 0; j < k; j++)
473 for (i = j; i >= 0; i -= m)
475 unsigned char **fromi;
477 fromi = &from[i];
478 if (cf(fromi[m], fromi[0]) > 0)
480 break;
482 else
484 unsigned char *s;
486 s = fromi[m];
487 fromi[m] = fromi[0];
488 fromi[0] = s;
496 * Argument list generation
499 getarg(ac)
500 struct comnod *ac;
502 struct argnod *argp;
503 int count = 0;
504 struct comnod *c;
506 if (c = ac)
508 argp = c->comarg;
509 while (argp)
511 count += split(macro(argp->argval), 1);
512 argp = argp->argnxt;
515 return (count);
518 static int
519 split(s) /* blank interpretation routine */
520 unsigned char *s;
522 unsigned char *argp;
523 int c;
524 int count = 0;
525 for (;;)
527 int length;
528 sigchk();
529 argp = locstak() + BYTESPERWORD;
530 while (c = *s) {
531 wchar_t wc;
532 if ((length = mbtowc(&wc, (char *)s,
533 MB_LEN_MAX)) <= 0) {
534 wc = (unsigned char)*s;
535 length = 1;
538 if (c == '\\') { /* skip over quoted characters */
539 if (argp >= brkend)
540 growstak(argp);
541 *argp++ = c;
542 s++;
543 /* get rest of multibyte character */
544 if ((length = mbtowc(&wc, (char *)s,
545 MB_LEN_MAX)) <= 0) {
546 wc = (unsigned char)*s;
547 length = 1;
549 if (argp >= brkend)
550 growstak(argp);
551 *argp++ = *s++;
552 while (--length > 0) {
553 if (argp >= brkend)
554 growstak(argp);
555 *argp++ = *s++;
557 continue;
560 if (anys(s, ifsnod.namval)) {
561 /* skip to next character position */
562 s += length;
563 break;
566 if (argp >= brkend)
567 growstak(argp);
568 *argp++ = c;
569 s++;
570 while (--length > 0) {
571 if (argp >= brkend)
572 growstak(argp);
573 *argp++ = *s++;
576 if (argp == staktop + BYTESPERWORD)
578 if (c)
580 continue;
582 else
584 return (count);
588 * file name generation
591 argp = endstak(argp);
592 trims(((struct argnod *)argp)->argval);
593 if ((flags & nofngflg) == 0 &&
594 (c = expand(((struct argnod *)argp)->argval, 0)))
595 count += c;
596 else
598 makearg((struct argnod *)argp);
599 count++;
601 gchain = (struct argnod *)((int)gchain | ARGMK);
605 #ifdef ACCT
606 #include <sys/types.h>
607 #include <sys/acct.h>
608 #include <sys/times.h>
610 struct acct sabuf;
611 struct tms buffer;
612 static clock_t before;
613 static int shaccton; /* 0 implies do not write record on exit */
614 /* 1 implies write acct record on exit */
615 static comp_t compress(clock_t);
619 * suspend accounting until turned on by preacct()
621 void
622 suspacct(void)
624 shaccton = 0;
627 void
628 preacct(unsigned char *cmdadr)
630 unsigned char *simple();
632 if (acctnod.namval && *acctnod.namval) {
633 sabuf.ac_btime = time((time_t *)0);
634 before = times(&buffer);
635 sabuf.ac_uid = getuid();
636 sabuf.ac_gid = getgid();
637 movstrn(simple(cmdadr), sabuf.ac_comm, sizeof (sabuf.ac_comm));
638 shaccton = 1;
642 void
643 doacct(void)
645 int fd;
646 clock_t after;
648 if (shaccton) {
649 after = times(&buffer);
650 sabuf.ac_utime = compress(buffer.tms_utime + buffer.tms_cutime);
651 sabuf.ac_stime = compress(buffer.tms_stime + buffer.tms_cstime);
652 sabuf.ac_etime = compress(after - before);
654 if ((fd = open((char *)acctnod.namval,
655 O_WRONLY | O_APPEND | O_CREAT, 0666)) != -1) {
656 write(fd, &sabuf, sizeof (sabuf));
657 close(fd);
663 * Produce a pseudo-floating point representation
664 * with 3 bits base-8 exponent, 13 bits fraction
667 static comp_t
668 compress(clock_t t)
670 int exp = 0;
671 int rund = 0;
673 while (t >= 8192) {
674 exp++;
675 rund = t & 04;
676 t >>= 3;
679 if (rund) {
680 t++;
681 if (t >= 8192) {
682 t >>= 3;
683 exp++;
686 return ((exp << 13) + t);
688 #endif