1
0
Files
irix-657m-src/eoe/cmd/ksh/sh/builtin.c
2022-09-29 17:59:04 +03:00

2897 lines
55 KiB
C

/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)ksh:sh/builtin.c 1.5.5.2"
/*
* builtin routines for the shell
*
* David Korn
* AT&T Bell Laboratories
* Room 3C-526B
* Murray Hill, N. J. 07974
* Tel. x7975
*
*/
#include <errno.h>
#include "defs.h"
#include "history.h"
#include "builtins.h"
#include "jobs.h"
#include "sym.h"
#define NOT_USED(x) (&x,1) /* prevents not used messages */
#ifdef _sys_resource_
# ifndef included_sys_time_
# include <sys/time.h>
# endif
# include <sys/resource.h>/* needed for ulimit */
# define LIM_FSIZE RLIMIT_FSIZE
# define LIM_DATA RLIMIT_DATA
# define LIM_STACK RLIMIT_STACK
# define LIM_CORE RLIMIT_CORE
# define LIM_CPU RLIMIT_CPU
# define INFINITY RLIM64_INFINITY
# ifdef RLIMIT_RSS
# define LIM_MAXRSS RLIMIT_RSS
# endif /* RLIMIT_RSS */
#else
# ifdef VLIMIT
# include <sys/vlimit.h>
# endif /* VLIMIT */
#endif /* _sys_resource_ */
#ifdef UNIVERSE
static int att_univ = -1;
# ifdef _sys_universe_
# include <sys/universe.h>
# define getuniverse(x) (setuniverse(flag=setuniverse(0)),\
(--flag>=0?strncpy(x,univ_name[flag],TMPSIZ):0),\
flag)
# else
# define univ_number(x) (x)
# endif /* _sys_universe_ */
#endif /* UNIVERSE */
#ifdef ECHOPRINT
# undef ECHO_RAW
# undef ECHO_N
#endif /* ECHOPRINT */
#define DOTMAX 32 /* maximum level of . nesting */
#define PHYS_MODE H_FLAG
#define LOG_MODE N_LJUST
/* This module references these external routines */
#ifdef ECHO_RAW
extern char *echo_mode();
#endif /* ECHO_RAW */
extern int gscan_all();
extern char *utos();
extern char *u64tos();
extern void ltou();
static int b_common();
static int b_unall();
static int flagset();
static int sig_number();
static int scanargs();
#ifdef JOBS
static void sig_list();
#endif /* JOBS */
static int argnum;
static int aflag;
static int newflag;
static int echon;
static int scoped;
int b_exec(argn,com)
char **com;
{
st.ioset = 0;
if(*++com)
b_login(argn,com);
return(0);
}
int b_login(argn,com)
char **com;
{
NOT_USED(argn);
if(is_option(RSHFLG))
sh_cfail(gettxt(_SGI_DMMX_e_restricted,e_restricted));
else
{
#ifdef JOBS
if(job_close() < 0)
return(1);
#endif /* JOBS */
/* force bad exec to terminate shell */
st.states &= ~(PROFILE|PROMPT|BUILTIN|LASTPIPE);
sig_reset(0);
hist_close();
sh_freeup();
if(st.states&RM_TMP)
rm_files(io_tmpname);
path_exec(com,(struct argnod*)0);
sh_done(0);
}
return(1);
}
int b_pwd(argn,com)
char **com;
{
register int flag=0;
register char *a1 = com[1];
NOT_USED(argn);
#if defined(LSTAT) || defined(FS_3D)
while(a1 && *a1=='-'&&
(flag = flagset(a1,~(PHYS_MODE|LOG_MODE))))
{
if(flag&LOG_MODE)
flag = 0;
com++;
a1 = com[1];
}
#endif /* LSTAT||FS_3D */
if(*(a1 = path_pwd(0))!='/')
sh_cfail(gettxt(_SGI_DMMX_e_pwd,e_pwd));
#if defined(LSTAT) || defined(FS_3D)
if(flag)
{
# ifdef FS_3D
if(umask(flag=umask(0)),flag&01000)
mount(".",a1=stakalloc(PATH_MAX),10|(PATH_MAX)<<4);
# else
a1 = stakcopy(a1);
# endif /* FS_3D */
#ifdef LSTAT
path_physical(a1);
#endif /* LSTAT */
}
#endif /* LSTAT||FS_3D */
p_setout(st.standout);
p_str(a1,NL);
return(0);
}
#ifndef ECHOPRINT
int b_echo(argn,com)
int argn;
char **com;
{
register int r;
char *save = *com;
# ifdef ECHO_RAW
/* This mess is because /bin/echo on BSD is archaic */
# ifdef UNIVERSE
if(att_univ < 0)
{
int flag;
char universe[TMPSIZ];
if(getuniverse(universe) >= 0)
att_univ = (strcmp(universe,"att")==0);
}
if(att_univ>0)
*com = (char*)e_minus;
else
# endif /* UNIVERSE */
*com = echo_mode();
r = b_print(argn+1,com-1);
*com = save;
return(r);
# else
# ifdef ECHO_N
/* same as echo except -n special */
{
struct namnod *np;
np = nam_search("_XPG",sh.var_tree,N_NULL);
if(!np || np && *(np->value.namval.cp) == '0') {
echon = 1;
return(b_print(argn,com));
} else {
*com = (char*)e_minus;
r = b_print(argn+1,com-1);
*com = save;
return(r);
}
}
# else
/* equivalent to print - */
*com = (char*)e_minus;
r = b_print(argn+1,com-1);
*com = save;
return(r);
# endif /* ECHO_N */
# endif /* ECHO_RAW */
}
#endif /* ECHOPRINT */
int b_print(argn,com)
int argn;
char **com;
{
register int fd;
register char *a1 = com[1];
register char *cmd = com[0];
register int flag = 0;
register int r=0;
const char *msg = gettxt(_SGI_DMMX_e_file,e_file);
int raw = 0;
NOT_USED(argn);
argnum = 1;
while(a1 && *a1 == '-')
{
int c = *(a1+1);
com++;
/* echon set when only -n is legal */
if(echon)
{
if(strcmp(a1,"-n")==0)
c = 0;
else
{
com--;
break;
}
}
newflag = flagset(a1,~(N_FLAG|R_FLAG|P_FLAG|U_FLAG|S_FLAG|N_RJUST));
flag |= newflag;
/* handle the -R flag for BSD style echo */
if(flag&N_RJUST)
echon = 1;
if(c==0 || newflag==0)
break;
a1 = com[1];
}
echon = 0;
argnum %= 10;
if(flag&(R_FLAG|N_RJUST))
raw = 1;
if(flag&S_FLAG)
{
/* print to history file */
if(!hist_open())
sh_cfail(gettxt(_SGI_DMMX_e_history,e_history));
fd = hist_ptr->fixfd;
st.states |= FIXFLG;
goto skip;
}
else if(flag&P_FLAG)
{
fd = COTPIPE;
msg = gettxt(_SGI_DMMX_e_query,e_query);
}
else if(flag&U_FLAG)
fd = argnum;
else
fd = st.standout;
if(r = !fiswrite(fd))
{
if(fd==st.standout)
return(r);
sh_cfail(msg);
}
skip:
p_setout(fd);
if(echo_list(raw,com+1))
{
if(is_option(WORDEXP))
p_char(0);
else if((flag&N_FLAG)==0)
newline();
}
if(flag&S_FLAG)
hist_flush();
return(r);
}
int b_let(argn,com)
register int argn;
char **com;
{
register int r;
if(argn < 2)
sh_cfail(gettxt(_SGI_DMMX_e_nargs,e_nargs));
while(--argn)
r = !sh_arith(*++com);
return(r);
}
int b_command(argn,com,execflg)
register char **com;
{
register const char *a1;
register struct namnod *np;
register int c,vflg,Vflg,pflg;
register int spc_exec = 0;
register int cmdoff;
extern char *optarg;
struct sh_optget Optget;
vflg = Vflg = pflg = 0;
if(argn == 1)
sh_fail(*com,gettxt(_SGI_DMMX_e_nargs,e_nargs),ERROR);
/* NOTREACHED */
sv_optget(&Optget);
while ((c = optget(argn, com, "vVp")) != EOF) {
switch (c) {
case 'v':
if(Vflg || pflg) {
rs_optget(&Optget);
sh_fail(*com,gettxt(_SGI_DMMX_e_combo,e_combo),ERROR);
/* NOTREACHED */
}
++vflg;
break;
case 'V':
if(vflg || pflg) {
rs_optget(&Optget);
sh_fail(*com,gettxt(_SGI_DMMX_e_combo,e_combo),ERROR);
/* NOTREACHED */
}
++Vflg;
break;
case 'p':
if(vflg || Vflg) {
rs_optget(&Optget);
sh_fail(*com,gettxt(_SGI_DMMX_e_combo,e_combo),ERROR);
/* NOTREACHED */
}
++pflg;
break;
case '?':
rs_optget(&Optget);
sh_fail(*com,gettxt(_SGI_DMMX_e_option,e_option),ERROR);
/* NOTREACHED */
}
}
if(((vflg || Vflg) && (argn-opt_index) != 1) || (pflg && (argn-opt_index) < 1)) {
rs_optget(&Optget);
sh_fail(*com,gettxt(_SGI_DMMX_e_nargs,e_nargs),ERROR);
/* NOTREACHED */
}
cmdoff = opt_index;
rs_optget(&Optget);
if(!vflg && !Vflg) {
struct fileblk fb;
int i,flags;
union anynode *t;
char inbuf[IOBSIZE+1];
char build[IOBSIZE+1];
char sav_path[PATH_MAX+1];
struct ionod *saviotemp = st.iotemp;
struct slnod *saveslp = st.staklist;
struct namnod* np;
if(pflg)
{
if(nam_fstrval(PATHNOD)) {
strcpy(sav_path,nam_fstrval(PATHNOD));
nam_fputval(PATHNOD,(char *)e_defpath);
}
else pflg=0;
}
io_push(&fb);
/*
* Reconstruct input line from **com args skipping the
* command "command" and any options.
* Surround each **com arg with single quotes to prevent
* further expansion and seperate with spaces.
*/
inbuf[0] = 0;
strcpy(inbuf,com[cmdoff]); /* Command name */
for(i=(cmdoff+1); com[i]; ++i) {
sprintf(build," '%s' ",com[i]);
strcat(inbuf,build);
}
io_sopen(inbuf);
st.exec_flag++;
t = sh_parse(NL,NLFLG|MTFLG);
st.exec_flag--;
p_setout(ERRIO);
io_pop(0);
np = nam_search(path_basename(com[cmdoff]),sh.fun_tree,0);
if(np && nam_istype(np,BLT_SPC))
st.states |= CMD_SPC;
flags = st.states&(ERRFLG|MONITOR);
if(execflg)
flags |= 1;
st.states |= NOFUNC;
sh_exec(t,flags);
if(np && nam_istype(np,BLT_SPC))
st.states &= ~CMD_SPC;
st.states &= ~NOFUNC;
sh_freeup();
st.iotemp = saviotemp;
st.staklist = saveslp;
if(pflg)
nam_fputval(PATHNOD,sav_path);
return(sh.exitval);
}
p_setout(st.standout);
/* Check for special builtin execables */
np = nam_search(path_basename(com[cmdoff]),sh.fun_tree,0);
if(np && nam_istype(np,BLT_EXEC)==BLT_EXEC) {
++spc_exec;
strcpy(com[cmdoff],path_basename(com[cmdoff]));
}
/* Utilities, regular builtin utilities, command names with slash */
/* and implementation provided functions */
if(!spc_exec && path_search(com[cmdoff],2)==0) {
a1 = sh.lastpath;
sh.lastpath = 0;
if(a1) {
p_str(a1,0);
if(Vflg)
p_str(gettxt(_SGI_DMMX_is_pathfound,is_pathfound),0);
p_char(NL);
return(0);
}
}
/* built-ins and functions */
if(np=nam_search(com[cmdoff],sh.fun_tree,N_NULL)) {
if(is_abuiltin(np) && nam_istype(np,BLT_SPC)==BLT_SPC) {
p_str(com[cmdoff],0);
if(Vflg)
p_str(gettxt(_SGI_DMMX_is_spc_builtin,is_spc_builtin),0);
}
else if(is_abuiltin(np)) {
p_str(com[cmdoff],0);
if(Vflg)
p_str(gettxt(_SGI_DMMX_is_builtin,is_builtin),0);
}
else if(nam_istype(np,N_EXPORT)) {
p_str(com[cmdoff],0);
if(Vflg)
p_str(gettxt(_SGI_DMMX_is_xfunction,is_xfunction),0);
} else {
p_str(com[cmdoff],0);
if(Vflg)
p_str(gettxt(_SGI_DMMX_is_function,is_function),0);
}
p_char(NL);
return(0);
}
/* reserved words */
if(sh_lookup(com[cmdoff],tab_reserved)) {
p_str(com[cmdoff],0);
if(Vflg)
p_str(gettxt(_SGI_DMMX_is_reserved,is_reserved),0);
p_char(NL);
return(0);
}
/* aliases */
if(np=nam_search(com[cmdoff],sh.alias_tree,N_NULL)) {
if(Vflg)
p_str(gettxt(_SGI_DMMX_e_aliasspc,e_aliasspc),0);
env_prnamval(np,0);
return(0);
}
if(vflg)
return(127);
p_setout(ERRIO);
p_str(com[cmdoff],0);
p_str(gettxt(_SGI_DMMX_e_found,e_found),NL);
return(1);
}
/*
* The following few builtins are provided to set,print,
* and test attributes and variables for shell variables,
* aliases, and functions.
* In addition, typeset -f can be used to test whether a
* function has been defined or to list all defined functions
* Note readonly is same as typeset -r.
* Note export is same as typeset -x.
*/
int b_readonly(argn,com)
register char **com;
{
register int pflag=0;
register int c;
struct sh_optget Optget;
aflag = '-';
argnum = scoped = 0;
if(argn > 1 && *com[1] == '-')
{
sv_optget(&Optget);
while ((c = optget(argn, com, "p")) != EOF)
{
switch (c)
{
case 'p':
++pflag;
break;
case '?':
rs_optget(&Optget);
sh_cfail(gettxt(_SGI_DMMX_e_option,e_option));
/* NOTREACHED */
}
}
if(pflag && argn > opt_index)
{
rs_optget(&Optget);
sh_cfail(gettxt(_SGI_DMMX_e_nargs,e_nargs));
/* NOTREACHED */
}
com += (opt_index-1);
rs_optget(&Optget);
}
return(b_common(com,R_FLAG,sh.var_tree,(pflag?P_FLAG:0)));
}
int b_export(argn,com)
register char **com;
{
register int pflag=0;
register int c;
struct sh_optget Optget;
aflag = '-';
argnum = scoped = 0;
if(argn > 1 && *com[1] == '-')
{
sv_optget(&Optget);
while ((c = optget(argn, com, "p")) != EOF)
{
switch (c)
{
case 'p':
++pflag;
break;
case '?':
rs_optget(&Optget);
sh_cfail(gettxt(_SGI_DMMX_e_option,e_option));
/* NOTREACHED */
}
}
if(pflag && argn > opt_index)
{
rs_optget(&Optget);
sh_cfail(gettxt(_SGI_DMMX_e_nargs,e_nargs));
/* NOTREACHED */
}
com += (opt_index-1);
rs_optget(&Optget);
}
return(b_common(com,X_FLAG,sh.var_tree,(pflag?P_FLAG:0)));
}
int b_type(argn,com)
register char **com;
{
NOT_USED(argn);
if(com[1] == 0)
sh_cfail(gettxt(_SGI_DMMX_e_nargs,e_nargs));
if(strcmp(com[1],"--")==0)
++com;
p_setout(st.standout);
return(sh_whence(com,V_FLAG));
}
int b_hash(argn,com)
register char **com;
{
int c;
struct sh_optget Optget;
sv_optget(&Optget);
scoped = 0;
if(com[1] && *com[1] == '-')
{
while ((c = optget(argn, com, "r")) != EOF)
{
switch (c)
{
case 'r':
gscan_all(nam_free,sh.track_tree);
rs_optget(&Optget);
return(0);
case '?':
rs_optget(&Optget);
sh_cfail(gettxt(_SGI_DMMX_e_option,e_option));
}
}
com += (opt_index-1);
}
rs_optget(&Optget);
aflag = '-';
return(b_common(com,T_FLAG,sh.track_tree,0));
}
int b_alias(argn,com)
register char **com;
{
register int flag = 0;
register struct Amemory *troot;
NOT_USED(argn);
argnum = scoped = 0;
if(com[1])
{
if( (aflag= *com[1]) == '-' || aflag == '+')
{
com += scanargs(com,~(T_FLAG|N_EXPORT));
flag = newflag;
}
}
else
aflag = 0;
if(flag&T_FLAG)
troot = sh.track_tree;
else
troot = sh.alias_tree;
return(b_common(com,flag,troot,0));
}
int b_typeset(argn,com)
register char **com;
{
register int flag = 0;
struct Amemory *troot;
NOT_USED(argn);
argnum = scoped = 0;
if(com[1])
{
if( (aflag= *com[1]) == '-' || aflag == '+')
{
com += scanargs(com,~(N_LJUST|N_RJUST|N_ZFILL
|N_INTGER|N_LTOU |N_UTOL|X_FLAG|R_FLAG
|F_FLAG|T_FLAG|N_HOST
|N_DOUBLE|N_EXPNOTE));
flag = newflag;
}
}
else
aflag = 0;
/* G_FLAG forces name to be in newest scope */
if(st.fn_depth)
scoped = G_FLAG;
if((flag&N_INTGER) && (flag&(N_LJUST|N_RJUST|N_ZFILL|F_FLAG)))
sh_cfail(gettxt(_SGI_DMMX_e_option,e_option));
else if(flag&F_FLAG)
{
if(flag&~(N_EXPORT|F_FLAG|T_FLAG|U_FLAG))
sh_cfail(gettxt(_SGI_DMMX_e_option,e_option));
troot = sh.fun_tree;
flag &= ~F_FLAG;
}
else
troot = sh.var_tree;
return(b_common(com,flag,troot,0));
}
static int b_common(com,flag,troot,pflag)
register int flag,pflag;
char **com;
struct Amemory *troot;
{
register int fd;
register char *a1;
register int type = 0;
int r = 0;
fd = st.standout;
p_setout(fd);
if(troot==sh.alias_tree)
/* env_namset treats this value specially */
type = (V_FLAG|G_FLAG);
if(aflag == 0)
{
if(type)
env_scan(fd,0,troot,0,pflag);
else
gscan_all(env_prattr,troot);
return(0);
}
if(com[1])
{
while(a1 = *++com)
{
register unsigned newflag;
register struct namnod *np;
unsigned curflag;
if(st.subflag && (flag || strchr(a1,'=')))
continue;
if(troot == sh.fun_tree)
{
/*
*functions can be exported or
* traced but not set
*/
if(flag&U_FLAG)
np = env_namset(a1,sh.fun_tree,P_FLAG|V_FLAG);
else
np = nam_search(a1,sh.fun_tree,0);
if(np && is_abuiltin(np))
np = 0;
if(np && ((flag&U_FLAG) || !isnull(np)))
{
if(flag==0)
{
env_prnamval(np,0);
continue;
}
if(aflag=='-')
nam_ontype(np,flag|N_FUNCTION);
else if(aflag=='+')
nam_offtype(np,~flag);
}
else
r++;
continue;
}
np = env_namset(a1,troot,(type|scoped));
/* tracked alias */
if(troot==sh.track_tree && aflag=='-')
{
nam_ontype(np,NO_ALIAS);
path_alias(np,path_absolute(np->namid));
continue;
}
if(flag==0 && aflag!='-' && strchr(a1,'=') == NULL)
{
/* type==0 for TYPESET */
if(type && (isnull(np) || !env_prnamval(np,0)))
{
p_setout(ERRIO);
p_str(a1,':');
p_str(gettxt(_SGI_DMMX_e_alias,e_alias),NL);
r++;
p_setout(st.standout);
}
continue;
}
curflag = namflag(np);
if (aflag == '-')
{
newflag = curflag;
if(flag&~NO_CHANGE)
newflag &= NO_CHANGE;
newflag |= flag;
if (flag & (N_LJUST|N_RJUST))
{
if (flag & N_LJUST)
newflag &= ~N_RJUST;
else
newflag &= ~N_LJUST;
}
if (flag & N_UTOL)
newflag &= ~N_LTOU;
else if (flag & N_LTOU)
newflag &= ~N_UTOL;
}
else
{
if((flag&R_FLAG) && (curflag&R_FLAG))
sh_fail(np->namid,gettxt(_SGI_DMMX_e_readonly,e_readonly),ERROR);
newflag = curflag & ~flag;
}
if (aflag && (argnum>0 || (curflag!=newflag)))
{
if(type)
namflag(np) = newflag;
else
nam_newtype (np, newflag,argnum);
nam_newtype (np, newflag,argnum);
}
}
}
else
env_scan(fd,flag,troot,aflag=='+',(pflag?flag:0));
return(r);
}
/*
* The removing of Shell variable names, aliases, and functions
* is performed here.
* Unset functions with unset -f
* Non-existent items being deleted give non-zero exit status
*/
int b_unalias(argn,com)
char **com;
{
register int c;
struct sh_optget Optget;
sv_optget(&Optget);
while ((c = optget(argn, com, "a")) != EOF)
{
switch (c)
{
case 'a':
gscan_all(nam_free,sh.alias_tree);
rs_optget(&Optget);
return(0);
case '?':
rs_optget(&Optget);
sh_cfail(gettxt(_SGI_DMMX_e_option,e_option));
}
}
com += (opt_index-1);
argn -= (opt_index-1);
rs_optget(&Optget);
return(b_unall(argn,com,sh.alias_tree));
}
int b_unset(argn,com)
register char **com;
{
struct Amemory *troot;
register int c;
struct sh_optget Optget;
sv_optget(&Optget);
troot = sh.var_tree; /* default tree */
while ((c = optget(argn, com, "fv")) != EOF)
{
switch (c)
{
case 'f':
troot = sh.fun_tree;
break;
case 'v':
troot = sh.var_tree;
break;
case '?':
rs_optget(&Optget);
sh_fail(*com,gettxt(_SGI_DMMX_e_option,e_option),ERROR);
/* NOTREACHED */
}
}
com += (opt_index-1);
argn -= (opt_index-1);
rs_optget(&Optget);
return(b_unall(argn,com,troot));
}
static int b_unall(argn,com,troot)
register int argn;
char **com;
struct Amemory *troot;
{
register char *a1;
register struct namnod *np;
register struct slnod *slp;
int r = 0;
if(st.subflag)
return(0);
if(argn < 2)
sh_cfail(gettxt(_SGI_DMMX_e_nargs,e_nargs));
while(a1 = *++com)
{
np=env_namset(a1,troot,P_FLAG);
if(np && !isnull(np))
{
if(troot==sh.var_tree)
{
if (nam_istype (np, N_RDONLY))
sh_fail(np->namid,gettxt(_SGI_DMMX_e_readonly,e_readonly),ERROR);
else if (nam_istype (np, N_RESTRICT))
sh_fail(np->namid,gettxt(_SGI_DMMX_e_restricted,e_restricted),ERROR);
#ifdef apollo
{
short namlen;
namlen =strlen(np->namid);
ev_$delete_var(np->namid,&namlen);
}
#endif /* apollo */
}
else if(is_abuiltin(np))
{
r = 1;
continue;
}
else if(slp=(struct slnod*)(np->value.namenv))
{
/* free function definition */
stakdelete(slp->slptr);
np->value.namenv = 0;
}
nam_free(np);
}
else if(isnull(np) && troot!=sh.alias_tree)
r = 0;
else r = 1;
}
return(r);
}
int b_dot(argn,com)
char **com;
{
register char *a1 = com[1];
st.states &= ~MONITOR;
if(a1)
{
register int flag;
jmp_buf retbuf;
jmp_buf *savreturn = sh.freturn;
#ifdef POSIX
/* check for function first */
register struct namnod *np;
np = nam_search(a1,sh.fun_tree,0);
if(np && !np->value.namval.ip)
{
if(!nam_istype(np,N_FUNCTION))
np = 0;
else
{
path_search(a1,0);
if(np->value.namval.ip==0)
sh_fail(a1,gettxt(_SGI_DMMX_e_found,e_found),FNDBAD);
}
}
if(!np)
#endif /* POSIX */
if((sh.un.fd=path_open(a1,path_get(a1))) < 0)
sh_fail(a1,gettxt(_SGI_DMMX_e_found,e_found),FNDBAD);
else
{
if(st.dot_depth++ > DOTMAX)
sh_cfail(gettxt(_SGI_DMMX_e_recursive,e_recursive));
if(argn > 2)
arg_set(com+1);
st.states |= BUILTIN;
sh.freturn = (jmp_buf*)retbuf;
flag = SETJMP(retbuf);
if(flag==0)
{
#ifdef POSIX
if(np)
sh_exec((union anynode*)(funtree(np))
,(int)(st.states&(ERRFLG|MONITOR)));
else
#endif /* POSIX */
sh_eval((char*)0);
}
st.states &= ~BUILTIN;
sh.freturn = savreturn;
st.dot_depth--;
if(flag && flag!=2)
sh_exit(sh.exitval);
}
}
else
sh_cfail(gettxt(_SGI_DMMX_e_argexp,e_argexp));
return(sh.exitval);
}
int b_times()
{
struct tms tt;
times(&tt);
p_setout(st.standout);
p_time(tt.tms_utime,' ');
p_time(tt.tms_stime,NL);
p_time(tt.tms_cutime,' ');
p_time(tt.tms_cstime,NL);
return(0);
}
/*
* return and exit
*/
int b_ret_exit(argn,com)
register char **com;
{
register int flag;
register int isexit = (**com=='e');
NOT_USED(argn);
if(st.subflag)
return(0);
flag = ((com[1]?atoi(com[1]):sh.oldexit)&EXITMASK);
if(st.fn_depth>0 || (!isexit && (st.dot_depth>0||(st.states&PROFILE))))
{
sh.exitval = flag;
LONGJMP(*sh.freturn,isexit?4:2);
}
/* force exit */
st.states &= ~(PROMPT|PROFILE|BUILTIN|FUNCTION|LASTPIPE);
sh_exit(flag);
return(1);
}
/*
* null command
*/
int b_null(argn,com)
register char **com;
{
NOT_USED(argn);
return(**com=='f');
}
int b_continue(argn,com)
register char **com;
{
NOT_USED(argn);
if(!st.subflag && st.loopcnt)
{
st.execbrk = st.breakcnt = 1;
if(com[1])
st.breakcnt = atoi(com[1]);
if(st.breakcnt > st.loopcnt)
st.breakcnt = st.loopcnt;
else
st.breakcnt = -st.breakcnt;
}
return(0);
}
int b_break(argn,com)
register char **com;
{
NOT_USED(argn);
if(!st.subflag && st.loopcnt)
{
st.execbrk = st.breakcnt = 1;
if(com[1])
st.breakcnt = atoi(com[1]);
if(st.breakcnt > st.loopcnt)
st.breakcnt = st.loopcnt;
}
return(0);
}
int b_trap(argn,com)
char **com;
{
register char *a1 = com[1];
register int sig;
NOT_USED(argn);
if(a1)
{
register int clear;
char *action = a1;
if(st.subflag)
return(0);
if(strcmp(a1,"--")==0) {
if(!com[2]) {
sig_list(-1);
return(0);
}
++com;
action = a1 = com[1];
}
/* first argument all digits or - means clear */
while(isdigit(*a1))
a1++;
clear = (a1!=action && *a1==0);
if(!clear)
{
++com;
if(*action=='-' && action[1]==0)
clear++;
}
while(a1 = *++com)
{
sig = sig_number(a1);
if(sig>=MAXTRAP || sig<MINTRAP)
sh_fail(a1,gettxt(_SGI_DMMX_e_trap,e_trap),ERROR);
else if(clear)
sig_clear(sig);
else
{
if(a1=st.trapcom[sig])
free(a1);
st.trapcom[sig] = sh_heap(action);
if(*action)
sig_ontrap(sig);
else
sig_ignore(sig);
}
}
}
else /* print out current traps */
#ifdef POSIX
sig_list(-1);
#else
{
p_setout(st.standout);
for(sig=0; sig<MAXTRAP; sig++)
if(st.trapcom[sig])
{
p_num(sig,':');
p_str(st.trapcom[sig],NL);
}
}
#endif /* POSIX */
return(0);
}
int b_chdir(argn,com)
char **com;
{
register char *a1 = com[1];
register const char *dp;
register char *cdpath = NULLSTR;
int flag = 0;
int rval = -1;
int errval = 1;
char *oldpwd;
if(st.subflag)
return(0);
if(is_option(RSHFLG))
sh_cfail(gettxt(_SGI_DMMX_e_restricted,e_restricted));
#ifdef LSTAT
#ifdef apollo
/*
* support for the apollo "set -o physical" feature.
*/
flag = is_option(PHYSICAL);
#endif /* apollo */
while(a1 && *a1=='-' && a1[1])
{
flag = flagset(a1,~(PHYS_MODE|LOG_MODE));
if(flag&LOG_MODE)
flag = 0;
com++;
argn--;
a1 = com[1];
}
#endif /* LSTAT */
if(argn >3)
sh_cfail(gettxt(_SGI_DMMX_e_nargs,e_nargs));
oldpwd = sh.pwd;
if(argn==3)
a1 = sh_substitute(oldpwd,a1,com[2]);
else if(a1==0 || *a1==0)
a1 = nam_strval(HOME);
else if(*a1 == '-' && *(a1+1) == 0)
a1 = nam_strval(OLDPWDNOD);
if(a1==0 || *a1==0)
sh_cfail(argn==3?gettxt(_SGI_DMMX_e_subst,e_subst):gettxt(_SGI_DMMX_e_direct,e_direct));
if(*a1 != '/')
{
cdpath = nam_strval(CDPNOD);
if(oldpwd==0)
oldpwd = path_pwd(1);
}
if(cdpath==0)
cdpath = NULLSTR;
if(*a1=='.')
{
/* test for pathname . ./ .. or ../ */
if(*(dp=a1+1) == '.')
dp++;
if(*dp==0 || *dp=='/')
cdpath = NULLSTR;
}
do
{
dp = cdpath;
cdpath=path_join((char*)dp,a1);
if(*stakptr(OPATH)!='/')
{
char *last=(char*)stakfreeze(1);
stakseek(OPATH);
stakputs(oldpwd);
stakputc('/');
stakputs(last+OPATH);
stakputc(0);
}
#ifdef LSTAT
if(!flag)
#endif /* LSTAT */
{
register char *cp;
#ifdef FS_3D
if(!(cp = pathcanon(stakptr(OPATH))))
continue;
/* eliminate trailing '/' */
while(*--cp == '/' && cp>stakptr(OPATH))
*cp = 0;
#else
if(*(cp=stakptr(OPATH))=='/')
if(!pathcanon(cp))
continue;
#endif /* FS_3D */
}
rval = chdir(path_relative(stakptr(OPATH)));
}
while(rval<0 && cdpath);
/* use absolute chdir() if relative chdir() fails */
if(rval<0 && *a1=='/' && *(path_relative(stakptr(OPATH)))!='/')
rval = chdir(a1);
#ifdef apollo
/*
* The label is used to display the error message if path_physical()
* routine fails.(See below)
*/
unavoidable_goto:
#endif /* apollo */
if(rval<0)
{
switch(errno)
{
#ifdef ENAMETOOLONG
case ENAMETOOLONG:
dp = gettxt(_SGI_DMMX_e_longname,e_longname);
break;
#endif /* ENAMETOOLONG */
#ifdef EMULTIHOP
case EMULTIHOP:
dp = gettxt(_SGI_DMMX_e_multihop,e_multihop);
break;
#endif /* EMULTIHOP */
case ENOTDIR:
dp = gettxt(_SGI_DMMX_e_notdir,e_notdir);
break;
case ENOENT:
dp = gettxt(_SGI_DMMX_e_found,e_found);
errval = FNDBAD;
break;
case EACCES:
dp = gettxt(_SGI_DMMX_e_access,e_access);
break;
#ifdef ENOLINK
case ENOLINK:
dp = gettxt(_SGI_DMMX_e_link,e_link);
break;
#endif /* ENOLINK */
default:
dp = gettxt(_SGI_DMMX_e_direct,e_direct);
break;
}
sh_fail(a1,dp,errval);
}
if(a1 == nam_strval(OLDPWDNOD) || argn==3)
dp = a1; /* print out directory for cd - */
#ifdef LSTAT
if(flag)
{
a1 = stakfreeze(1)+OPATH;
#ifdef apollo
/*
* check the return status of path_physical().
* if the return status is 0 then the getwd() has
* failed, so print an error message.
*/
if ( !path_physical(a1) )
{
rval = -1;
goto unavoidable_goto;
}
#else
path_physical(a1);
#endif /* apollo */
}
else
#endif /* LSTAT */
a1 = (char*)stakfreeze(1)+OPATH;
#ifdef POSIX
if(*dp && *dp!= ':' && strchr(a1,'/'))
#else
if(*dp && *dp!= ':' && (st.states&PROMPT) && strchr(a1,'/'))
#endif /* POSIX */
{
p_setout(st.standout);
p_str(a1,NL);
}
if(*a1 != '/')
return(0);
nam_fputval(OLDPWDNOD,oldpwd);
if(oldpwd)
free(oldpwd);
nam_free(PWDNOD);
nam_fputval(PWDNOD,a1);
nam_ontype(PWDNOD,N_FREE|N_EXPORT);
sh.pwd = PWDNOD->value.namval.cp;
return(0);
}
int b_shift(argn,com)
register char **com;
{
register int flag = (com[1]?(int)sh_arith(com[1]):1);
NOT_USED(argn);
if(flag<0 || st.dolc<flag)
sh_cfail(gettxt(_SGI_DMMX_e_number,e_number));
else
{
if(st.subflag)
return(0);
st.dolv += flag;
st.dolc -= flag;
}
return(0);
}
int b_wait(argn,com)
register char **com;
{
NOT_USED(argn);
st.states &= ~MONITOR;
if(!st.subflag)
job_bwait(com+1);
return(sh.exitval);
}
/*
* b_read() adds C_FLAG to env_readline() to continue assigning variables
* after encountering readonly variables.
*/
int b_read(argn,com)
char **com;
{
register char *a1 = com[1];
register int flag;
register int fd;
int r1,r2;
NOT_USED(argn);
st.states &= ~MONITOR;
tty_set(-1); /* reset tty info */
argnum = 0;
com += scanargs(com,~(R_FLAG|P_FLAG|U_FLAG|S_FLAG));
a1 = com[1];
flag = newflag;
if(flag&P_FLAG)
{
if((fd = sh.cpipe[INPIPE])<=0)
sh_cfail(gettxt(_SGI_DMMX_e_query,e_query));
}
else if(flag&U_FLAG)
fd = argnum;
else
fd = 0;
if(fd && !fisread(fd))
sh_cfail(gettxt(_SGI_DMMX_e_file,e_file));
/* look for prompt */
if(a1 && (a1=strchr(a1,'?')) && tty_check(fd))
{
p_setout(ERRIO);
p_str(a1+1,0);
}
r1 = env_readline(&com[1],fd,flag&(R_FLAG|S_FLAG)|C_FLAG);
if(r2=(fiseof(io_ftable[fd])!=0))
{
if(flag&P_FLAG)
{
io_pclose(sh.cpipe);
return(1);
}
}
clearerr(io_ftable[fd]);
return(r2?r2:(r1?r1:0));
}
int b_set(argn,com)
register char **com;
{
if(com[1])
{
arg_opts(argn,com,BUILTIN);
st.states &= ~(READPR|MONITOR);
st.states |= is_option(READPR|MONITOR);
}
else
/*scan name chain and print*/
env_scan(st.standout,0,sh.var_tree,0,0);
return(sh.exitval);
}
int b_eval(argn,com)
register char **com;
{
NOT_USED(argn);
st.states &= ~MONITOR;
if(com[1])
{
sh.un.com = com+2;
sh_eval(com[1]);
}
return(sh.exitval);
}
int b_fc(argn,com)
char **com;
{
register char *a1;
register int flag;
register struct history *fp;
int fdo;
char *argv[2];
char fname[TMPSIZ];
int index2;
int indx = -1; /* used as subscript for range */
char *edit = NULL; /* name of editor */
char *replace = NULL; /* replace old=new */
int incr;
int range[2]; /* upper and lower range of commands */
int lflag = 0;
int nflag = 0;
int rflag = 0;
histloc location;
NOT_USED(argn);
st.states |= BUILTIN;
if(!hist_open())
sh_cfail(gettxt(_SGI_DMMX_e_history,e_history));
fp = hist_ptr;
while((a1=com[1]) && *a1 == '-')
{
if(*(a1+1) == '-')
{
++com;
continue;
}
argnum = -1;
flag = flagset(a1,~(E_FLAG|L_FLAG|N_FLAG|R_FLAG|S_FLAG));
if(flag==0)
{
if(argnum < 0)
{
com++;
break;
}
flag = fp->fixind - argnum-1;
if(flag <= 0)
flag = 1;
range[++indx] = flag;
argnum = 0;
if(indx==1)
break;
}
else
{
if(flag&E_FLAG)
{
/* name of editor specified */
com++;
if((edit=com[1]) == NULL)
sh_cfail(gettxt(_SGI_DMMX_e_argexp,e_argexp));
}
if(flag&S_FLAG)
edit = "-";
if(flag&N_FLAG)
nflag++;
if(flag&L_FLAG)
lflag++;
if(flag&R_FLAG)
rflag++;
}
com++;
}
flag = indx;
while(flag<1 && (a1=com[1]))
{
/* look for old=new argument */
if(replace==NULL && strchr(a1+1,'='))
{
replace = a1;
com++;
continue;
}
else if(isdigit(*a1) || *a1 == '-' || *a1 == '+')
{
/* see if completely numeric */
do a1++;
while(isdigit(*a1));
if(*a1==0)
{
a1 = com[1];
range[++flag] = atoi(a1);
if(*a1 == '-')
range[flag] += (fp->fixind-1);
com++;
continue;
}
}
/* search for last line starting with string */
location = hist_find(com[1],fp->fixind-1,0,-1);
if((range[++flag] = location.his_command) < 0)
sh_fail(com[1],gettxt(_SGI_DMMX_e_found,e_found),FNDBAD);
com++;
}
if(flag <0)
{
/* set default starting range */
if(lflag)
{
flag = fp->fixind-16;
if(flag<1)
flag = 1;
}
else
flag = fp->fixind-2;
range[0] = flag;
flag = 0;
}
if(flag==0)
/* set default termination range */
range[1] = (lflag?fp->fixind-1:range[0]);
if((index2 = fp->fixind - fp->fixmax) <=0)
index2 = 1;
/* check for valid ranges */
for(flag=0;flag<2;flag++)
if(range[flag]<index2 ||
range[flag]>=(fp->fixind-(lflag==0)))
sh_cfail(gettxt(_SGI_DMMX_e_number,e_number));
if(edit && *edit=='-' && range[0]!=range[1])
sh_cfail(gettxt(_SGI_DMMX_e_number,e_number));
/* now list commands from range[rflag] to range[1-rflag] */
incr = 1;
flag = rflag>0;
if(range[1-flag] < range[flag])
incr = -1;
if(lflag)
{
fdo = st.standout;
a1 = "\n\t";
}
else
{
fdo = io_mktmp(fname);
a1 = "\n";
nflag++;
}
p_setout(fdo);
while(1)
{
if(nflag==0)
p_num(range[flag],'\t');
else if(lflag)
p_char('\t');
hist_list(hist_position(range[flag]),0,a1);
if(lflag && (sh.trapnote&SIGSET))
sh_exit(SIGFAIL);
if(range[flag] == range[1-flag])
break;
range[flag] += incr;
}
if(lflag)
return(0);
io_fclose(fdo);
hist_eof();
p_setout(ERRIO);
a1 = edit;
if(a1==NULL && (a1=nam_strval(FCEDNOD)) == NULL)
a1 = (char*)e_defedit;
#ifdef apollo
/*
* Code to support the FC using the pad editor.
* Exampled of how to use: FCEDIT=pad
*/
if (strcmp (a1, "pad") == 0)
{
int pad_create();
io_fclose(fdo);
fdo = pad_create(fname);
pad_wait(fdo);
unlink(fname);
strcat(fname, ".bak");
unlink(fname);
io_seek(fdo,(off_t)0,SEEK_SET);
}
else
{
#endif /* apollo */
if(*a1 != '-')
{
sh.un.com = argv;
argv[0] = fname;
argv[1] = NULL;
sh_eval(a1);
}
fdo = io_fopen(fname);
unlink(fname);
#ifdef apollo
}
#endif /* apollo */
/* don't history fc itself unless forked */
if(!(st.states&FORKED))
hist_cancel();
st.states |= (READPR|FIXFLG); /* echo lines as read */
st.exec_flag--; /* needed for command numbering */
if(replace!=NULL)
hist_subst(sh.cmdname,fdo,replace);
else if(sh.exitval == 0)
{
/* read in and run the command */
st.states &= ~BUILTIN;
sh.un.fd = fdo;
sh_eval((char*)0);
}
else
{
io_fclose(fdo);
if(!is_option(READPR))
st.states &= ~(READPR|FIXFLG);
}
st.exec_flag++;
return(sh.exitval);
}
int b_getopts(argn,com)
char **com;
{
register char *optstr = com[1];
register char *namval;
register int flag;
register struct namnod *n;
char namarg[3];
int r = 0;
extern opt_index,opt_opt;
if(argn < 3)
sh_cfail(gettxt(_SGI_DMMX_e_argexp,e_argexp));
n = env_namset(com[2],sh.var_tree,P_FLAG);
if(argn>3)
{
com +=2;
argn -=2;
}
else
{
com = st.dolv;
argn = st.dolc+1;
}
/* nam_offtype(OPTARGNOD,~N_RDONLY); */
switch(flag=optget(argn,com,optstr))
{
case ':':
case '?':
if(*optstr != ':')
{
p_setout(ERRIO);
p_prp(sh.cmdname);
p_str(e_colon,opt_opt);
p_char(' ');
if(flag == '?')
{
p_str(gettxt(_SGI_DMMX_e_option,e_option),NL);
r = 0;
}
else
{
p_str(gettxt(_SGI_DMMX_e_argexp,e_argexp),NL);
r = 1;
}
nam_fputval(OPTARGNOD,"");
namval = "?";
}
else
{
char badarg[2];
badarg[0] = opt_opt;
badarg[1] = 0;
if(flag == '?')
namval = "?";
else namval = ":";
r = 0;
nam_fputval(OPTARGNOD,badarg);
}
break;
case -1:
namval = "?";
r = 1;
nam_fputval(OPTARGNOD,"");
break;
default:
if(opt_plus)
{
namarg[0] = '+';
namarg[1] = flag;
namarg[2] = 0;
}
else
{
namarg[0] = flag;
namarg[1] = 0;
}
namval = namarg;
nam_fputval(OPTARGNOD,opt_arg);
r = 0;
break;
}
nam_putval(n, namval);
/* nam_ontype(OPTARGNOD,N_RDONLY); */
return(r);
}
int b_whence(argn,com)
register char **com;
{
NOT_USED(argn);
com += scanargs(com,~(V_FLAG|P_FLAG));
if(com[1] == 0)
sh_cfail(gettxt(_SGI_DMMX_e_nargs,e_nargs));
p_setout(st.standout);
return(sh_whence(com,newflag));
}
int b_umask(argn,com)
char **com;
{
register char *a1;
register int flag = 0;
register int Sflag = 0;
register int c;
struct sh_optget Optget;
sv_optget(&Optget);
if(argn == 1)
a1 = NULL;
else if(argn > 1 && *com[1] == '-')
{
while ((c = optget(argn, com, "S")) != EOF)
{
switch (c)
{
case 'S':
++Sflag;
break;
case '?':
rs_optget(&Optget);
sh_cfail(gettxt(_SGI_DMMX_e_option,e_option));
/* NOTREACHED */
}
}
if(Sflag && argn > opt_index || (argn-opt_index) > 1)
{
rs_optget(&Optget);
sh_cfail(gettxt(_SGI_DMMX_e_nargs,e_nargs));
/* NOTREACHED */
}
if(Sflag)
a1 = NULL;
else a1 = com[opt_index];
}
else if(argn > 2)
{
rs_optget(&Optget);
sh_cfail(gettxt(_SGI_DMMX_e_nargs,e_nargs));
/* NOTREACHED */
}
else a1 = com[opt_index];
rs_optget(&Optget);
if(a1)
{
register int c;
if(st.subflag)
return(0);
if(isdigit(*a1))
{
while(c = *a1++)
{
if (c>='0' && c<='7')
flag = (flag<<3) + (c-'0');
else
sh_cfail(gettxt(_SGI_DMMX_e_number,e_number));
}
}
else
{
char **cp = com+1;
flag = umask(0);
c = strperm(a1,cp,~flag);
if(**cp)
{
umask(flag);
sh_cfail(gettxt(_SGI_DMMX_e_format,e_format));
}
flag = (~c&0777);
}
umask(flag);
}
else
{
p_setout(st.standout);
a1 = utos((ulong)(flag=umask(0)),8);
umask(flag);
if(Sflag)
{
register int x;
for(x=2;x>=0;--x)
{
(x==2?p_str("u=",0):(x==1?p_str(",g=",0):p_str(",o=",0)));
if((~flag>>(x*3))&4)p_str("r",0);
if((~flag>>(x*3))&2)p_str("w",0);
if((~flag>>(x*3))&1)p_str("x",0);
}
p_char(NL);
}
else
{
*++a1 = '0';
p_str(a1,NL);
}
}
return(0);
}
#ifdef LIM_CPU
# define HARD 1
# define SOFT 2
/* BSD style ulimit */
int b_ulimit(argn,com)
char **com;
{
register char *a1;
register int flag = 0;
# ifdef RLIMIT_CPU
struct rlimit64 rlp;
# endif /* RLIMIT_CPU */
const struct sysmsgnod *sp;
rlim64_t i;
int label;
register int n;
register int mode = 0;
int unit;
struct sh_optget Optget;
sv_optget(&Optget);
while((n = optget(argn,com,":HSacdfmnpstv")) != EOF)
{
switch(n)
{
case 'H':
mode |= HARD;
continue;
case 'S':
mode |= SOFT;
continue;
case 'a':
flag = (0x2f
# ifdef LIM_MAXRSS
|(1<<4)
# endif /* LIM_MAXRSS */
# ifdef RLIMIT_NOFILE
|(1<<6)
# endif /* RLIMIT_NOFILE */
# ifdef RLIMIT_VMEM
|(1<<7)
# endif /* RLIMIT_VMEM */
# ifdef RLIMIT_PTHREAD
|(1<<8)
# endif /* RLIMIT_PTHREAD */
);
break;
case 't':
flag |= 1;
break;
# ifdef LIM_MAXRSS
case 'm':
flag |= (1<<4);
break;
# endif /* LIM_MAXRSS */
case 'd':
flag |= (1<<2);
break;
case 's':
flag |= (1<<3);
break;
case 'f':
flag |= (1<<1);
break;
case 'c':
flag |= (1<<5);
break;
# ifdef RLIMIT_NOFILE
case 'n':
flag |= (1<<6);
break;
# endif /* RLIMIT_NOFILE */
# ifdef RLIMIT_VMEM
case 'v':
flag |= (1<<7);
break;
# endif /* RLIMIT_VMEM */
# ifdef RLIMIT_PTHREAD
case 'p':
flag |= (1<<8);
break;
# endif /* RLIMIT_PTHREAD */
default:
rs_optget(&Optget);
sh_cfail(gettxt(_SGI_DMMX_e_option,e_option));
}
}
a1 = com[opt_index];
rs_optget(&Optget);
/* default to -f */
if(flag==0)
flag |= (1<<1);
/* only one option at a time for setting */
label = (flag&(flag-1));
if(a1 && label)
sh_cfail(gettxt(_SGI_DMMX_e_option,e_option));
sp = limit_names;
if(mode==0)
mode = (HARD|SOFT);
for(; flag; sp++,flag>>=1)
{
if(!(flag&1))
continue;
n = sp->sysval>>11;
unit = sp->sysval&0x7ff;
if(a1)
{
if(st.subflag)
return(0);
if(strcmp(a1,gettxt(_SGI_DMMX_e_unlimited,e_unlimited))==0)
i = INFINITY;
else
{
long long n64;
if((n64=sh_arith(a1)) < 0)
sh_cfail(gettxt(_SGI_DMMX_e_number,e_number));
i = (rlim64_t)n64;
i *= unit;
}
# ifdef RLIMIT_CPU
if(getrlimit64(n,&rlp) <0)
sh_cfail(gettxt(_SGI_DMMX_e_number,e_number));
if(mode&HARD)
rlp.rlim_max = i;
if(mode&SOFT)
rlp.rlim_cur = i;
if(setrlimit64(n,&rlp) <0)
sh_cfail(gettxt(_SGI_DMMX_e_ulimit,e_ulimit));
# endif /* RLIMIT_CPU */
}
else
{
# ifdef RLIMIT_CPU
if(getrlimit64(n,&rlp) <0)
sh_cfail(gettxt(_SGI_DMMX_e_number,e_number));
if(mode&HARD)
i = rlp.rlim_max;
if(mode&SOFT)
i = rlp.rlim_cur;
# else
i = -1;
}
if((i=vlimit(n,i)) < 0)
sh_cfail(gettxt(_SGI_DMMX_e_number,e_number));
if(a1==0)
{
# endif /* RLIMIT_CPU */
p_setout(st.standout);
if(label)
p_str(gettxt(sp->sysmsgid,sp->sysnam),SP);
if(i!=INFINITY)
{
i = (i+unit-1)/unit;
p_str(u64tos((unsigned long long)i,10),NL);
}
else
p_str(gettxt(_SGI_DMMX_e_unlimited,e_unlimited),NL);
}
}
return(0);
}
#else
int b_ulimit(argn,com)
char **com;
{
register char *a1 = com[1];
register int flag;
# ifndef VENIX
long i;
long ulimit();
register int mode = 2;
NOT_USED(argn);
if(a1 && *a1 == '-')
{
# ifdef RT
flag = flagset(a1,~(F_FLAG|P_FLAG));
# else
flag = flagset(a1,~F_FLAG);
# endif /* RT */
a1 = com[2];
}
if(flag&P_FLAG)
mode = 5;
if(a1)
{
if(st.subflag)
return(0);
if((i=sh_arith(a1)) < 0)
sh_cfail(gettxt(_SGI_DMMX_e_number,e_number));
}
else
{
mode--;
i = -1;
}
if((i=ulimit(mode,i)) < 0)
sh_cfail(gettxt(_SGI_DMMX_e_number,e_number));
if(a1==0)
{
p_setout(st.standout);
p_str(utos((ulong)i,10),NL);
}
# endif /* VENIX */
return(0);
}
#endif /* LIM_CPU */
#ifdef JOBS
# ifdef SIGTSTP
int b_bgfg(argn,com)
register char **com;
{
register int flag = (**com=='b');
NOT_USED(argn);
#ifdef POSIX
if(com[1] && *com[1] == '-')
{
if(strcmp(com[1],"--")==0)
++com;
else
sh_cfail(gettxt(_SGI_DMMX_e_option,e_option));
}
#endif /* POSIX */
if(!is_option(MONITOR) || !job.jobcontrol)
{
if(st.states&PROMPT)
sh_cfail(gettxt(_SGI_DMMX_e_no_jctl,e_no_jctl));
return(1);
}
if(job_walk(job_switch,flag,com+1))
sh_cfail(gettxt(_SGI_DMMX_e_no_job,e_no_job));
return(sh.exitval);
}
# endif /* SIGTSTP */
int b_jobs(argn,com)
char **com;
{
NOT_USED(argn);
com += scanargs(com,~(N_FLAG|L_FLAG|P_FLAG));
if(*++com==0)
com = 0;
p_setout(st.standout);
if(job_walk(job_list,newflag,com))
sh_cfail(gettxt(_SGI_DMMX_e_no_job,e_no_job));
return(sh.exitval);
}
int b_kill(argn,com)
char **com;
{
register int flag;
register char *a1 = com[1];
if(argn < 2)
sh_cfail(gettxt(_SGI_DMMX_e_nargs,e_nargs));
/* just in case we send a kill -9 $$ */
p_flush();
flag = SIGTERM;
if(*a1 == '-')
{
a1++;
if(*a1 == 'l')
{
#ifdef POSIX
if(argn>2)
{
com++;
while(a1= *++com)
{
if(isdigit(*a1))
sig_list((atoi(a1)&0177)+1);
else
{
if((flag=sig_number(a1)) < 0)
sh_cfail(gettxt(_SGI_DMMX_e_option,e_option));
p_num(flag,NL);
}
}
}
else
#endif /* POSIX */
sig_list(0);
return(0);
}
else if(*a1=='s')
{
com++;
a1 = com[1];
}
flag = sig_number(a1);
if(flag <0 || flag >= NSIG)
sh_cfail(gettxt(_SGI_DMMX_e_option,e_option));
com++;
}
if(*++com==0)
sh_cfail(gettxt(_SGI_DMMX_e_nargs,e_nargs));
if(strcmp(*com,"--")==0)
++com;
if(job_walk(job_kill,flag,com))
sh.exitval = 2;
return(sh.exitval);
}
#endif
#ifdef LDYNAMIC
# ifdef apollo
/*
* Apollo system support library loads into the virtual address space
*/
int b_inlib(argn,com)
char **com;
{
register char *a1 = com[1];
int status;
short len;
std_$call void loader_$inlib();
if(!st.subflag && a1)
{
len = strlen(a1);
loader_$inlib(*a1, len, status);
if(status!=0)
sh_fail(a1, gettxt(_SGI_DMMX_e_badinlib,e_badinlib),ERROR);
}
return(0);
}
#else
/*
* dynamic library loader from Ted Kowalski
*/
int b_inlib(argn,com)
char **com;
{
register char *a1;
if(!st.subflag)
{
ldinit();
addfunc(ldname("nam_putval", 0), (int (*)())nam_putval);
addfunc(ldname("nam_strval", 0), (int (*)())nam_strval);
addfunc(ldname("p_setout", 0), (int (*)())p_setout);
addfunc(ldname("p_str", 0), (int (*)())p_str);
addfunc(ldname("p_flush", 0), (int (*)())p_flush);
while(a1= *++com)
{
if(!ldfile(a1))
sh_fail(a1, gettxt(_SGI_DMMX_e_badinlib,e_badinlib),ERROR);
}
loadend();
if(undefined()!=0)
sh_cfail(gettxt(_SGI_DMMX_e_undefsym,e_undefsym));
}
}
/*
* bind a built-in name to the function that implements it
* uses Ted Kowalski's run-time loader
*/
int b_builtin(argn,com)
char **com;
{
register struct namnod *np;
int (*fn)();
int (*ret_func())();
if(argn!=3)
sh_cfail(gettxt(_SGI_DMMX_e_nargs,e_nargs));
if(!(np = nam_search(com[1],sh.fun_tree,N_ADD)))
sh_fail(com[1],gettxt(_SGI_DMMX_e_create,e_create),ERROR);
if(!isnull(np))
sh_fail(com[1],gettxt(_SGI_DMMX_is_builtin,is_builtin),ERROR);
if(!(fn = ret_func(ldname(com[2],0))))
sh_fail(com[2],gettxt(_SGI_DMMX_e_found,e_found),FNDBAD);
funptr(np) = fn;
nam_ontype(np,N_BLTIN);
}
# endif /* !apollo */
#endif /* LDYNAMIC */
#ifdef FS_3D
# define VLEN 14
int b_vpath_map(argn,com)
char **com;
{
register int flag = (com[0][1]=='p'?2:4);
register char *a1 = com[1];
char version[VLEN+1];
char *vend;
int n;
switch(argn)
{
case 1:
case 2:
flag |= 8;
p_setout(st.standout);
if((n = mount(a1,version,flag)) >= 0)
{
vend = stakalloc(++n);
n = mount(a1,vend,flag|(n<<4));
}
if(n < 0)
{
if(flag==2)
sh_cfail(gettxt(_SGI_DMMX_e_getmap,e_getmap));
else
sh_cfail(gettxt(_SGI_DMMX_e_getvers,e_getvers));
}
if(argn==2)
{
p_str(vend,NL);
break;
}
n = 0;
while(flag = *vend++)
{
if(flag==' ')
{
flag = e_sptbnl[n+1];
n = !n;
}
p_char(flag);
}
if(n)
newline();
break;
default:
if(!(argn&1))
sh_cfail(gettxt(_SGI_DMMX_e_nargs,e_nargs));
/*FALLTHROUGH*/
case 3:
if(st.subflag)
break;
for(n=1;n<argn;n+=2)
if(mount(com[n+1],com[n],flag)<0)
{
if(flag==2)
sh_cfail(gettxt(_SGI_DMMX_e_setmap,e_setmap));
else
sh_cfail(gettxt(_SGI_DMMX_e_setvpath,e_setvpath));
}
}
return(0);
}
#endif /* FS_3D */
#ifdef UNIVERSE
/*
* there are two styles of universe
* Pyramid universes have <sys/universe.h> file
* Masscomp universes do not
*/
int b_universe(argn,com)
char **com;
{
register char *a1 = com[1];
if(a1)
{
if(setuniverse(univ_number(a1)) < 0)
sh_cfail(gettxt(_SGI_DMMX_e_invalidnm,e_invalidnm));
att_univ = (strcmp(a1,"att")==0);
/* set directory in new universe */
if(*(a1 = path_pwd(0))=='/')
chdir(a1);
/* clear out old tracked alias */
stakseek(0);
stakputs((PATHNOD)->namid);
stakputc('=');
stakputs(nam_strval(PATHNOD));
a1 = stakfreeze(1);
env_namset(a1,sh.var_tree,nam_istype(PATHNOD,~0));
}
else
{
int flag;
char universe[TMPSIZ];
if(getuniverse(universe) < 0)
sh_cfail(gettxt(_SGI_DMMX_e_no_access,e_no_access));
else
p_str(universe,NL);
}
return(0);
}
#endif /* UNIVERSE */
#ifdef SYSSLEEP
/* fine granularity sleep builtin someday */
int b_sleep(argn,com)
char **com;
{
extern double atof();
register char *a1 = com[1];
if(a1)
{
if(strmatch(a1,"*([0-9])?(.)*([0-9])"))
sh_delay(atof(a1));
else
sh_cfail(gettxt(_SGI_DMMX_e_number,e_number));
}
else
sh_cfail(gettxt(_SGI_DMMX_e_argexp,e_argexp));
return(0);
}
#endif /* SYSSLEEP */
static const char flgchar[] = "efgilmnprstuvxEFHLPRZ";
static const int flgval[] = {E_FLAG,F_FLAG,G_FLAG,I_FLAG,L_FLAG,M_FLAG,
N_FLAG,P_FLAG,R_FLAG,S_FLAG,T_FLAG,U_FLAG,V_FLAG,
X_FLAG,N_DOUBLE|N_INTGER|N_EXPNOTE,N_DOUBLE|N_INTGER,
N_HOST,N_LJUST,H_FLAG,N_RJUST,N_RJUST|N_ZFILL};
/*
* process option flags for built-ins
* flagmask are the invalid options
*/
static int flagset(flaglist,flagmask)
char *flaglist;
{
register int flag = 0;
register int c;
register char *cp,*sp;
int numset = 0;
for(cp=flaglist+1;c = *cp;cp++)
{
if(isdigit(c))
{
if(argnum < 0)
{
argnum = 0;
numset = -100;
}
else
numset++;
argnum = 10*argnum + (c - '0');
}
else if(sp=strchr(flgchar,c))
flag |= flgval[sp-flgchar];
else if(c!= *flaglist)
goto badoption;
}
if(numset>0 && flag==0)
goto badoption;
if((flag&flagmask)==0)
return(flag);
badoption:
sh_cfail(gettxt(_SGI_DMMX_e_option,e_option));
/* NOTREACHED */
}
/*
* process command line options and store into newflag
*/
static int scanargs(com,flags)
char *com[];
{
register char **argv = ++com;
register int flag;
register char *a1;
newflag = 0;
if(*argv)
aflag = **argv;
else
aflag = 0;
if(aflag!='+' && aflag!='-')
return(0);
while((a1 = *argv) && *a1==aflag)
{
if(a1[1] && a1[1]!=aflag)
flag = flagset(a1,flags);
else
flag = 0;
argv++;
if(flag==0)
break;
newflag |= flag;
}
return(argv-com);
}
/*
* evaluate the string <s> or the contents of file <un.fd> as shell script
* If <s> is not null, un is interpreted as an argv[] list instead of a file
*/
void sh_eval(s)
register char *s;
{
struct fileblk fb;
union anynode *t;
char inbuf[IOBSIZE+1];
struct ionod *saviotemp = st.iotemp;
struct slnod *saveslp = st.staklist;
io_push(&fb);
if(s)
{
io_sopen(s);
if(sh.un.com)
{
fb.feval=sh.un.com;
if(*fb.feval)
fb.ftype = F_ISEVAL;
}
}
else if(sh.un.fd>=0)
{
io_init(input=sh.un.fd,&fb,inbuf);
}
sh.un.com = 0;
st.exec_flag++;
t = sh_parse(NL,NLFLG|MTFLG);
st.exec_flag--;
if(is_option(READPR)==0)
st.states &= ~READPR;
if(s==NULL && hist_ptr)
hist_flush();
p_setout(ERRIO);
io_pop(0);
sh_exec(t,(int)(st.states&(ERRFLG|MONITOR)));
sh_freeup();
st.iotemp = saviotemp;
st.staklist = saveslp;
}
/*
* Given the name or number of a signal return the signal number
*/
static int sig_number(string)
register char *string;
{
register int n;
if (string == NULL)
return(-1);
if(isdigit(*string))
n = atoi(string);
else
{
ltou(string,string);
n = sh_lookup(string,sig_names);
n &= (1<<SIGBITS)-1;
n--;
}
return(n);
}
#ifdef JOBS
/*
* list all the possible signals
* If flag is 1, then the current trap settings are displayed
*/
static void sig_list(flag)
{
register const struct sysnod *syscan;
register int n = MAXTRAP;
const char *names[MAXTRAP+3];
const char *etrap = gettxt(_SGI_DMMX_e_trap,e_trap);
syscan=sig_names;
p_setout(st.standout);
/* not all signals may be defined */
#ifdef POSIX
if(flag<0)
n += 2;
#else
NOT_USED(flag);
#endif /* POSIX */
while(--n >= 0)
names[n] = etrap;
while(*syscan->sysnam)
{
n = syscan->sysval;
n &= ((1<<SIGBITS)-1);
names[n] = syscan->sysnam;
syscan++;
}
n = MAXTRAP-1;
#ifdef POSIX
if(flag<0)
n += 2;
#endif /* POSIX */
while(names[--n]==etrap);
names[n+1] = NULL;
#ifdef POSIX
if(flag<0)
{
while(--n >= 0)
{
if(st.trapcom[n])
{
p_str(gettxt(_SGI_DMMX_e_trap,e_trap),' ');
p_qstr(st.trapcom[n],' ');
p_str(names[n+1],NL);
}
}
}
else if(flag)
{
if(flag <= n && names[flag])
p_str(names[flag],NL);
else
p_num(flag-1,NL);
}
else
#endif /* POSIX */
p_list(n-1,(char**)(names+2));
}
#endif /* JOBS */
#ifdef SYSSLEEP
/*
* delay execution for time <t>
*/
#ifdef _poll_
# include <poll.h>
#endif /* _poll_ */
#ifndef TIC_SEC
# ifdef HZ
# define TIC_SEC HZ /* number of ticks per second */
# else
# define TIC_SEC 60 /* number of ticks per second */
# endif /* HZ */
#endif /* TIC_SEC */
int sh_delay(t)
double t;
{
register int n = t;
#ifdef _poll_
struct pollfd fd;
if(t<=0)
return;
else if(n > 30)
{
sleep(n);
t -= n;
}
if(n=1000*t)
poll(&fd,0,n);
#else
# ifdef _SELECT5_
struct timeval timeloc;
if(t<=0)
return;
timeloc.tv_sec = n;
timeloc.tv_usec = 1000000*(t-(double)n);
select(0,(fd_set*)0,(fd_set*)0,(fd_set*)0,&timeloc);
# else
# ifdef _SELECT4_
/* for 9th edition machines */
if(t<=0)
return;
if(n > 30)
{
sleep(n);
t -= n;
}
if(n=1000*t)
select(0,(fd_set*)0,(fd_set*)0,n);
# else
struct tms tt;
if(t<=0)
return;
sleep(n);
t -= n;
if(t)
{
clock_t begin = times(&tt);
if(begin==0)
return;
t *= TIC_SEC;
n += (t+.5);
while((times(&tt)-begin) < n);
}
# endif /* _SELECT4_ */
# endif /* _SELECT5_ */
#endif /* _poll_ */
}
#endif /* SYSSLEEP */
#ifdef UNIVERSE
# ifdef _sys_universe_
int univ_number(str)
char *str;
{
register int n = 0;
while( n < NUMUNIV)
{
if(strcmp(str,univ_name[n++])==0)
return(n);
}
return(-1);
}
# endif /* _sys_universe_ */
#endif /* UNIVERSE */
static void
limtail(cp, str0)
char *cp, *str0;
{
register char *str = str0;
while (*cp && *cp == *str)
cp++, str++;
if (*cp)
sh_cfail(gettxt(_SGI_DMMX_e_badscale,e_badscale));
}
static const struct sys2msgnod *
findlim(cp)
char *cp;
{
register const struct sys2msgnod *sp, *res;
res = 0;
for (sp = blimit_names; sp->sysmsgid != NULLSTR; sp++)
if (prefix(cp, sp->sysnam)) {
if (res)
sh_cfail(gettxt(_SGI_DMMX_e_ambiguous,e_ambiguous));
res = sp;
}
if (res)
return (res);
sh_cfail(gettxt(_SGI_DMMX_e_nosuchres,e_nosuchres));
/*NOTREACHED*/
}
static long long
getval(sp, v)
register const struct sys2msgnod *sp;
char **v;
{
register double f;
char *cp = *v++;
extern double atof();
int unit,limit;
limit = sp->sysval>>11;
unit = sp->sysval&0x7ff;
f = atof((const char *)cp);
while (isdigit(*cp) || *cp == '.' ||
*cp == 'e' ||
*cp == 'E' ||
*cp == '-' ||
*cp == '+' )
cp++;
if (*cp == 0) {
if (*v == 0)
return ((long long)(f+0.5) * unit);
cp = *v;
}
switch (*cp) {
case ':':
if (limit != RLIMIT_CPU)
goto badscal;
return ((long long)(f * 60.0 + atof((const char *)cp+1)));
case 'h':
if (limit != RLIMIT_CPU)
goto badscal;
limtail(cp, gettxt(_SGI_DMMX_sc_hours,sc_hours));
f *= 3600.;
break;
case 'm':
if (limit == RLIMIT_CPU) {
limtail(cp, gettxt(_SGI_DMMX_sc_minutes,sc_minutes));
f *= 60.;
break;
}
case 'M':
if (limit == RLIMIT_CPU)
goto badscal;
*cp = 'm';
limtail(cp, gettxt(_SGI_DMMX_sc_megabytes,sc_megabytes));
f *= 1024.*1024.;
break;
case 's':
if (limit != RLIMIT_CPU)
goto badscal;
limtail(cp, gettxt(_SGI_DMMX_sc_seconds,sc_seconds));
break;
case 'k':
if (limit == RLIMIT_CPU)
goto badscal;
limtail(cp, gettxt(_SGI_DMMX_sc_kbytes,sc_kbytes));
f *= 1024;
break;
case 'u':
limtail(cp, gettxt(_SGI_DMMX_e_unlimited,e_unlimited));
return (RLIM64_INFINITY);
default:
badscal:
sh_cfail(gettxt(_SGI_DMMX_e_badscale,e_badscale));
}
return ((long long)(f+0.5));
}
void static
psecs(__int64_t l)
{
register __int64_t i;
i = l / 3600;
if (i) {
p_str(u64tos((unsigned long long)i,10),':');
i = l % 3600;
p_str(u64tos((unsigned long long)(i/60),10),0);
goto minsec;
}
i = l;
p_str(u64tos((unsigned long long)(i/60),10),0);
minsec:
i %= 60;
p_char(':');
p_str(u64tos((unsigned long long)i,10),0);
}
static void
plim(register const struct sys2msgnod *sp, char hard)
{
struct rlimit64 rlim;
rlim64_t limit;
int unit,rlimit;
rlimit = sp->sysval>>11;
unit = sp->sysval&0x7ff;
p_setout(st.standout);
p_str(gettxt(sp->sysmsgid,sp->sysnam),0);
if(getrlimit64(rlimit, &rlim) < 0)
sh_cfail(gettxt(_SGI_DMMX_e_number,e_number));
limit = hard ? rlim.rlim_max : rlim.rlim_cur;
if (limit == RLIM64_INFINITY)
p_str(gettxt(_SGI_DMMX_e_unlimited,e_unlimited),0);
else if (rlimit == RLIMIT_CPU)
psecs(limit);
else {
limit = (limit+unit-1)/unit;
p_str(u64tos((unsigned long long)limit,10),SP);
if(strcmp(sp->sys2msgid,""))
p_str(gettxt(sp->sys2msgid,sp->sys2nam),0);
}
p_char(NL);
}
static
setlim(register const struct sys2msgnod *sp, char hard, rlim64_t limit)
{
struct rlimit64 rlim;
int rlimit;
rlimit = sp->sysval>>11;
if(getrlimit64(rlimit, &rlim) < 0)
sh_cfail(gettxt(_SGI_DMMX_e_number,e_number));
if (hard)
rlim.rlim_max = limit;
else if (limit == RLIM64_INFINITY && geteuid() != 0)
rlim.rlim_cur = rlim.rlim_max;
else
rlim.rlim_cur = limit;
if (setrlimit64(rlimit, &rlim) < 0) {
p_setout(ERRIO);
p_str(gettxt(sp->sysmsgid,sp->sysnam),0);
p_str(gettxt(_SGI_DMMX_e_cant,e_cant),0);
if (limit == RLIM64_INFINITY)
p_str(gettxt(_SGI_DMMX_e_remove,e_remove),0);
else
p_str(gettxt(_SGI_DMMX_e_set,e_set),0);
if (hard)
p_str(gettxt(_SGI_DMMX_e_hard,e_hard),0);
p_str(gettxt(_SGI_DMMX_e_limit,e_limit),NL);
return (-1);
}
return (0);
}
static
prefix(sub, str)
register char *sub, *str;
{
for (;;) {
if (*sub == 0)
return (1);
if (*str == 0)
return (0);
if (*sub++ != *str++)
return (0);
}
}
/* Bourne shell limit() and unlimit()
* builtins added for backward compatability
*/
b_limit(argn,v)
register char **v;
{
const struct sys2msgnod *sp;
register rlim64_t limit;
char hard = 0;
v++;
if (*v && eq(*v, "-h")) {
hard = 1;
v++;
}
if (*v == 0) {
for (sp = blimit_names; sp->sysmsgid != NULLSTR; sp++)
plim(sp, hard);
return(0);
}
sp = findlim(v[0]);
if (v[1] == 0) {
plim(sp, hard);
return(0);
}
limit = getval(sp, v+1);
if (setlim(sp, hard, limit) < 0)
sh_cfail(gettxt(_SGI_DMMX_e_ulimit,e_ulimit));
return(0);
}
b_unlimit(argn,v)
register char **v;
{
const struct sys2msgnod *sp;
int err = 0;
char hard = 0;
v++;
if (*v && eq(*v, "-h")) {
hard = 1;
v++;
}
if (*v == 0) {
for (sp = blimit_names; sp->sysmsgid != NULLSTR ; sp++)
if (setlim(sp, hard, (rlim64_t)RLIM64_INFINITY) < 0)
err++;
if (err)
sh_cfail(gettxt(_SGI_DMMX_e_ulimit,e_ulimit));
return(0);
}
while (*v) {
sp = findlim(*v++);
if (setlim(sp, hard, (rlim64_t)RLIM64_INFINITY) < 0)
sh_cfail(gettxt(_SGI_DMMX_e_ulimit,e_ulimit));
}
return(0);
}