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]
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 */
39 static unsigned char *execs();
42 extern void makearg(struct argnod
*);
47 * service routines for `execute'
50 initio(struct ionod
*iop
, int save
)
61 ion
= mactrim(iop
->ioname
);
64 if (*ion
&& (flags
&noexec
) == 0) {
66 fdmap
[topfd
].org_fd
= ioufd
;
67 fdmap
[topfd
++].dup_fd
= savefd(ioufd
);
70 if (iof
& IODOC_SUBST
) {
73 subst(chkopen(ion
, 0), (fd
= tmpfil(&tb
)));
76 * pushed in tmpfil() --
77 * bug fix for problem with
82 fd
= chkopen(tmpout
, 0);
83 unlink((const char *)tmpout
);
84 } else if (iof
& IOMOV
) {
88 } else if ((fd
= stoi(ion
)) >= USERIO
) {
93 } else if (((iof
& IOPUT
) == 0) && ((iof
& IORDW
) == 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
);
119 unsigned char *sname
;
124 while (*sname
++ != '/')
135 unsigned char *path
, *newpath
;
141 failed(s
, restricted
);
143 return ((unsigned char *)nullstr
);
144 } else if ((path
= pathnod
.namval
) == 0)
145 return ((unsigned char *)defpath
);
147 pathlen
= length(path
)-1;
148 /* Add extra ':' if PATH variable ends in ':' */
149 if (pathlen
> 2 && path
[pathlen
- 1] == ':' &&
150 path
[pathlen
- 2] != ':') {
152 (void) memcpystak(newpath
, path
, pathlen
);
153 newpath
[pathlen
] = ':';
154 endstak(newpath
+ pathlen
+ 1);
157 return (cpystak(path
));
162 pathopen(unsigned char *path
, unsigned char *name
)
168 path
= catpath(path
, name
);
169 } while ((f
= open((char *)curstak(), 0)) < 0 && path
);
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
) {
194 path
= (*scanp
? scanp
: 0);
201 while (*argp
++ = *scanp
++)
207 nextpath(unsigned char *path
)
209 unsigned char *scanp
= path
;
211 while (*scanp
&& *scanp
!= COLON
)
217 return (*scanp
? scanp
: 0);
220 static const char *xecmsg
;
221 static unsigned char **xecenv
;
224 execa(unsigned char *at
[], short pos
)
227 unsigned char **t
= at
;
230 if ((flags
& noexec
) == 0) {
233 xecenv
= local_setenv();
239 path
= nextpath(path
);
244 while (path
= execs(path
, t
))
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]);
260 execve((const char *)p
, (char *const *)&t
[0],
261 (char *const *)xecenv
);
264 case ENOEXEC
: /* could be a shell script */
270 clearup(); /* remove open files and for loop junk */
273 input
= chkopen(p
, 0);
276 preacct(p
); /* reset accounting */
284 longjmp(subshell
, 1);
317 trim(unsigned char *at
)
320 unsigned char *current
;
328 while (c
= *current
) {
329 if ((len
= mbtowc(&wc
, (char *)current
,
337 memcpy(last
, current
, len
);
343 /* remove \ and quoted nulls */
347 if ((len
= mbtowc(&wc
, (char *)current
,
353 memcpy(last
, current
, len
);
364 /* Same as trim, but only removes backlashes before slashes */
370 unsigned char *current
;
378 while (c
= *current
) {
379 if ((len
= mbtowc(&wc
, (char *)current
,
387 memcpy(last
, current
, len
);
388 last
+= len
; current
+= len
;
392 /* remove \ and quoted nulls */
394 if (!(c
= *current
)) {
406 if ((len
= mbtowc(&wc
, (char *)current
,
412 memcpy(last
, current
, len
);
413 last
+= len
; current
+= len
;
423 unsigned char *t
= macro(s
);
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
;
442 *--comargn
= argp
->argval
;
447 if (argp
== 0 || Rcheat(argp
) & ARGMK
)
449 gsort(comargn
, comargm
);
452 argp
= (struct argnod
*)(Rcheat(argp
) & ~ARGMK
);
459 unsigned char *from
[], *to
[];
464 if ((n
= to
- from
) <= 1)
466 for (j
= 1; j
<= n
; j
*= 2)
468 for (m
= 2 * j
- 1; m
/= 2; )
471 for (j
= 0; j
< k
; j
++)
473 for (i
= j
; i
>= 0; i
-= m
)
475 unsigned char **fromi
;
478 if (cf(fromi
[m
], fromi
[0]) > 0)
496 * Argument list generation
511 count
+= split(macro(argp
->argval
), 1);
519 split(s
) /* blank interpretation routine */
529 argp
= locstak() + BYTESPERWORD
;
532 if ((length
= mbtowc(&wc
, (char *)s
,
534 wc
= (unsigned char)*s
;
538 if (c
== '\\') { /* skip over quoted characters */
543 /* get rest of multibyte character */
544 if ((length
= mbtowc(&wc
, (char *)s
,
546 wc
= (unsigned char)*s
;
552 while (--length
> 0) {
560 if (anys(s
, ifsnod
.namval
)) {
561 /* skip to next character position */
570 while (--length
> 0) {
576 if (argp
== staktop
+ BYTESPERWORD
)
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)))
598 makearg((struct argnod
*)argp
);
601 gchain
= (struct argnod
*)((int)gchain
| ARGMK
);
606 #include <sys/types.h>
607 #include <sys/acct.h>
608 #include <sys/times.h>
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()
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
));
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
));
663 * Produce a pseudo-floating point representation
664 * with 3 bits base-8 exponent, 13 bits fraction
686 return ((exp
<< 13) + t
);