10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52256Sna195498 * Common Development and Distribution License (the "License").
62256Sna195498 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
212256Sna195498
220Sstevel@tonic-gate /*
23*12273SCasper.Dik@Sun.COM * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
270Sstevel@tonic-gate /* All Rights Reserved */
280Sstevel@tonic-gate
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate * UNIX shell
310Sstevel@tonic-gate */
320Sstevel@tonic-gate
330Sstevel@tonic-gate #include "defs.h"
340Sstevel@tonic-gate #include "sym.h"
350Sstevel@tonic-gate #include "timeout.h"
36527Schin #include <stdio.h>
370Sstevel@tonic-gate #include <sys/types.h>
380Sstevel@tonic-gate #include <sys/stat.h>
390Sstevel@tonic-gate #include <sys/wait.h>
400Sstevel@tonic-gate #include "dup.h"
410Sstevel@tonic-gate
420Sstevel@tonic-gate #ifdef RES
430Sstevel@tonic-gate #include <sgtty.h>
440Sstevel@tonic-gate #endif
450Sstevel@tonic-gate
460Sstevel@tonic-gate pid_t mypid, mypgid, mysid;
470Sstevel@tonic-gate
480Sstevel@tonic-gate static BOOL beenhere = FALSE;
49527Schin unsigned char tmpout[TMPOUTSZ];
500Sstevel@tonic-gate struct fileblk stdfile;
510Sstevel@tonic-gate struct fileblk *standin = &stdfile;
520Sstevel@tonic-gate int mailchk = 0;
530Sstevel@tonic-gate
540Sstevel@tonic-gate static unsigned char *mailp;
550Sstevel@tonic-gate static long *mod_time = 0;
560Sstevel@tonic-gate static BOOL login_shell = FALSE;
570Sstevel@tonic-gate
580Sstevel@tonic-gate #if vax
590Sstevel@tonic-gate char **execargs = (char **)(0x7ffffffc);
600Sstevel@tonic-gate #endif
610Sstevel@tonic-gate
620Sstevel@tonic-gate #if pdp11
630Sstevel@tonic-gate char **execargs = (char **)(-2);
640Sstevel@tonic-gate #endif
650Sstevel@tonic-gate
660Sstevel@tonic-gate
67527Schin static void exfile();
680Sstevel@tonic-gate extern unsigned char *simple();
69527Schin static void Ldup(int, int);
70527Schin void settmp(void);
71527Schin void chkmail(void);
72527Schin void setmail(unsigned char *);
730Sstevel@tonic-gate
74527Schin int
main(int c,char * v[],char * e[])75527Schin main(int c, char *v[], char *e[])
760Sstevel@tonic-gate {
77527Schin int rflag = ttyflg;
780Sstevel@tonic-gate int rsflag = 1; /* local restricted flag */
79527Schin unsigned char *flagc = flagadr;
800Sstevel@tonic-gate struct namnod *n;
810Sstevel@tonic-gate
820Sstevel@tonic-gate mypid = getpid();
830Sstevel@tonic-gate mypgid = getpgid(mypid);
840Sstevel@tonic-gate mysid = getsid(mypid);
850Sstevel@tonic-gate
860Sstevel@tonic-gate /*
870Sstevel@tonic-gate * Do locale processing only if /usr is mounted.
880Sstevel@tonic-gate */
890Sstevel@tonic-gate localedir_exists = (access(localedir, F_OK) == 0);
900Sstevel@tonic-gate
910Sstevel@tonic-gate /*
920Sstevel@tonic-gate * initialize storage allocation
930Sstevel@tonic-gate */
940Sstevel@tonic-gate
950Sstevel@tonic-gate if (stakbot == 0) {
960Sstevel@tonic-gate addblok((unsigned)0);
970Sstevel@tonic-gate }
980Sstevel@tonic-gate
990Sstevel@tonic-gate /*
1000Sstevel@tonic-gate * If the first character of the last path element of v[0] is "-"
1010Sstevel@tonic-gate * (ex. -sh, or /bin/-sh), this is a login shell
1020Sstevel@tonic-gate */
1030Sstevel@tonic-gate if (*simple(v[0]) == '-') {
1040Sstevel@tonic-gate signal(SIGXCPU, SIG_DFL);
1050Sstevel@tonic-gate signal(SIGXFSZ, SIG_DFL);
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate /*
1080Sstevel@tonic-gate * As the previous comment states, this is a login shell.
1090Sstevel@tonic-gate * Therefore, we set the login_shell flag to explicitly
1100Sstevel@tonic-gate * indicate this condition.
1110Sstevel@tonic-gate */
1120Sstevel@tonic-gate login_shell = TRUE;
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate stdsigs();
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate /*
1180Sstevel@tonic-gate * set names from userenv
1190Sstevel@tonic-gate */
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate setup_env();
1220Sstevel@tonic-gate
1230Sstevel@tonic-gate /*
1240Sstevel@tonic-gate * LC_MESSAGES is set here so that early error messages will
1250Sstevel@tonic-gate * come out in the right style.
1260Sstevel@tonic-gate * Note that LC_CTYPE is done later on and is *not*
1270Sstevel@tonic-gate * taken from the previous environ
1280Sstevel@tonic-gate */
1290Sstevel@tonic-gate
1300Sstevel@tonic-gate /*
1310Sstevel@tonic-gate * Do locale processing only if /usr is mounted.
1320Sstevel@tonic-gate */
1330Sstevel@tonic-gate if (localedir_exists)
1340Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
1350Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
1360Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
1370Sstevel@tonic-gate #endif
1380Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate /*
1410Sstevel@tonic-gate * 'rsflag' is zero if SHELL variable is
1420Sstevel@tonic-gate * set in environment and
1430Sstevel@tonic-gate * the simple file part of the value.
1440Sstevel@tonic-gate * is rsh
1450Sstevel@tonic-gate */
146528Schin if (n = findnam("SHELL")) {
1470Sstevel@tonic-gate if (eq("rsh", simple(n->namval)))
1480Sstevel@tonic-gate rsflag = 0;
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate /*
1520Sstevel@tonic-gate * a shell is also restricted if the simple name of argv(0) is
1530Sstevel@tonic-gate * rsh or -rsh in its simple name
1540Sstevel@tonic-gate */
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate #ifndef RES
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate if (c > 0 && (eq("rsh", simple(*v)) || eq("-rsh", simple(*v))))
1590Sstevel@tonic-gate rflag = 0;
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate #endif
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate if (eq("jsh", simple(*v)) || eq("-jsh", simple(*v)))
1640Sstevel@tonic-gate flags |= monitorflg;
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate hcreate();
1670Sstevel@tonic-gate set_dotpath();
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate /*
1710Sstevel@tonic-gate * look for options
1720Sstevel@tonic-gate * dolc is $#
1730Sstevel@tonic-gate */
1740Sstevel@tonic-gate dolc = options(c, v);
1750Sstevel@tonic-gate
176528Schin if (dolc < 2) {
1770Sstevel@tonic-gate flags |= stdflg;
1780Sstevel@tonic-gate {
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate while (*flagc)
1810Sstevel@tonic-gate flagc++;
1820Sstevel@tonic-gate *flagc++ = STDFLG;
1830Sstevel@tonic-gate *flagc = 0;
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate if ((flags & stdflg) == 0)
1870Sstevel@tonic-gate dolc--;
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate if ((flags & privflg) == 0) {
190527Schin uid_t euid;
191527Schin gid_t egid;
192527Schin uid_t ruid;
193527Schin gid_t rgid;
1940Sstevel@tonic-gate
1950Sstevel@tonic-gate /*
1960Sstevel@tonic-gate * Determine all of the user's id #'s for this process and
1970Sstevel@tonic-gate * then decide if this shell is being entered as a result
1980Sstevel@tonic-gate * of a fork/exec.
1990Sstevel@tonic-gate * If the effective uid/gid do NOT match and the euid/egid
2000Sstevel@tonic-gate * is < 100 and the egid is NOT 1, reset the uid and gid to
2010Sstevel@tonic-gate * the user originally calling this process.
2020Sstevel@tonic-gate */
2030Sstevel@tonic-gate euid = geteuid();
2040Sstevel@tonic-gate ruid = getuid();
2050Sstevel@tonic-gate egid = getegid();
2060Sstevel@tonic-gate rgid = getgid();
2070Sstevel@tonic-gate if ((euid != ruid) && (euid < 100))
2080Sstevel@tonic-gate setuid(ruid); /* reset the uid to the orig user */
2090Sstevel@tonic-gate if ((egid != rgid) && ((egid < 100) && (egid != 1)))
2100Sstevel@tonic-gate setgid(rgid); /* reset the gid to the orig user */
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate dolv = (unsigned char **)v + c - dolc;
2140Sstevel@tonic-gate dolc--;
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate /*
2170Sstevel@tonic-gate * return here for shell file execution
2180Sstevel@tonic-gate * but not for parenthesis subshells
2190Sstevel@tonic-gate */
2200Sstevel@tonic-gate if (setjmp(subshell)) {
2210Sstevel@tonic-gate freejobs();
2220Sstevel@tonic-gate flags |= subsh;
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate /*
2260Sstevel@tonic-gate * number of positional parameters
2270Sstevel@tonic-gate */
2280Sstevel@tonic-gate replace(&cmdadr, dolv[0]); /* cmdadr is $0 */
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate /*
2310Sstevel@tonic-gate * set pidname '$$'
2320Sstevel@tonic-gate */
2330Sstevel@tonic-gate assnum(&pidadr, (long)mypid);
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate /*
2360Sstevel@tonic-gate * set up temp file names
2370Sstevel@tonic-gate */
2380Sstevel@tonic-gate settmp();
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate /*
2410Sstevel@tonic-gate * default internal field separators
2420Sstevel@tonic-gate * Do not allow importing of IFS from parent shell.
2430Sstevel@tonic-gate * setup_env() may have set anything from parent shell to IFS.
2440Sstevel@tonic-gate * Always set the default ifs to IFS.
2450Sstevel@tonic-gate */
246527Schin assign(&ifsnod, (unsigned char *)sptbnl);
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate dfault(&mchknod, MAILCHECK);
2490Sstevel@tonic-gate mailchk = stoi(mchknod.namval);
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate /* initialize OPTIND for getopt */
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate n = lookup("OPTIND");
254527Schin assign(n, (unsigned char *)"1");
2550Sstevel@tonic-gate /*
2560Sstevel@tonic-gate * make sure that option parsing starts
2570Sstevel@tonic-gate * at first character
2580Sstevel@tonic-gate */
2590Sstevel@tonic-gate _sp = 1;
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate if ((beenhere++) == FALSE) /* ? profile */
2620Sstevel@tonic-gate {
2630Sstevel@tonic-gate if ((login_shell == TRUE) && (flags & privflg) == 0) {
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate /* system profile */
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate #ifndef RES
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate if ((input = pathopen(nullstr, sysprofile)) >= 0)
2700Sstevel@tonic-gate exfile(rflag); /* file exists */
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate #endif
2730Sstevel@tonic-gate /* user profile */
2740Sstevel@tonic-gate
275528Schin if ((input = pathopen(homenod.namval, profile)) >= 0) {
2760Sstevel@tonic-gate exfile(rflag);
2770Sstevel@tonic-gate flags &= ~ttyflg;
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate if (rsflag == 0 || rflag == 0) {
2810Sstevel@tonic-gate if ((flags & rshflg) == 0) {
2820Sstevel@tonic-gate while (*flagc)
2830Sstevel@tonic-gate flagc++;
2840Sstevel@tonic-gate *flagc++ = 'r';
2850Sstevel@tonic-gate *flagc = '\0';
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate flags |= rshflg;
2880Sstevel@tonic-gate }
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate /*
2910Sstevel@tonic-gate * open input file if specified
2920Sstevel@tonic-gate */
293528Schin if (comdiv) {
2940Sstevel@tonic-gate estabf(comdiv);
2950Sstevel@tonic-gate input = -1;
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate else
2980Sstevel@tonic-gate {
2990Sstevel@tonic-gate if (flags & stdflg) {
3000Sstevel@tonic-gate input = 0;
3010Sstevel@tonic-gate } else {
3020Sstevel@tonic-gate /*
3030Sstevel@tonic-gate * If the command file specified by 'cmdadr'
3040Sstevel@tonic-gate * doesn't exist, chkopen() will fail calling
3050Sstevel@tonic-gate * exitsh(). If this is a login shell and
3060Sstevel@tonic-gate * the $HOME/.profile file does not exist, the
3070Sstevel@tonic-gate * above statement "flags &= ~ttyflg" does not
3080Sstevel@tonic-gate * get executed and this makes exitsh() call
3090Sstevel@tonic-gate * longjmp() instead of exiting. longjmp() will
3100Sstevel@tonic-gate * return to the location specified by the last
3110Sstevel@tonic-gate * active jmpbuffer, which is the one set up in
3120Sstevel@tonic-gate * the function exfile() called after the system
3130Sstevel@tonic-gate * profile file is executed (see lines above).
3140Sstevel@tonic-gate * This would cause an infinite loop, because
3150Sstevel@tonic-gate * chkopen() will continue to fail and exitsh()
3160Sstevel@tonic-gate * to call longjmp(). To make exitsh() exit instead
3170Sstevel@tonic-gate * of calling longjmp(), we then set the flag forcexit
3180Sstevel@tonic-gate * at this stage.
3190Sstevel@tonic-gate */
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate flags |= forcexit;
3220Sstevel@tonic-gate input = chkopen(cmdadr, 0);
3230Sstevel@tonic-gate flags &= ~forcexit;
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate #ifdef ACCT
3270Sstevel@tonic-gate if (input != 0)
3280Sstevel@tonic-gate preacct(cmdadr);
3290Sstevel@tonic-gate #endif
3300Sstevel@tonic-gate comdiv--;
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate #ifdef pdp11
3340Sstevel@tonic-gate else
3350Sstevel@tonic-gate *execargs = (char *)dolv; /* for `ps' cmd */
3360Sstevel@tonic-gate #endif
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate
3390Sstevel@tonic-gate exfile(0);
3400Sstevel@tonic-gate done(0);
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate
343527Schin static void
exfile(int prof)344527Schin exfile(int prof)
3450Sstevel@tonic-gate {
3460Sstevel@tonic-gate time_t mailtime = 0; /* Must not be a register variable */
3470Sstevel@tonic-gate time_t curtime = 0;
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate /*
3500Sstevel@tonic-gate * move input
3510Sstevel@tonic-gate */
352528Schin if (input > 0) {
3530Sstevel@tonic-gate Ldup(input, INIO);
3540Sstevel@tonic-gate input = INIO;
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate setmode(prof);
3590Sstevel@tonic-gate
360528Schin if (setjmp(errshell) && prof) {
3610Sstevel@tonic-gate close(input);
3620Sstevel@tonic-gate (void) endjobs(0);
3630Sstevel@tonic-gate return;
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate /*
3660Sstevel@tonic-gate * error return here
3670Sstevel@tonic-gate */
3680Sstevel@tonic-gate
3690Sstevel@tonic-gate loopcnt = peekc = peekn = 0;
3700Sstevel@tonic-gate fndef = 0;
3710Sstevel@tonic-gate nohash = 0;
3720Sstevel@tonic-gate iopend = 0;
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate if (input >= 0)
3750Sstevel@tonic-gate initf(input);
3760Sstevel@tonic-gate /*
3770Sstevel@tonic-gate * command loop
3780Sstevel@tonic-gate */
379528Schin for (;;) {
3800Sstevel@tonic-gate tdystak(0);
3810Sstevel@tonic-gate stakchk(); /* may reduce sbrk */
3820Sstevel@tonic-gate exitset();
3830Sstevel@tonic-gate
384528Schin if ((flags & prompt) && standin->fstak == 0 && !eof) {
3850Sstevel@tonic-gate
386528Schin if (mailp) {
3870Sstevel@tonic-gate time(&curtime);
3880Sstevel@tonic-gate
389528Schin if ((curtime - mailtime) >= mailchk) {
3900Sstevel@tonic-gate chkmail();
3910Sstevel@tonic-gate mailtime = curtime;
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate /* necessary to print jobs in a timely manner */
3960Sstevel@tonic-gate if (trapnote & TRAPSET)
3970Sstevel@tonic-gate chktrap();
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate prs(ps1nod.namval);
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate #ifdef TIME_OUT
4020Sstevel@tonic-gate alarm(TIMEOUT);
4030Sstevel@tonic-gate #endif
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate trapnote = 0;
4080Sstevel@tonic-gate peekc = readwc();
4090Sstevel@tonic-gate if (eof) {
4100Sstevel@tonic-gate if (endjobs(JOB_STOPPED))
4110Sstevel@tonic-gate return;
4120Sstevel@tonic-gate eof = 0;
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate
4150Sstevel@tonic-gate #ifdef TIME_OUT
4160Sstevel@tonic-gate alarm(0);
4170Sstevel@tonic-gate #endif
4180Sstevel@tonic-gate
4190Sstevel@tonic-gate {
420527Schin struct trenod *t;
4210Sstevel@tonic-gate t = cmd(NL, MTFLG);
4220Sstevel@tonic-gate if (t == NULL && flags & ttyflg)
4230Sstevel@tonic-gate freejobs();
4240Sstevel@tonic-gate else
4250Sstevel@tonic-gate execute(t, 0, eflag);
4260Sstevel@tonic-gate }
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate eof |= (flags & oneflg);
4290Sstevel@tonic-gate
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate
433527Schin void
chkpr(void)434527Schin chkpr(void)
4350Sstevel@tonic-gate {
4360Sstevel@tonic-gate if ((flags & prompt) && standin->fstak == 0)
4370Sstevel@tonic-gate prs(ps2nod.namval);
4380Sstevel@tonic-gate }
4390Sstevel@tonic-gate
440527Schin void
settmp(void)441527Schin settmp(void)
4420Sstevel@tonic-gate {
443527Schin int len;
4440Sstevel@tonic-gate serial = 0;
445527Schin if ((len = snprintf((char *)tmpout, TMPOUTSZ, "/tmp/sh%u", mypid)) >=
446527Schin TMPOUTSZ) {
447527Schin /*
448527Schin * TMPOUTSZ should be big enough, but if it isn't,
449527Schin * we'll at least try to create tmp files with
450527Schin * a truncated tmpfile name at tmpout.
451527Schin */
452527Schin tmpout_offset = TMPOUTSZ - 1;
453527Schin } else {
454527Schin tmpout_offset = len;
455527Schin }
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate
458527Schin static void
Ldup(int fa,int fb)459527Schin Ldup(int fa, int fb)
4600Sstevel@tonic-gate {
4610Sstevel@tonic-gate #ifdef RES
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate dup(fa | DUPFLG, fb);
4640Sstevel@tonic-gate close(fa);
4650Sstevel@tonic-gate ioctl(fb, FIOCLEX, 0);
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate #else
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate if (fa >= 0) {
470528Schin if (fa != fb) {
4710Sstevel@tonic-gate close(fb);
4720Sstevel@tonic-gate fcntl(fa, 0, fb); /* normal dup */
4730Sstevel@tonic-gate close(fa);
4740Sstevel@tonic-gate }
4750Sstevel@tonic-gate fcntl(fb, 2, 1); /* autoclose for fb */
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate #endif
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate
481527Schin void
chkmail(void)482527Schin chkmail(void)
4830Sstevel@tonic-gate {
484527Schin unsigned char *s = mailp;
485527Schin unsigned char *save;
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate long *ptr = mod_time;
4880Sstevel@tonic-gate unsigned char *start;
4890Sstevel@tonic-gate BOOL flg;
4900Sstevel@tonic-gate struct stat statb;
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate while (*s) {
4930Sstevel@tonic-gate start = s;
4940Sstevel@tonic-gate save = 0;
4950Sstevel@tonic-gate flg = 0;
4960Sstevel@tonic-gate
4970Sstevel@tonic-gate while (*s) {
4980Sstevel@tonic-gate if (*s != COLON) {
4990Sstevel@tonic-gate if (*s == '%' && save == 0)
5000Sstevel@tonic-gate save = s;
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate s++;
5030Sstevel@tonic-gate } else {
5040Sstevel@tonic-gate flg = 1;
5050Sstevel@tonic-gate *s = 0;
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate
5090Sstevel@tonic-gate if (save)
5100Sstevel@tonic-gate *save = 0;
5110Sstevel@tonic-gate
5120Sstevel@tonic-gate if (*start && stat((const char *)start, &statb) >= 0) {
5130Sstevel@tonic-gate if (statb.st_size && *ptr &&
5140Sstevel@tonic-gate statb.st_mtime != *ptr) {
5150Sstevel@tonic-gate if (save) {
5160Sstevel@tonic-gate prs(save+1);
5170Sstevel@tonic-gate newline();
5180Sstevel@tonic-gate }
5190Sstevel@tonic-gate else
5202256Sna195498 prs(_gettext(mailmsg));
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate *ptr = statb.st_mtime;
5230Sstevel@tonic-gate } else if (*ptr == 0)
5240Sstevel@tonic-gate *ptr = 1;
5250Sstevel@tonic-gate
5260Sstevel@tonic-gate if (save)
5270Sstevel@tonic-gate *save = '%';
5280Sstevel@tonic-gate
5290Sstevel@tonic-gate if (flg)
5300Sstevel@tonic-gate *s++ = COLON;
5310Sstevel@tonic-gate
5320Sstevel@tonic-gate ptr++;
5330Sstevel@tonic-gate }
5340Sstevel@tonic-gate }
5350Sstevel@tonic-gate
536527Schin void
setmail(unsigned char * mailpath)537527Schin setmail(unsigned char *mailpath)
5380Sstevel@tonic-gate {
539527Schin unsigned char *s = mailpath;
540527Schin int cnt = 1;
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate long *ptr;
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate free(mod_time);
545528Schin if (mailp = mailpath) {
546528Schin while (*s) {
5470Sstevel@tonic-gate if (*s == COLON)
5480Sstevel@tonic-gate cnt += 1;
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate s++;
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate
5530Sstevel@tonic-gate ptr = mod_time = (long *)alloc(sizeof (long) * cnt);
5540Sstevel@tonic-gate
555528Schin while (cnt) {
5560Sstevel@tonic-gate *ptr = 0;
5570Sstevel@tonic-gate ptr++;
5580Sstevel@tonic-gate cnt--;
5590Sstevel@tonic-gate }
5600Sstevel@tonic-gate }
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate void
setmode(int prof)564527Schin setmode(int prof)
5650Sstevel@tonic-gate {
5660Sstevel@tonic-gate /*
5670Sstevel@tonic-gate * decide whether interactive
5680Sstevel@tonic-gate */
5690Sstevel@tonic-gate
5700Sstevel@tonic-gate if ((flags & intflg) ||
5710Sstevel@tonic-gate ((flags&oneflg) == 0 &&
5720Sstevel@tonic-gate isatty(output) &&
5730Sstevel@tonic-gate isatty(input)))
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate {
5760Sstevel@tonic-gate dfault(&ps1nod, (geteuid() ? stdprompt : supprompt));
5770Sstevel@tonic-gate dfault(&ps2nod, readmsg);
5780Sstevel@tonic-gate flags |= ttyflg | prompt;
5790Sstevel@tonic-gate if (mailpnod.namflg != N_DEFAULT)
5800Sstevel@tonic-gate setmail(mailpnod.namval);
5810Sstevel@tonic-gate else
5820Sstevel@tonic-gate setmail(mailnod.namval);
5830Sstevel@tonic-gate startjobs();
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate else
5860Sstevel@tonic-gate {
5870Sstevel@tonic-gate flags |= prof;
5880Sstevel@tonic-gate flags &= ~prompt;
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate }
591