Beispiel #1
0
static int mesg(int  mode)
{
	struct stat statb;
	char *tty = ttyname(2);
	if(!tty)
		tty = ttyname(0);
	if(!tty)
		tty = ttyname(1);
	if(!tty)
		error(ERROR_exit(1),"cannot find terminal");
	if(stat(tty,&statb)<0)
		error(ERROR_system(1),"%s: cannot stat",tty);
	switch(mode)
	{
	    case 'n':
	    case 'y':
		if(mode=='y')
			statb.st_mode |= S_IWGRP;
		else
			statb.st_mode &= ~S_IWGRP;
		if(chmod(tty, statb.st_mode) < 0)
			error(ERROR_system(1),"%s: cannot stat",tty);
		break;
	    case 0:
		sfprintf(sfstdout,"%c\n",(statb.st_mode&S_IWGRP)?'y':'n');
	}
	return((statb.st_mode&S_IWGRP)==0);
}
Beispiel #2
0
int
b_comm(int argc, char *argv[], Shbltin_t* context)
{
	register int mode = C_FILE1|C_FILE2|C_COMMON;
	register char *cp;
	Sfio_t *f1, *f2;

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	for (;;)
	{
		switch (optget(argv, usage))
		{
 		case '1':
			mode &= ~C_FILE1;
			continue;
		case '2':
			mode &= ~C_FILE2;
			continue;
		case '3':
			mode &= ~C_COMMON;
			continue;
		case ':':
			error(2, "%s",opt_info.arg);
			break;
		case '?':
			error(ERROR_usage(2), "%s",opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	argc -= opt_info.index;
	if(error_info.errors || argc!=2)
		error(ERROR_usage(2),"%s",optusage(NiL));
	cp = *argv++;
	if(streq(cp,"-"))
		f1 = sfstdin;
	else if(!(f1 = sfopen(NiL, cp,"r")))
		error(ERROR_system(1),"%s: cannot open",cp);
	cp = *argv;
	if(streq(cp,"-"))
		f2 = sfstdin;
	else if(!(f2 = sfopen(NiL, cp,"r")))
		error(ERROR_system(1),"%s: cannot open",cp);
	if(mode)
	{
		if(comm(f1,f2,sfstdout,mode) < 0)
			error(ERROR_system(1)," write error");
	}
	else if(f1==sfstdin || f2==sfstdin)
		sfseek(sfstdin,(Sfoff_t)0,SEEK_END);
	if(f1!=sfstdin)
		sfclose(f1);
	if(f2!=sfstdin)
		sfclose(f2);
	return error_info.errors;
}
Beispiel #3
0
Datei: args.c Projekt: att/ast
void sh_applyopts(Shell_t *shp, Shopt_t newflags) {
    // Cannot set -n for interactive shells since there is no way out.
    if (sh_isoption(shp, SH_INTERACTIVE)) off_option(&newflags, SH_NOEXEC);
    if (is_option(&newflags, SH_PRIVILEGED)) on_option(&newflags, SH_NOUSRPROFILE);
    int is_privileged = is_option(&newflags, SH_PRIVILEGED) != sh_isoption(shp, SH_PRIVILEGED);
    int is_privileged_off = is_option(&(shp->arg_context)->sh->offoptions, SH_PRIVILEGED);
    if ((!sh_isstate(shp, SH_INIT) && is_privileged) ||
        (sh_isstate(shp, SH_INIT) && is_privileged_off && shp->gd->userid != shp->gd->euserid)) {
        if (!is_option(&newflags, SH_PRIVILEGED)) {
            if (setuid(shp->gd->userid) < 0) {
                error(ERROR_system(0), "setuid(%d) failed", shp->gd->userid);
                return;
            }
            if (setgid(shp->gd->groupid) < 0) {
                error(ERROR_system(0), "setgid(%d) failed", shp->gd->groupid);
                return;
            }
            if (shp->gd->euserid == 0) {
                shp->gd->euserid = shp->gd->userid;
                shp->gd->egroupid = shp->gd->groupid;
            }
        } else if ((shp->gd->userid != shp->gd->euserid && setuid(shp->gd->euserid) < 0) ||
                   (shp->gd->groupid != shp->gd->egroupid && setgid(shp->gd->egroupid) < 0) ||
                   (shp->gd->userid == shp->gd->euserid && shp->gd->groupid == shp->gd->egroupid)) {
            off_option(&newflags, SH_PRIVILEGED);
        }
    }
#if SHOPT_BASH
    on_option(&newflags, SH_CMDHIST);
    on_option(&newflags, SH_CHECKHASH);
    on_option(&newflags, SH_EXECFAIL);
    on_option(&newflags, SH_EXPAND_ALIASES);
    on_option(&newflags, SH_HISTAPPEND);
    on_option(&newflags, SH_INTERACTIVE_COMM);
    on_option(&newflags, SH_LITHIST);
    on_option(&newflags, SH_NOEMPTYCMDCOMPL);

    if (!is_option(&newflags, SH_XPG_ECHO) && sh_isoption(shp, SH_XPG_ECHO)) {
        astconf("UNIVERSE", 0, "ucb");
    }
    if (is_option(&newflags, SH_XPG_ECHO) && !sh_isoption(shp, SH_XPG_ECHO)) {
        astconf("UNIVERSE", 0, "att");
    }
    if (is_option(&newflags, SH_HISTORY2) && !sh_isoption(shp, SH_HISTORY2)) {
        sh_onstate(shp, SH_HISTORY);
        sh_onoption(shp, SH_HISTORY);
    }
    if (!is_option(&newflags, SH_HISTORY2) && sh_isoption(shp, SH_HISTORY2)) {
        sh_offstate(shp, SH_HISTORY);
        sh_offoption(shp, SH_HISTORY);
    }
#endif
    shp->options = newflags;
}
Beispiel #4
0
int
b_mkfifo(int argc, char *argv[], void* context)
{
	register char*	arg;
	register mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
	register mode_t	mask = 0;
	register int	mflag = 0;

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'm':
			mflag = 1;
			mode = strperm(arg = opt_info.arg, &opt_info.arg, mode);
			if (*opt_info.arg)
				error(ERROR_exit(0), "%s: invalid mode", arg);
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			break;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	if (error_info.errors || !*argv)
		error(ERROR_usage(2), "%s", optusage(NiL));
	mask = umask(0);
	if (!mflag)
	{
		mode &= ~mask;
		umask(mask);
		mask = 0;
	}
	while (arg = *argv++)
		if (mkfifo(arg, mode) < 0)
			error(ERROR_system(0), "%s:", arg);
	if (mask)
		umask(mask);
	return error_info.errors != 0;
}
Beispiel #5
0
/*
 * set an alarm for <t> seconds
 */
static double setalarm(register double t)
{
#if defined(_lib_setitimer) && defined(ITIMER_REAL)
	struct itimerval tnew, told;
	tnew.it_value.tv_sec = t;
	tnew.it_value.tv_usec = 1.e6*(t- (double)tnew.it_value.tv_sec);
	if(t && tnew.it_value.tv_sec==0 && tnew.it_value.tv_usec<1000)
		tnew.it_value.tv_usec = 1000;
	tnew.it_interval.tv_sec = 0;
	tnew.it_interval.tv_usec = 0;
	if(setitimer(ITIMER_REAL,&tnew,&told) < 0)
		errormsg(SH_DICT,ERROR_system(1),e_alarm);
	t = told.it_value.tv_sec + 1.e-6*told.it_value.tv_usec;
#else
	unsigned seconds = (unsigned)t;
	if(t && seconds<1)
		seconds=1;
	t = (double)alarm(seconds);
#endif
	return(t);
}
Beispiel #6
0
int
b_paste(int argc, char** argv, Shbltin_t* context)
{
	register int		n, sflag=0;
	register Sfio_t		*fp, **streams;
	register char 		*cp, *delim;
	char			*ep;
	Delim_t			*mp;
	int			dlen, dsiz;
	char			defdelim[2];

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	delim = 0;
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'd':
			delim = opt_info.arg;
			continue;
		case 's':
			sflag++;
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			break;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	if(error_info.errors)
		error(ERROR_usage(2),"%s", optusage(NiL));
	if(!delim || !*delim)
	{
		delim = defdelim;
		delim[0] = '\t';
		delim[1] = 0;
	}
	if (!(delim = strdup(delim)))
		error(ERROR_system(1), "out of space");
	dlen = dsiz = stresc(delim);
	mp = 0;
	if (mbwide())
	{
		cp = delim;
		ep = delim + dlen;
		dlen = 0;
		while (cp < ep)
		{
			mbchar(cp);
			dlen++;
		}
		if(dlen < dsiz)
		{
			if (!(mp = newof(0, Delim_t, dlen, 0)))
			{
				free(delim);
				error(ERROR_system(1), "out of space");
			}
			cp = delim;
			dlen = 0;
			while (cp < ep)
			{
				mp[dlen].chr = cp;
				mbchar(cp);
				mp[dlen].len = cp - mp[dlen].chr;
				dlen++;
			}
		}
	}
	if(cp = *argv)
	{
		n = argc - opt_info.index;
		argv++;
	}
	else
		n = 1;
	if(!sflag)
	{
		if (!(streams = (Sfio_t**)stakalloc(n*sizeof(Sfio_t*))))
			error(ERROR_exit(1), "out of space");
		n = 0;
	}
	do
	{
		if(!cp || streq(cp,"-"))
			fp = sfstdin;
		else if(!(fp = sfopen(NiL,cp,"r")))
			error(ERROR_system(0),"%s: cannot open",cp);
		if(fp && sflag)
		{
			if(spaste(fp,sfstdout,delim,dsiz,dlen,mp) < 0)
				error(ERROR_system(0),"write failed");
			if(fp!=sfstdin)
				sfclose(fp);
		}
		else if(!sflag)
			streams[n++] = fp;
	} while(cp= *argv++);
	if(!sflag)
	{
		if(error_info.errors==0 && paste(n,streams,sfstdout,delim,dsiz,dlen,mp) < 0)
			error(ERROR_system(0),"write failed");
		while(--n>=0)
			if((fp=streams[n]) && fp!=sfstdin)
				sfclose(fp);
	}
	if (mp)
		free(mp);
	free(delim);
	return(error_info.errors);
}
Beispiel #7
0
Datei: pack.c Projekt: DataIX/ast
int
main(int argc, register char *argv[])
{
	static char command[] = "pack";
	register Huff_t	*hp;
	register char	*infile,*outfile;
	Sfio_t		*fpin,*fpout;
	int		nfile=0, npack=0, force=0, verbose=0;
	int		out, deleted, dsize, n;
	struct stat	statb;

	NOT_USED(argc);
	error_info.id = command;
	while(n = optget(argv,usage)) switch(n)
	{
	case 'f':
		force++;
		break;
	case 'v':
		verbose = !verbose;
		break;
	case ':':
		error(2, opt_info.arg);
		break;
	case '?':
		error(ERROR_usage(2), "%s", opt_info.arg);
		break;
	}
	argv += opt_info.index;
	if(error_info.errors || !*argv)
		error(ERROR_usage(2), "%s", optusage((char*)0));

	while (infile = *argv++)
	{
		if(*infile == '-')
		{
			/* awful way to handle options, but preserves SVID */
			switch(infile[1])
			{
				case 'f':
					force++;
					continue;
				case 0:
					verbose = !verbose;
					continue;
			}
		}
		nfile++;
		fpin = fpout = (Sfio_t*)0;
		hp = (Huff_t*)0;
		deleted = 0;
		if(!(outfile = outname(infile)))
			continue;
		if (!(fpin=sfopen((Sfio_t*)0,infile,"r")))
			error(ERROR_system(0), "%s: cannot open", infile);
		else if(fstat(sffileno(fpin),&statb) < 0)
			error(ERROR_system(0), "%s: cannot stat", infile);
		else if(S_ISDIR(statb.st_mode))
			error(2, "%s: cannot pack a directory", infile);
		else if(statb.st_nlink > 1)
			error(2, "%s: has links", infile);
		else if(statb.st_size ==0)
			error(2, "%s: cannot pack a zero length file", infile);
		else if(access(outfile,F_OK) ==0)
			error(ERROR_system(0), "%s: already exists", outfile);
		else if(((out=open(outfile,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,PERM(statb.st_mode))) < 0) ||
			!(fpout = sfnew((Sfio_t*)0,(char*)0,SF_UNBOUND,out,SF_WRITE)))
			error(ERROR_system(0), "%s: cannot create", outfile);
		else if((deleted++,chmod(outfile,statb.st_mode)) < 0)
			error(ERROR_system(0), "%s: cannot change mode to %o",outfile,statb.st_mode);
		else
		{
			chown(outfile,statb.st_uid,statb.st_gid);
			if(!(hp = huffinit(fpin,(Sfoff_t)-1)))
				error(2, "%s: read error", infile);
			else if(sfseek(fpin,(Sfoff_t)0,0) < 0)
				error(ERROR_system(0),"%s: seek error", infile);
			else if((dsize = huffputhdr(hp,fpout)) < 0)
				error(2, "%s: write error", infile);
			else if(!force && block(huffisize(hp)) <= block(huffosize(hp)+dsize))
				error(2, "%s:no savings - file unchanged", infile);
			else if(huffencode(hp,fpin,fpout,SF_UNBOUND)<0)
				error(2, "%s: read error", infile);
			else
			{
				double diff;
				if(remove(infile) < 0)
					error(ERROR_system(0), "%s: cannot remove", infile);
				diff = huffisize(hp) - (dsize+huffosize(hp));
				sfprintf(sfstdout,"%s: %s : %.1f%% Compression\n",command,
					infile,(100*diff)/((double)huffisize(hp)));
				if(verbose)
					vprint(hp,dsize);
				npack++;
				deleted = 0;
			}
		}
		if(hp)
			huffend(hp);
		if(fpin)
			sfclose(fpin);
		if(fpout)
			sfclose(fpout);
		if(deleted)
			remove(outfile);
		if(outfile)
			free(outfile);
	}
	nfile -= npack;
	if(nfile > 125)
		nfile = 125;
	exit(nfile);
}
Beispiel #8
0
int
b_uname(int argc, char** argv, void* context)
{
	register long	flags = 0;
	register int	sep = 0;
	register int	n;
	register char*	s;
	char*		t;
	char*		e;
	char*		sethost = 0;
	int		list = 0;
	struct utsname	ut;
	char		buf[257];

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'a':
			flags |= OPT_all|((1L<<OPT_ALL)-1);
			continue;
		case 'b':
			flags |= OPT_base;
			continue;
		case 'c':
			flags |= OPT_vendor;
			continue;
		case 'd':
			flags |= OPT_domain;
			continue;
		case 'f':
			list = 1;
			continue;
		case 'h':
			flags |= OPT_hostid;
			continue;
		case 'i':
			flags |= OPT_implementation;
			continue;
		case 'm':
			flags |= OPT_machine;
			continue;
		case 'n':
			flags |= OPT_nodename;
			continue;
		case 'o':
			flags |= OPT_operating_system;
			continue;
		case 'p':
			flags |= OPT_processor;
			continue;
		case 'r':
			flags |= OPT_release;
			continue;
		case 's':
			flags |= OPT_system;
			continue;
		case 't':
			flags |= OPT_machine_type;
			continue;
		case 'v':
			flags |= OPT_version;
			continue;
		case 'x':
			flags |= OPT_extra;
			continue;
		case 'A':
			flags |= OPT_total|((1L<<OPT_TOTAL)-1);
			continue;
		case 'R':
			flags |= OPT_extended_release;
			continue;
		case 'S':
			sethost = opt_info.arg;
			continue;
		case ':':
			s = "/usr/bin/uname";
			if (!streq(argv[0], s) && (!eaccess(s, X_OK) || !eaccess(s+=4, X_OK)))
			{
				argv[0] = s;
				return sh_run(context, argc, argv);
			}
			error(2, "%s", opt_info.arg);
			break;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	if (error_info.errors || *argv && (flags || sethost) || sethost && flags)
		error(ERROR_usage(2), "%s", optusage(NiL));
	if (sethost)
	{
#if _lib_sethostname
		if (sethostname(sethost, strlen(sethost) + 1))
#else
#ifdef	ENOSYS
		errno = ENOSYS;
#else
		errno = EPERM;
#endif
#endif
		error(ERROR_system(1), "%s: cannot set host name", sethost);
	}
	else if (list)
		astconflist(sfstdout, NiL, ASTCONF_base|ASTCONF_defined|ASTCONF_lower|ASTCONF_quote|ASTCONF_matchcall, "CS|SI");
	else if (*argv)
	{
		e = &buf[sizeof(buf)-1];
		while (s = *argv++)
		{
			t = buf;
			*t++ = 'C';
			*t++ = 'S';
			*t++ = '_';
			while (t < e && (n = *s++))
				*t++ = islower(n) ? toupper(n) : n;
			*t = 0;
			sfprintf(sfstdout, "%s%c", *(t = astconf(buf, NiL, NiL)) ? t : *(t = astconf(buf+3, NiL, NiL)) ? t :  "unknown", *argv ? ' ' : '\n');
		}
	}
	else
	{
		s = buf;
		if (!flags)
			flags = OPT_system;
		memzero(&ut, sizeof(ut));
		if (uname(&ut) < 0)
			error(ERROR_usage(2), "information unavailable");
		output(OPT_system, ut.sysname, "sysname");
		if (flags & OPT_nodename)
		{
#if !_mem_nodeext_utsname && _lib_gethostname
			if (sizeof(ut.nodename) > 9 || gethostname(s, sizeof(buf)))
#endif
			s = ut.nodename;
			output(OPT_nodename, s, "nodename");
		}
		output(OPT_release, ut.release, "release");
		output(OPT_version, ut.version, "version");
		output(OPT_machine, ut.machine, "machine");
		if (flags & OPT_processor)
		{
			if (!*(s = astconf("ARCHITECTURE", NiL, NiL)))
				s = ut.machine;
			output(OPT_processor, s, "processor");
		}
		if (flags & OPT_implementation)
		{
			if (!*(s = astconf("PLATFORM", NiL, NiL)) && !*(s = astconf("HW_NAME", NiL, NiL)))
			{
				if (t = strchr(hosttype, '.'))
					t++;
				else
					t = (char*)hosttype;
				strncpy(s = buf, t, sizeof(buf) - 1);
			}
			output(OPT_implementation, s, "implementation");
		}
		if (flags & OPT_operating_system)
		{
			s = astconf("OPERATING_SYSTEM", NiL, NiL);
			if (!*s)
#ifdef _UNAME_os_DEFAULT
				s = _UNAME_os_DEFAULT;
#else
				s = ut.sysname;
#endif
			output(OPT_operating_system, s, "operating-system");
		}
		if (flags & OPT_extended_release)
		{
			s = astconf("RELEASE", NiL, NiL);
			output(OPT_extended_release, s, "extended-release");
		}
#if _mem_idnumber_utsname
		output(OPT_hostid, ut.idnumber, "hostid");
#else
		if (flags & OPT_hostid)
		{
			if (!*(s = astconf("HW_SERIAL", NiL, NiL)))
#if _lib_gethostid
				sfsprintf(s = buf, sizeof(buf), "%08x", gethostid());
#else
				/*NOP*/;
#endif
			output(OPT_hostid, s, "hostid");
		}
#endif
		if (flags & OPT_vendor)
		{
			s = astconf("HW_PROVIDER", NiL, NiL);
			output(OPT_vendor, s, "vendor");
		}
		if (flags & OPT_domain)
		{
			if (!*(s = astconf("SRPC_DOMAIN", NiL, NiL)))
#if _lib_getdomainname
				getdomainname(s, sizeof(buf));
#else
				/*NOP*/;
#endif
			output(OPT_domain, s, "domain");
		}
#if _mem_m_type_utsname
		s = ut.m_type;
#else
		s = astconf("MACHINE", NiL, NiL);
#endif
		output(OPT_machine_type, s, "m_type");
#if _mem_base_rel_utsname
		s = ut.base_rel;
#else
		s = astconf("BASE", NiL, NiL);
#endif
		output(OPT_base, s, "base_rel");
		if (flags & OPT_extra)
		{
			char*	last = (char*)&ut;

			extra(sysname);
			extra(nodename);
			extra(release);
			extra(version);
			extra(machine);
#if _mem_idnumber_utsname
			extra(idnumber);
#endif
#if _mem_m_type_utsname
			extra(m_type);
#endif
#if _mem_base_rel_utsname
			extra(base_rel);
#endif
			if (last < ((char*)(&ut + 1)))
			{
				s = t = last;
				while (s < (char*)(&ut + 1))
				{
					if (!(n = *s++))
					{
						if ((s - t) > 1)
						{
							if (sep)
								sfputc(sfstdout, ' ');
							else
								sep = 1;
							sfputr(sfstdout, t, -1);
						}
						t = s;
					}
					else if (!isprint(n))
						break;
				}
			}
		}
		if (sep)
			sfputc(sfstdout, '\n');
	}
	return error_info.errors;
}
Beispiel #9
0
int
b_date(int argc, register char** argv, void* context)
{
	register int	n;
	register char*	s;
	register Fmt_t*	f;
	char*		t;
	unsigned long	u;
	Time_t		now;
	Time_t		ts;
	Time_t		te;
	Time_t		e;
	char		buf[1024];
	Fmt_t*		fmts;
	Fmt_t		fmt;
	struct stat	st;

	char*		cmd = argv[0];	/* original command path	*/
	char*		format = 0;	/* tmxfmt() format		*/
	char*		string = 0;	/* date string			*/
	int		elapsed = 0;	/* args are start/stop pairs	*/
	int		filetime = 0;	/* use this st_ time field	*/
	int		increment = 0;	/* incrementally adjust time	*/
	int		last = 0;	/* display the last time arg	*/
	Tm_zone_t*	listzones = 0;	/* known time zone table	*/
	int		network = 0;	/* don't set network time	*/
	int		show = 0;	/* show date and don't set	*/
	int		unelapsed = 0;	/* fmtelapsed() => strelapsed	*/

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	tm_info.flags = TM_DATESTYLE;
	fmts = &fmt;
	fmt.format = "";
	fmt.next = 0;
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'a':
		case 'c':
		case 'm':
			filetime = opt_info.option[1];
			continue;
		case 'd':
			string = opt_info.arg;
			show = 1;
			continue;
		case 'e':
			format = "%#";
			continue;
		case 'E':
			elapsed = 1;
			continue;
		case 'f':
			format = opt_info.arg;
			continue;
		case 'i':
			increment = 1;
			continue;
		case 'l':
			tm_info.flags |= TM_LEAP;
			continue;
		case 'L':
			last = 1;
			continue;
		case 'n':
			network = 1;
			continue;
		case 'p':
			if (!(f = newof(0, Fmt_t, 1, 0)))
				error(ERROR_SYSTEM|3, "out of space [format]");
			f->next = fmts;
			f->format = opt_info.arg;
			fmts = f;
			continue;
		case 's':
			show = 1;
			continue;
		case 'u':
			tm_info.flags |= TM_UTC;
			continue;
		case 'U':
			unelapsed = (int)opt_info.num;
			continue;
		case 'z':
			listzones = tm_data.zone;
			continue;
		case '?':
			error(ERROR_USAGE|4, "%s", opt_info.arg);
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			continue;
		}
		break;
	}
	argv += opt_info.index;
	if (error_info.errors)
		error(ERROR_USAGE|4, "%s", optusage(NiL));
	now = tmxgettime();
	if (listzones)
	{
		s = "-";
		while (listzones->standard)
		{
			if (listzones->type)
				s = listzones->type;
			sfprintf(sfstdout, "%3s %4s %4s %4d %4d\n", s, *listzones->standard ? listzones->standard : "-", listzones->daylight ? listzones->daylight : "-", listzones->west, listzones->dst);
			listzones++;
			show = 1;
		}
	}
	else if (elapsed)
	{
		e = 0;
		while (s = *argv++)
		{
			if (!(t = *argv++))
			{
				argv--;
				t = "now";
			}
			ts = convert(fmts, s, now);
			te = convert(fmts, t, now);
			if (te > ts)
				e += te - ts;
			else
				e += ts - te;
		}
		sfputr(sfstdout, fmtelapsed((unsigned long)tmxsec(e), 1), '\n');
		show = 1;
	}
	else if (unelapsed)
	{
		while (s = *argv++)
		{
			u = strelapsed(s, &t, unelapsed);
			if (*t)
				error(3, "%s: invalid elapsed time", s);
			sfprintf(sfstdout, "%lu\n", u);
		}
		show = 1;
	}
	else if (filetime)
	{
		if (!*argv)
			error(ERROR_USAGE|4, "%s", optusage(NiL));
		n = argv[1] != 0;
		while (s = *argv++)
		{
			if (stat(s, &st))
				error(2, "%s: not found", s);
			else
			{
				switch (filetime)
				{
				case 'a':
					now = tmxgetatime(&st);
					break;
				case 'c':
					now = tmxgetctime(&st);
					break;
				default:
					now = tmxgetmtime(&st);
					break;
				}
				tmxfmt(buf, sizeof(buf), format, now);
				if (n)
					sfprintf(sfstdout, "%s: %s\n", s, buf);
				else
					sfprintf(sfstdout, "%s\n", buf);
				show = 1;
			}
		}
	}
	else
	{
		if ((s = *argv) && !format && *s == '+')
		{
			format = s + 1;
			argv++;
			s = *argv;
		}
		if (s || (s = string))
		{
			if (*argv && string)
				error(ERROR_USAGE|4, "%s", optusage(NiL));
			now = convert(fmts, s, now);
			if (*argv && (s = *++argv))
			{
				show = 1;
				do
				{
					if (!last)
					{
						tmxfmt(buf, sizeof(buf), format, now);
						sfprintf(sfstdout, "%s\n", buf);
					}
					now = convert(fmts, s, now);
				} while (s = *++argv);
			}
		}
		else
			show = 1;
		if (format || show)
		{
			tmxfmt(buf, sizeof(buf), format, now);
			sfprintf(sfstdout, "%s\n", buf);
		}
		else if (settime(context, cmd, now, increment, network))
			error(ERROR_SYSTEM|3, "cannot set system time");
	}
	while (fmts != &fmt)
	{
		f = fmts;
		fmts = fmts->next;
		free(f);
	}
	tm_info.flags = 0;
	if (show && sfsync(sfstdout))
		error(ERROR_system(0), "write error");
	return error_info.errors != 0;
}
Beispiel #10
0
int
b_stty(int argc, char** argv, Shbltin_t* context)
{
	struct termios		tty;
	register int		n;
	register int		flags = 0;
	int			fd = 0;
	const Tty_t*		tp;
	Optdisc_t		disc;

	cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_INTERACTIVE);
	memset(&disc, 0, sizeof(disc));
	disc.version = OPT_VERSION;
	disc.infof = infof;
	opt_info.disc = &disc;
	for (;;)
	{
		switch (n = optget(argv, usage))
		{
		case 'f':
			fd = (int)opt_info.num;
			continue;
		case 'a':
		case 'g':
		case 't':
			if (!opt_info.offset || !argv[opt_info.index][opt_info.offset])
			{
				switch (n)
				{
				case 'a':
					flags |= A_FLAG;
					break;
				case 'g':
					flags |= G_FLAG;
					break;
				case 't':
					flags |= T_FLAG;
					break;
				}
				continue;
			}
			/*FALLTHROUGH*/
		case ':':
			if (!opt_info.offset)
				error(2, "%s", opt_info.arg);
			else if (!(tp = lookup(argv[opt_info.index]+1)) || (tp->type != BIT && tp->type != TABS))
				error(ERROR_exit(1), "%s: unknown mode", argv[opt_info.index]);
			break;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	if (error_info.errors || (flags && *argv) || (flags&(flags-1)))
		error(ERROR_usage(2), "%s", optusage(NiL));
	if (tcgetattr(fd, &tty) < 0)
		error(ERROR_system(1), "not a tty");
	if (flags & T_FLAG)
		sfprintf(sfstdout, "%d\n", tcgetpgrp(0));
	else if (*argv)
	{
		if (!argv[1] && **argv == ':')
			gin(*argv, &tty);
		else
			set(argv, &tty);
		if (tcsetattr(0, TCSANOW, &tty) < 0)
			error(ERROR_system(1), "cannot set tty");
	}
	else
		output(&tty, flags);
	return error_info.errors;
}
Beispiel #11
0
int main(int argc, char *argv[])
{
	Sfio_t *in, *out;
	Shell_t	*shp;
	Namval_t *np;
	Shnode_t *t;
	char *cp;
	int n, nflag=0, vflag=0, dflag=0;
	error_info.id = argv[0];
	while(n = optget(argv, usage )) switch(n)
	{
	    case 'D':
		dflag=1;
		break;
	    case 'v':
		vflag=1;
		break;
	    case 'n':
		nflag=1;
		break;
	    case ':':
		errormsg(SH_DICT,2,"%s",opt_info.arg);
		break;
	    case '?':
		errormsg(SH_DICT,ERROR_usage(2),"%s",opt_info.arg);
		break;
	}
	shp = sh_init(argc,argv,(Shinit_f)0);
	shp->shcomp = 1;
	argv += opt_info.index;
	argc -= opt_info.index;
	if(error_info.errors || argc>2)
		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
	if(cp= *argv)
	{
		argv++;
		in = sh_pathopen(cp);
	}
	else
		in = sfstdin;
	if(cp= *argv)
	{
		struct stat statb;
		if(!(out = sfopen((Sfio_t*)0,cp,"w")))
			errormsg(SH_DICT,ERROR_system(1),"%s: cannot create",cp);
		if(fstat(sffileno(out),&statb) >=0)
			chmod(cp,(statb.st_mode&~S_IFMT)|S_IXUSR|S_IXGRP|S_IXOTH);
	}
	else
		out = sfstdout;
	if(dflag)
	{
		sh_onoption(SH_DICTIONARY);
		sh_onoption(SH_NOEXEC);
	}
	if(nflag)
		sh_onoption(SH_NOEXEC);
	if(vflag)
		sh_onoption(SH_VERBOSE);
	if(!dflag)
		sfwrite(out,header,sizeof(header));
	shp->inlineno = 1;
#if SHOPT_BRACEPAT
        sh_onoption(SH_BRACEEXPAND);
#endif
	while(1)
	{
		stakset((char*)0,0);
		if(t = (Shnode_t*)sh_parse(shp,in,0))
		{
			if((t->tre.tretyp&(COMMSK|COMSCAN))==0 && t->com.comnamp && strcmp(nv_name((Namval_t*)t->com.comnamp),"alias")==0)
				sh_exec(t,0);
			if(!dflag && sh_tdump(out,t) < 0)
				errormsg(SH_DICT,ERROR_exit(1),"dump failed");
		}
		else if(sfeof(in))
			break;
		if(sferror(in))
			errormsg(SH_DICT,ERROR_system(1),"I/O error");
		if(t && ((t->tre.tretyp&COMMSK)==TCOM) && (np=t->com.comnamp) && (cp=nv_name(np)))
		{
			if(strcmp(cp,"exit")==0)
				break;
			/* check for exec of a command */
			if(strcmp(cp,"exec")==0)
			{
				if(t->com.comtyp&COMSCAN)
				{
					if(t->com.comarg->argnxt.ap)
						break;
				}
				else
				{
					struct dolnod *ap = (struct dolnod*)t->com.comarg;
					if(ap->dolnum>1)
						break;
				}
			}
		}
	}
	/* copy any remaining input */
	sfmove(in,out,SF_UNBOUND,-1);
	if(in!=sfstdin)
		sfclose(in);
	if(out!=sfstdout)
		sfclose(out);
	return(0);
}
Beispiel #12
0
main(int argc, char *argv[])
{
	register int n;
	register char *cp;
	Sfio_t *in, *out;

	error_info.id = argv[0];
	NoP(id[0]);
#if _AST_VERSION >= 20060701L
	cmdinit(argc, argv,0, NULL, 0);
#else
	cmdinit(argv,0, NULL, 0);
#endif
	while (n = optget(argv, " [file ...]")) switch (n)
	{
	    case ':':
		error(2, opt_info.arg);
		break;
	    case '?':
		error(ERROR_usage(2), opt_info.arg);
		break;
	}
	argv += opt_info.index;
	if(error_info.errors)
		error(ERROR_usage(2),optusage((char*)0));
	if(cp = *argv)
		argv++;
	do
	{
                if(!cp || strcmp(cp,"-")==0)
		{
                        in = sfstdin;
			out = sfstdout;
		}
		else
		{
			if(!(in = sfopen((Sfio_t*)0,cp,"rb")))
			{
				error(ERROR_system(0),"%s: cannot open for input",cp);
				error_info.errors = 1;
				continue;
			}

			if(!(out = sfopen((Sfio_t*)0,cp,"r+b")))
			{
				error(ERROR_system(0),"%s: cannot open for writing",cp);
				error_info.errors = 1;
				continue;
			}
		}
		nocrnl(in,out);
		if(in!=sfstdin)
			sfclose(in);
		if(out!=sfstdout)
		{
			sfsync(out);
			ftruncate(sffileno(out),sftell(out));
			sfclose(out);
		}
	}
	while(cp= *argv++);
	return(error_info.errors);
}
Beispiel #13
0
int
b_fmt(int argc, char** argv, void *context)
{
	register int	n;
	char*		cp;
	Fmt_t		fmt;
	char		outbuf[8 * 1024];

	fmt.flags = 0;
	fmt.out = sfstdout;
	fmt.outbuf = outbuf;
	fmt.outp = 0;
	fmt.endbuf = &outbuf[72];
	fmt.indent = 0;
	fmt.nextdent = 0;
	fmt.nwords = 0;
	fmt.prefix = 0;
	fmt.quote = 0;
	fmt.retain = 0;
	fmt.section = 1;
	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	for (;;)
	{
		switch (n = optget(argv, usage))
		{
		case 'c':
		case 'o':
		case 's':
		case 'u':
			setoption(&fmt, n);
			continue;
		case 'w':
			if (opt_info.num < TABSZ || opt_info.num>= sizeof(outbuf))
				error(2, "width out of range");
			fmt.endbuf = &outbuf[opt_info.num];
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			break;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	if (error_info.errors)
		error(ERROR_usage(2), "%s", optusage(NiL));
	if (isoption(&fmt, 'o'))
		setoption(&fmt, 'c');
	if (isoption(&fmt, 's'))
		clroption(&fmt, 'u');
	if (cp = *argv)
		argv++;
	do {
		if (!cp || streq(cp, "-"))
			fmt.in = sfstdin;
		else if (!(fmt.in = sfopen(NiL, cp, "r")))
		{
			error(ERROR_system(0), "%s: cannot open", cp);
			error_info.errors = 1;
			continue;
		}
		dofmt(&fmt);
		if (fmt.in != sfstdin)
			sfclose(fmt.in);
	} while (cp = *argv++);
	outline(&fmt);
	if (sfsync(sfstdout))
		error(ERROR_system(0), "write error");
	return error_info.errors != 0;
}
Beispiel #14
0
int    b_print(int argc, char *argv[], Shbltin_t *context)
{
	register Sfio_t *outfile;
	register int exitval=0,n, fd = 1;
	register Shell_t *shp = context->shp;
	const char *options, *msg = e_file+4;
	char *format = 0, *fmttype=0;
	int sflag = 0, nflag=0, rflag=0, vflag=0;
	Namval_t *vname=0;
	Optdisc_t disc;
	disc.version = OPT_VERSION;
	disc.infof = infof;
	opt_info.disc = &disc;
	if(argc>0)
	{
		options = sh_optprint;
		nflag = rflag = 0;
		format = 0;
	}
	else
	{
		struct print *pp = (struct print*)context;
		shp = pp->sh;
		options = pp->options;
		if(argc==0)
		{
			nflag = pp->echon;
			rflag = pp->raw;
			argv++;
			goto skip;
		}
	}
	while((n = optget(argv,options))) switch(n)
	{
		case 'n':
			nflag++;
			break;
		case 'p':
			fd = shp->coutpipe;
			msg = e_query;
			break;
		case 'f':
			format = opt_info.arg;
			break;
		case 's':
			/* print to history file */
			if(!sh_histinit((void*)shp))
				errormsg(SH_DICT,ERROR_system(1),e_history);
			fd = sffileno(shp->gd->hist_ptr->histfp);
			sh_onstate(shp,SH_HISTORY);
			sflag++;
			break;
		case 'e':
			rflag = 0;
			break;
		case 'r':
			rflag = 1;
			break;
		case 'u':
			if(opt_info.arg[0]=='p' && opt_info.arg[1]==0)
			{
				fd = shp->coutpipe;
				msg = e_query;
				break;
			}
			fd = (int)strtol(opt_info.arg,&opt_info.arg,10);
			if(*opt_info.arg)
				fd = -1;
			else if(!sh_iovalidfd(shp,fd))
				fd = -1;
			else if(!(shp->inuse_bits&(1<<fd)) && (sh_inuse(shp,fd) || (shp->gd->hist_ptr && fd==sffileno(shp->gd->hist_ptr->histfp))))

				fd = -1;
			break;
		case 'j':
			fmttype = "json";
		case 'v':
			if(argc < 0)
			{
				if(!(vname = nv_open(opt_info.arg, shp->var_tree,NV_VARNAME|NV_NOARRAY)))
					errormsg(SH_DICT,2, "Cannot create variable %s", opt_info.arg);
			}
			else
				vflag='v';
			break;
		case 'C':
			vflag='C';
			break;
		case ':':
			/* The following is for backward compatibility */
#if OPT_VERSION >= 19990123
			if(strcmp(opt_info.name,"-R")==0)
#else
			if(strcmp(opt_info.option,"-R")==0)
#endif
			{
				rflag = 1;
				if(error_info.errors==0)
				{
					argv += opt_info.index+1;
					/* special case test for -Rn */
					if(strchr(argv[-1],'n'))
						nflag++;
					if(*argv && strcmp(*argv,"-n")==0)
					{

						nflag++;
						argv++;
					}
					goto skip2;
				}
			}
			else
				errormsg(SH_DICT,2, "%s", opt_info.arg);
			break;
		case '?':
			errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
			break;
	}
	argv += opt_info.index;
	if(error_info.errors || (argc<0 && !(format = *argv++)))
		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
	if(vflag && format)
		errormsg(SH_DICT,ERROR_usage(2),"-%c and -f are mutually exclusive",vflag);
skip:
	if(format)
		format = genformat(shp,format);
	/* handle special case of '-' operand for print */
	if(argc>0 && *argv && strcmp(*argv,"-")==0 && strcmp(argv[-1],"--"))
		argv++;
	if(vname)
	{
		if(!shp->strbuf2)
			shp->strbuf2 = sfstropen();
		outfile = shp->strbuf2;
		goto printv;
	}
skip2:
	if(fd < 0)
	{
		errno = EBADF;
		n = 0;
	}
	else if(!(n=shp->fdstatus[fd]))
		n = sh_iocheckfd(shp,fd,fd);
	if(!(n&IOWRITE))
	{
		/* don't print error message for stdout for compatibility */
		if(fd==1)
			return(1);
		errormsg(SH_DICT,ERROR_system(1),msg);
	}
	if(!(outfile=shp->sftable[fd]))
	{
		sh_onstate(shp,SH_NOTRACK);
		n = SF_WRITE|((n&IOREAD)?SF_READ:0);
		shp->sftable[fd] = outfile = sfnew(NIL(Sfio_t*),shp->outbuff,IOBSIZE,fd,n);
		sh_offstate(shp,SH_NOTRACK);
		sfpool(outfile,shp->outpool,SF_WRITE);
	}
Beispiel #15
0
Datei: args.c Projekt: att/ast
// This routine turns options on and off.
// The options "PDicr" are illegal from set command.
// The -o option is used to set option by name.
// This routine returns the number of non-option arguments.
int sh_argopts(int argc, char *argv[], void *context) {
    Shell_t *shp = context;
    int n, o;
    Arg_t *ap = shp->arg_context;
    Lex_t *lp = shp->lex_context;
    Shopt_t newflags;
    int setflag = 0, action = 0, trace = (int)sh_isoption(shp, SH_XTRACE);
    Namval_t *np = NULL;
    const char *sp;
    char *keylist = NULL;
    int verbose, f, unsetnp = 0;
    Optdisc_t disc;

    newflags = shp->options;
    memset(&disc, 0, sizeof(disc));
    disc.version = OPT_VERSION;
    disc.infof = infof;
    opt_info.disc = &disc;

    if (argc > 0) {
        setflag = 4;
    } else {
        argc = -argc;
    }

    while ((n = optget(argv, setflag ? sh_optset : sh_optksh))) {
        o = 0;
        f = *opt_info.option == '-' && (opt_info.num || opt_info.arg);
        switch (n) {
            case 'A': {
                np = nv_open(opt_info.arg, shp->var_tree, NV_ARRAY | NV_VARNAME);
                if (f) unsetnp = 1;
                continue;
            }
            case 'K': {
                keylist = opt_info.arg;
                continue;
            }
#if SHOPT_BASH
            case 'O': {  // shopt options, only in bash mode
                if (!sh_isoption(shp, SH_BASH)) {
                    errormsg(SH_DICT, ERROR_exit(1), e_option, opt_info.name);
                    __builtin_unreachable();
                }
            }
#endif
            // FALLTHRU
            case 'o': {  // set options
            byname:
                if (!opt_info.arg || !*opt_info.arg || *opt_info.arg == '-') {
                    action = PRINT;
                    // print style: -O => shopt options.
                    // bash => print unset options also, no heading.
                    verbose = (f ? PRINT_VERBOSE : PRINT_NO_HEADER) | (n == 'O' ? PRINT_SHOPT : 0) |
                              (sh_isoption(shp, SH_BASH) ? PRINT_ALL | PRINT_NO_HEADER : 0) |
                              ((opt_info.arg && (!*opt_info.arg || *opt_info.arg == '-'))
                                   ? (PRINT_TABLE | PRINT_NO_HEADER)
                                   : 0);
                    continue;
                }
                o = sh_lookopt(opt_info.arg, &f);
                if (o <= 0 || (!sh_isoption(shp, SH_BASH) && (o & SH_BASHEXTRA)) ||
                    ((!sh_isoption(shp, SH_BASH) || n == 'o') && (o & SH_BASHOPT))

                    || (setflag && (o & SH_COMMANDLINE))) {
                    errormsg(SH_DICT, 2, e_option, opt_info.arg);
                    error_info.errors++;
                }
                o &= 0xff;
                if (sh_isoption(shp, SH_RESTRICTED) && !f && o == SH_RESTRICTED) {
                    errormsg(SH_DICT, ERROR_exit(1), e_restricted, opt_info.arg);
                    __builtin_unreachable();
                }
                break;
            }
#if SHOPT_BASH
            case -1: {  // --rcfile
                shp->gd->rcfile = opt_info.arg;
                continue;
            }
            case -2: {  // --noediting
                if (!f) {
                    off_option(&newflags, SH_VI);
                    off_option(&newflags, SH_EMACS);
                    off_option(&newflags, SH_GMACS);
                }
                continue;
            }
            case -3: {  // --profile
                n = 'l';
                sp = strchr(optksh, n);
                if (sp) o = flagval[sp - optksh];
                break;
            }
            case -4: {  // --posix
                // Mask lower 8 bits to find char in optksh string.
                n &= 0xff;
                sp = strchr(optksh, n);
                if (sp) o = flagval[sp - optksh];
                break;
            }
            case -5: {  // --version
                sfputr(sfstdout, "ksh bash emulation, version ", -1);
                np = nv_open("BASH_VERSION", shp->var_tree, 0);
                sfputr(sfstdout, nv_getval(np), -1);
                np = nv_open("MACHTYPE", shp->var_tree, 0);
                sfprintf(sfstdout, " (%s)\n", nv_getval(np));
                sh_exit(shp, 0);
            }
#endif
            case -6: {  // --default
                const Shtable_t *tp;
                for (tp = shtab_options; (o = tp->sh_number); tp++) {
                    if (!(o & SH_COMMANDLINE) && is_option(&newflags, o & 0xff)) {
                        off_option(&newflags, o & 0xff);
                    }
                }
                continue;
            }
            case -7: {
                f = 0;
                goto byname;
            }
            case 'D': {
                on_option(&newflags, SH_NOEXEC);
                // Cppcheck doesn't recognize the "goto" in the preceding case and thus thinks we
                // might fall through and call strchr() with n == -7.  Even though this it
                // technically a bug in cppcheck it is one reason why `goto` shouldn't be used; at
                // least inside `switch` blocks.
                // cppcheck-suppress invalidFunctionArg
                sp = strchr(optksh, n);
                if (sp) o = flagval[sp - optksh];
                break;
            }
            case 'T': {
                if (opt_info.num) {
                    shp->test |= opt_info.num;
                } else {
                    shp->test = 0;
                }
                continue;
            }
            case 's': {
                if (setflag) {
                    action = SORT;
                    continue;
                }
                sp = strchr(optksh, n);
                if (sp) o = flagval[sp - optksh];
                break;
            }
            case 'R': {
                if (setflag) {
                    n = ':';
                } else {
                    ap->kiafile = opt_info.arg;
                    n = 'n';
                }
                sp = strchr(optksh, n);
                if (sp) o = flagval[sp - optksh];
                break;
            }
            case ':': {
                if (opt_info.name[0] == '-' && opt_info.name[1] == '-') {
                    opt_info.arg = argv[opt_info.index - 1] + 2;
                    f = 1;
                    goto byname;
                }
                errormsg(SH_DICT, 2, "%s", opt_info.arg);
                continue;
            }
            case '?': {
                errormsg(SH_DICT, ERROR_usage(0), "%s", opt_info.arg);
                return -1;
            }
            default: {
                sp = strchr(optksh, n);
                if (sp) o = flagval[sp - optksh];
                break;
            }
        }
        if (f) {
            if (o == SH_VI || o == SH_EMACS || o == SH_GMACS) {
                off_option(&newflags, SH_VI);
                off_option(&newflags, SH_EMACS);
                off_option(&newflags, SH_GMACS);
            }
            on_option(&newflags, o);
            off_option(&shp->offoptions, o);
        } else {
            if (o == SH_RESTRICTED && sh_isoption(shp, SH_RESTRICTED)) {
                errormsg(SH_DICT, ERROR_exit(1), e_restricted, "r");
                __builtin_unreachable();
            }
            if (o == SH_XTRACE) trace = 0;
            off_option(&newflags, o);
            if (setflag == 0) on_option(&shp->offoptions, o);
        }
    }
    if (error_info.errors) {
        errormsg(SH_DICT, ERROR_usage(2), "%s", optusage(NULL));
        __builtin_unreachable();
    }
    // Check for '-' or '+' argument.
    sp = argv[opt_info.index];
    if (sp && sp[1] == 0 && (*sp == '+' || *sp == '-') && strcmp(argv[opt_info.index - 1], "--")) {
        opt_info.index++;
        off_option(&newflags, SH_XTRACE);
        off_option(&newflags, SH_VERBOSE);
        trace = 0;
    }
    if (trace) sh_trace(shp, argv, 1);
    argc -= opt_info.index;
    argv += opt_info.index;
    if (action == PRINT) sh_printopts(shp, newflags, verbose, 0);
    if (setflag) {
        if (action == SORT) {
            int (*sortfn)(const char *, const char *) = strcoll;
            Namarr_t *arp;
            struct Value *args;
            unsigned char *bits;
            if (argc > 0) {
                strsort(argv, argc, sortfn);
            } else if (np && (arp = nv_arrayptr(np)) && (args = nv_aivec(np, &bits))) {
                char *cp;
                int i, c, keys = 0;

                if (keylist) {
                    for (cp = keylist; (c = *cp); cp++) {
                        if (c == ',') keys++;
                    }
                    keys++;
                } else {
                    keylist = "";
                }
                arp->nelem = nv_aipack(arp);
                cp = nv_name(np);
                c = strlen(cp);
                // This used to multiply by `(keys - 1)` but `keys` can be zero which means the
                // nodesize can be less than `sizeof(struct Node)` which is obviously wrong.
                // Whether multiplying by `keys` is correct is unclear.
                // See issue #824.
                size_t nodesize = sizeof(struct Node) + keys * sizeof(Namval_t *);
                struct Sort *sp =
                    malloc(sizeof(struct Sort) + strlen(keylist) + (sizeof(char *) + 1) * keys +
                           (arp->nelem + 1) * (nodesize + sizeof(void *)) + c + 3);
                sp->shp = shp;
                sp->np = np;
                if (!(sp->root = shp->last_root)) sp->root = shp->var_tree;
                sp->vp = args;
                sp->cur = 0;
                sp->nodes = (struct Node *)&sp->keys[keys + 2];
                memset(sp->nodes, 0, arp->nelem * nodesize);
                sp->nptrs = (struct Node **)((char *)sp->nodes + arp->nelem * nodesize);
                sp->flags = (char *)&sp->nptrs[arp->nelem + 1];
                memset(sp->flags, 0, keys + 1);
                sp->name = sp->flags + keys + 1;
                memcpy(sp->name, cp, c + 1);
                sp->keys[0] = sp->name + c + 1;
                strcpy(sp->keys[0], keylist);
                cp = (char *)sp->nodes;
                for (c = 0; c < arp->nelem; c++) {
                    if (*keylist && *keylist != ':') {
                        struct Namval *np = FETCH_VT(args[c], np);
                        ((struct Node *)cp)->index = strtol(np->nvname, NULL, 10);
                        ((struct Node *)cp)->bits = bits[c];
                    } else {
                        ((struct Node *)cp)->index = c;
                    }
                    ((struct Node *)cp)->vp = args[c];
                    sp->nptrs[c] = (struct Node *)cp;
                    cp += nodesize;
                }
                if (!(cp = sp->keys[0])) cp = keylist;
                for (keys = 0; (c = *cp); cp++) {
                    if (c == ',') {
                        *cp++ = 0;
                        sp->keys[++keys] = cp;
                        sp->flags[keys] = 0;
                    } else if (c == ':') {
                    again:
                        *cp++ = 0;
                        c = *cp;
                        if (c == 'r') {
                            sp->flags[keys] |= SORT_reverse;
                            c = cp[1];
                        } else if (c == 'n') {
                            sp->flags[keys] |= SORT_numeric;
                            c = cp[1];
                        }
                        if (c == 'n' || c == 'r') goto again;
                    }
                }
                sp->keys[++keys] = 0;
                Sp = sp;
                if (sp->keys[0] && *sp->keys[0]) {
                    sortfn = arraysort;
                } else if (sp->flags[0] & SORT_numeric) {
                    sortfn = numsort;
                } else {
                    sortfn = alphasort;
                }
                strsort((char **)sp->nptrs, arp->nelem, sortfn);
                cp = (char *)sp->nodes;
                for (c = 0; c < arp->nelem; c++) {
                    i = (char *)sp->nptrs[c] - (char *)&sp->nodes[0];
                    if (i / nodesize != c) {
                        args[c] = ((struct Node *)(cp + i))->vp;
                        bits[c] = ((struct Node *)(cp + i))->bits;
                    }
                }
                free(sp);
                nv_close(np);
                np = NULL;
            } else {
                strsort(shp->st.dolv + 1, shp->st.dolc, sortfn);
            }
        }
        if (np) {
            if (unsetnp) nv_unset(np);
            nv_setvec(np, 0, argc, argv);
            nv_close(np);
        } else if (argc > 0 || ((sp = argv[-1]) && strcmp(sp, "--") == 0)) {
            sh_argset(ap, argv - 1);
        }
    } else if (is_option(&newflags, SH_CFLAG)) {
        if (!(shp->comdiv = *argv++)) {
            errormsg(SH_DICT, 2, e_cneedsarg);
            errormsg(SH_DICT, ERROR_usage(2), optusage(NULL));
            __builtin_unreachable();
        }
        argc--;
    }
    // Handling SH_INTERACTIVE and SH_PRIVILEGED has been moved to
    // sh_applyopts(), so that the code can be reused from b_shopt(), too.
    sh_applyopts(shp, newflags);
    if (!ap->kiafile) return argc;

    if (!argv[0]) {
        errormsg(SH_DICT, ERROR_usage(2), "-R requires scriptname");
        __builtin_unreachable();
    }
    if (!(lp->kiafile = sfopen(NULL, ap->kiafile, "w+"))) {
        errormsg(SH_DICT, ERROR_system(3), e_create, ap->kiafile);
        __builtin_unreachable();
    }
    if (!(lp->kiatmp = sftmp(2 * SF_BUFSIZE))) {
        errormsg(SH_DICT, ERROR_system(3), e_tmpcreate);
        __builtin_unreachable();
    }
    sfputr(lp->kiafile, ";vdb;CIAO/ksh", '\n');
    lp->kiabegin = sftell(lp->kiafile);
    lp->entity_tree = dtopen(&_Nvdisc, Dtbag);
    lp->scriptname = strdup(sh_fmtq(argv[0]));
    lp->script = kiaentity(lp, lp->scriptname, -1, 'p', -1, 0, 0, 's', 0, "");
    lp->fscript = kiaentity(lp, lp->scriptname, -1, 'f', -1, 0, 0, 's', 0, "");
    lp->unknown = kiaentity(lp, "<unknown>", -1, 'p', -1, 0, 0, '0', 0, "");
    kiaentity(lp, "<unknown>", -1, 'p', 0, 0, lp->unknown, '0', 0, "");
    lp->current = lp->script;
    ap->kiafile = NULL;

    return argc;
}
Beispiel #16
0
int
b_head(int argc, register char** argv, void* context)
{
	static const char	header_fmt[] = "\n==> %s <==\n";

	register Sfio_t*	fp;
	register char*		cp;
	register off_t		keep = 10;
	register off_t		skip = 0;
	register int		delim = '\n';
	int			header = 1;
	char*			format = (char*)header_fmt+1;

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'c':
			delim = -1;
			/*FALLTHROUGH*/
		case 'n':
			if (opt_info.offset && argv[opt_info.index][opt_info.offset] == 'c')
			{
				delim = -1;
				opt_info.offset++;
			}
			if ((keep = opt_info.number) <=0)
				error(2, "%s: %I*d: positive numeric option argument expected", opt_info.name, sizeof(keep), keep);
			continue;
		case 'q':
			header = argc;
			continue;
		case 'v':
			header = 0;
			continue;
		case 's':
			skip = opt_info.number;
			continue;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			continue;
		}
		break;
	}
	argv += opt_info.index;
	argc -= opt_info.index;
	if (error_info.errors)
		error(ERROR_usage(2), "%s", optusage(NiL));
	if (cp = *argv)
		argv++;
	do
	{
		if (!cp || streq(cp, "-"))
		{
			cp = "/dev/stdin";
			fp = sfstdin;
			sfset(fp, SF_SHARE, 1);
		}
		else if (!(fp = sfopen(NiL, cp, "r")))
		{
			error(ERROR_system(0), "%s: cannot open", cp);
			continue;
		}
		if (argc > header)
			sfprintf(sfstdout, format, cp);
		format = (char*)header_fmt;
		if (skip > 0)
			sfmove(fp, NiL, skip, delim);
		if (sfmove(fp, sfstdout, keep, delim) < 0 && errno != EPIPE)
			error(ERROR_system(0), "%s: read error", cp);
		if (fp != sfstdin)
			sfclose(fp);
	} while (cp = *argv++);
	if (sfsync(sfstdout))
		error(ERROR_system(0), "write error");
	return error_info.errors != 0;
}
Beispiel #17
0
Datei: enum.c Projekt: att/ast
int b_enum(int argc, char **argv, Shbltin_t *context) {
    bool pflag = false, iflag = false;
    int i, n;
    ssize_t sz = -1;
    Namval_t *np, *tp, *mp;
    Namarr_t *ap;
    char *cp;
    const char *sp;
    struct Enum *ep;
    Shell_t *shp = context->shp;
    struct {
        Optdisc_t opt;
        Namval_t *np;
    } optdisc;

    if (cmdinit(argc, argv, context, ERROR_NOTIFY)) return -1;
    while ((n = optget(argv, enum_usage))) {
        switch (n) {
            case 'p': {
                pflag = true;
                break;
            }
            case 'i': {
                iflag = true;
                break;
            }
            case ':': {
                errormsg(SH_DICT, 2, "%s", opt_info.arg);
                break;
            }
            case '?': {
                errormsg(SH_DICT, ERROR_usage(2), "%s", opt_info.arg);
                __builtin_unreachable();
            }
            default: { break; }
        }
    }

    argv += opt_info.index;
    argc -= opt_info.index;
    if (error_info.errors || argc != 1) {
        error(ERROR_USAGE | 2, "%s", optusage(NULL));
        return 1;
    }

    while ((cp = *argv++)) {
        np = nv_open(cp, shp->var_tree, NV_VARNAME | NV_NOADD);
        if (!np || !(ap = nv_arrayptr(np)) || ap->fun || ap->nelem < 2) {
            error(ERROR_exit(1), "%s must name an array containing at least two elements", cp);
        }
        n = stktell(shp->stk);
        sfprintf(shp->stk, "%s.%s%c", NV_CLASS, np->nvname, 0);
        tp = nv_open(stkptr(shp->stk, n), shp->var_tree, NV_VARNAME);
        if (pflag) {
            sh_outenum(shp, sfstdout, tp);
            continue;
        }
        stkseek(shp->stk, n);
        n = ap->nelem;
        i = 0;
        nv_onattr(tp, NV_UINT16);
        nv_putval(tp, (char *)&i, NV_INTEGER);
        nv_putsub(np, NULL, 0L, ARRAY_SCAN);
        do {
            sz += strlen(nv_getval(np));
        } while (nv_nextsub(np));
        ep = calloc(1, sizeof(struct Enum));
        if (!ep) {
            error(ERROR_system(1), "out of space");
            __builtin_unreachable();
        }
        ep->nelem = n;
        mp = nv_namptr(ep->node, 0);
        mp->nvshell = shp;
        nv_setsize(mp, 10);
        nv_onattr(mp, NV_UINT16);
        ep->iflag = iflag;

        ep->values = malloc(n * sizeof(*ep->values));
        nv_putsub(np, NULL, 0L, ARRAY_SCAN);
        i = 0;
        do {
            sp = nv_getval(np);
            ep->values[i++] = strdup(sp);
        } while (nv_nextsub(np));
        assert(n == i);

        ep->namfun.dsize = sizeof(struct Enum);
        ep->namfun.disc = &ENUM_disc;
        ep->namfun.type = tp;
        nv_onattr(tp, NV_RDONLY);
        nv_disc(tp, &ep->namfun, DISC_OP_FIRST);
        memset(&optdisc, 0, sizeof(optdisc));
        optdisc.opt.infof = enuminfo;
        optdisc.np = tp;
        nv_addtype(tp, enum_type, &optdisc, sizeof(optdisc));
        nv_onattr(np, NV_LTOU | NV_UTOL);
    }
    nv_open(0, shp->var_tree, 0);
    return error_info.errors != 0;
}
Beispiel #18
0
int b_enum(int argc, char** argv, Shbltin_t *context)
#endif
{
	bool			pflag=false, iflag=false;
	int			i,n;
	ssize_t			sz = -1;
	Namval_t		*np, *tp, *mp;
	Namarr_t		*ap;
	char			*cp,*sp;
	struct Enum		*ep;
	Shell_t			*shp = context->shp;
	struct {
	    Optdisc_t	opt;
	    Namval_t	*np;
	}			optdisc;

	cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
	for (;;)
	{
		switch (optget(argv, enum_usage))
		{
		case 'p':
			pflag = true;
			continue;
		case 'i':
			iflag = true;
			continue;
		case '?':
			error(ERROR_USAGE|4, "%s", opt_info.arg);
			break;
		case ':':
			error(2, "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	if (error_info.errors)
	{
		error(ERROR_USAGE|2, "%s", optusage(NiL));
		return 1;
	}
	if(!*argv)
		sh_outenum(shp,sfstdout,(Namval_t*)0);
	while(cp = *argv++)
	{
		if(!(np = nv_open(cp, shp->var_tree, NV_VARNAME|NV_NOADD))  || !(ap=nv_arrayptr(np)) || ap->fun || (sz=ap->nelem) < 2)
			error(ERROR_exit(1), "%s must name an array  containing at least two elements",cp);
		n = stktell(shp->stk);
		sfprintf(shp->stk,"%s.%s%c",NV_CLASS,np->nvname,0);
		tp = nv_open(stkptr(shp->stk,n), shp->var_tree, NV_VARNAME);
		if(pflag)
		{
			sh_outenum(shp,sfstdout,tp);
			continue;
		}
		stkseek(shp->stk,n);
		n = sz;
		i = 0;
		nv_onattr(tp, NV_UINT16);
		nv_putval(tp, (char*)&i, NV_INTEGER);
		nv_putsub(np, (char*)0, 0L, ARRAY_SCAN);
		do
		{
			sz += strlen(nv_getval(np));
		}
		while(nv_nextsub(np));
		sz += n*sizeof(char*);
		if(!(ep = newof(0,struct Enum,1,sz)))
			error(ERROR_system(1), "out of space");
		mp = nv_namptr(ep->node,0);
		mp->nvshell = shp;
		nv_setsize(mp,10);
		nv_onattr(mp, NV_UINT16);
		ep->iflag = iflag;
		ep->nelem = n;
		cp = (char*)&ep->values[n+1];
		nv_putsub(np, (char*)0, 0L, ARRAY_SCAN);
		ep->values[n] = 0;
		i = 0;
		do
		{
			ep->values[i++] = cp;
			sp =  nv_getval(np);
			n = strlen(sp);
			memcpy(cp,sp,n+1);
			cp += n+1;
		}
		while(nv_nextsub(np));
		ep->hdr.dsize = sizeof(struct Enum)+sz;
		ep->hdr.disc = &ENUM_disc;
		ep->hdr.type = tp;
		nv_onattr(tp, NV_RDONLY);
		nv_disc(tp, &ep->hdr,NV_FIRST);
		memset(&optdisc,0,sizeof(optdisc));
		optdisc.opt.infof = enuminfo;
		optdisc.np = tp;
		nv_addtype(tp, enum_type, &optdisc.opt, sizeof(optdisc)); 
		nv_onattr(np,NV_LTOU|NV_UTOL);
	}
	nv_open(0,shp->var_tree,0);
	return error_info.errors != 0;
}
Beispiel #19
0
/*
 * This routine will turn the sftmp() file into a real /tmp file or pipe
 */
void	sh_subtmpfile(int pflag)
{
	Shell_t *shp = &sh;
	int fds[2];
	Sfoff_t off;
	register struct checkpt	*pp = (struct checkpt*)shp->jmplist;
	register struct subshell *sp = subshell_data->pipe;
	if(sfset(sfstdout,0,0)&SF_STRING)
	{
		register int fd;
		/* save file descriptor 1 if open */
		if((sp->tmpfd = fd = fcntl(1,F_DUPFD,10)) >= 0)
		{
			fcntl(fd,F_SETFD,FD_CLOEXEC);
			shp->fdstatus[fd] = shp->fdstatus[1]|IOCLEX;
			close(1);
			shp->fdstatus[1] = IOCLOSE;
		}
		else if(errno!=EBADF)
		{
			((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
			shp->toomany = 1;
			errormsg(SH_DICT,ERROR_system(1),e_toomany);
		}
		if(shp->subshare || !pflag)
		{
			sfdisc(sfstdout,SF_POPDISC);
			if((fd=sffileno(sfstdout))>=0)
			{
				shp->fdstatus[fd] = IOREAD|IOWRITE;
				sfsync(sfstdout);
				if(fd==1)
					fcntl(1,F_SETFD,0);
				else
				{
					sfsetfd(sfstdout,1);
					shp->fdstatus[1] = shp->fdstatus[fd];
					shp->fdstatus[fd] = IOCLOSE;
				}
				goto skip;
			}
		}
	}
	if(sp && (shp->fdstatus[1]==IOCLOSE || (!shp->subshare && !(shp->fdstatus[1]&IONOSEEK))))
	{
		struct stat statb,statx;
		int fd;
		sh_pipe(fds);
		sp->pipefd = fds[0];
		sh_fcntl(sp->pipefd,F_SETFD,FD_CLOEXEC);
		/* write the data to the pipe */
		if(off = sftell(sfstdout))
		{
			write(fds[1],sfsetbuf(sfstdout,(Void_t*)sfstdout,0),(size_t)off);
			sfpurge(sfstdout);
		}
		if((sfset(sfstdout,0,0)&SF_STRING) || fstat(1,&statb)<0)
			statb.st_ino = 0;
		sfclose(sfstdout);
		if((sh_fcntl(fds[1],F_DUPFD, 1)) != 1)
			errormsg(SH_DICT,ERROR_system(1),e_redirect);
		sh_close(fds[1]);
		if(statb.st_ino) for(fd=0; fd < 10; fd++)
		{
			if(fd==1 || ((shp->fdstatus[fd]&(IONOSEEK|IOSEEK|IOWRITE))!=(IOSEEK|IOWRITE)) || fstat(fd,&statx)<0)
				continue;
			if(statb.st_ino==statx.st_ino && statb.st_dev==statx.st_dev)
			{
				sh_close(fd);
				fcntl(1,F_DUPFD, fd);
			}
		}
	skip:
		sh_iostream(shp,1);
		sfset(sfstdout,SF_SHARE|SF_PUBLIC,1);
		sfpool(sfstdout,shp->outpool,SF_WRITE);
		if(pp && pp->olist  && pp->olist->strm == sfstdout)
			pp->olist->strm = 0;
	}
}
Beispiel #20
0
Datei: misc.c Projekt: att/ast
int b_dot_cmd(int n, char *argv[], Shbltin_t *context) {
    char *script;
    Namval_t *np;
    int jmpval;
    Shell_t *shp = context->shp;
    struct sh_scoped savst, *prevscope = shp->st.self;
    int fd;
    char *filename = NULL;
    char *buffer = NULL;
    struct dolnod *saveargfor = NULL;
    volatile struct dolnod *argsave = NULL;
    checkpt_t buff;
    Sfio_t *iop = NULL;
    short level;
    Optdisc_t disc;

    memset(&disc, 0, sizeof(disc));
    disc.version = OPT_VERSION;
    opt_info.disc = &disc;

    while ((n = optget(argv, sh_optdot))) {
        switch (n) {
            case ':': {
                errormsg(SH_DICT, 2, "%s", opt_info.arg);
                break;
            }
            case '?': {
                errormsg(SH_DICT, ERROR_usage(0), "%s", opt_info.arg);
                return 2;
            }
            default: { break; }
        }
    }

    argv += opt_info.index;
    script = *argv;
    if (error_info.errors || !script) {
        errormsg(SH_DICT, ERROR_usage(2), "%s", optusage(NULL));
        __builtin_unreachable();
    }
    if (shp->dot_depth + 1 > DOTMAX) {
        errormsg(SH_DICT, ERROR_exit(1), e_toodeep, script);
        __builtin_unreachable();
    }
    np = shp->posix_fun;
    if (!np) {
        // Check for KornShell style function first.
        np = nv_search(script, shp->fun_tree, 0);
        if (np && is_afunction(np) && !nv_isattr(np, NV_FPOSIX)) {
            if (!FETCH_VT(np->nvalue, ip)) {
                // TODO: Replace this with a comment explaining why the return value of this
                // path_search() call is ignored. At the time I wrote this (2019-03-16) no unit test
                // exercises this statement. I added the void cast to silence Coverity Scan 253792.
                (void)path_search(shp, script, NULL, 0);
                if (FETCH_VT(np->nvalue, ip)) {
                    if (nv_isattr(np, NV_FPOSIX)) np = NULL;
                } else {
                    errormsg(SH_DICT, ERROR_exit(1), e_found, script);
                    __builtin_unreachable();
                }
            }
        } else {
            np = NULL;
        }

        if (!np) {
            fd = path_open(shp, script, path_get(shp, script));
            if (fd < 0) {
                errormsg(SH_DICT, ERROR_system(1), e_open, script);
                __builtin_unreachable();
            }
            filename = path_fullname(shp, stkptr(shp->stk, PATH_OFFSET));
        }
    }
    *prevscope = shp->st;
    shp->st.lineno = np ? ((struct functnod *)nv_funtree(np))->functline : 1;
    shp->st.var_local = shp->st.save_tree = shp->var_tree;
    if (filename) {
        shp->st.filename = filename;
        shp->st.lineno = 1;
    }
    level = shp->fn_depth + shp->dot_depth + 1;
    nv_putval(SH_LEVELNOD, (char *)&level, NV_INT16);
    shp->st.prevst = prevscope;
    shp->st.self = &savst;
    shp->topscope = (Shscope_t *)shp->st.self;
    prevscope->save_tree = shp->var_tree;
    if (np) {
        struct Ufunction *rp = FETCH_VT(np->nvalue, rp);
        shp->st.filename = strdup(rp->fname ? rp->fname : "");
    }
    nv_putval(SH_PATHNAMENOD, shp->st.filename, NV_NOFREE);
    shp->posix_fun = NULL;
    if (np || argv[1]) argsave = sh_argnew(shp, argv, &saveargfor);
    sh_pushcontext(shp, &buff, SH_JMPDOT);
    jmpval = sigsetjmp(buff.buff, 0);
    if (jmpval == 0) {
        shp->dot_depth++;
        if (np) {
            sh_exec(shp, (Shnode_t *)(nv_funtree(np)), sh_isstate(shp, SH_ERREXIT));
        } else {
            buffer = malloc(IOBSIZE + 1);
            iop = sfnew(NULL, buffer, IOBSIZE, fd, SF_READ);
            sh_offstate(shp, SH_NOFORK);
            sh_eval(shp, iop, sh_isstate(shp, SH_PROFILE) ? SH_FUNEVAL : 0);
        }
    }
    sh_popcontext(shp, &buff);
    if (buffer) free(buffer);
    if (!np) {
        free(shp->st.filename);
        shp->st.filename = NULL;
    }
    shp->dot_depth--;
    if ((np || argv[1]) && jmpval != SH_JMPSCRIPT) {
        sh_argreset(shp, (struct dolnod *)argsave, saveargfor);
    } else {
        prevscope->dolc = shp->st.dolc;
        prevscope->dolv = shp->st.dolv;
    }
    if (shp->st.self != &savst) *shp->st.self = shp->st;
    // Only restore the top Shscope_t portion for posix functions.
    memcpy(&shp->st, prevscope, sizeof(Shscope_t));
    shp->topscope = (Shscope_t *)prevscope;
    nv_putval(SH_PATHNAMENOD, shp->st.filename, NV_NOFREE);
    if (jmpval && jmpval != SH_JMPFUN) siglongjmp(shp->jmplist->buff, jmpval);
    return shp->exitval;
}
Beispiel #21
0
int	b_hist(int argc,char *argv[], void *extra)
{
	register History_t *hp;
	register char *arg;
	register int flag,fdo;
	register Shell_t *shp = ((Shbltin_t*)extra)->shp;
	Sfio_t *outfile;
	char *fname;
	int range[2], incr, index2, indx= -1;
	char *edit = 0;		/* name of editor */
	char *replace = 0;		/* replace old=new */
	int lflag = 0, nflag = 0, rflag = 0;
#if SHOPT_HISTEXPAND
	int pflag = 0;
#endif
	Histloc_t location;
	NOT_USED(argc);
	if(!sh_histinit((void*)shp))
		errormsg(SH_DICT,ERROR_system(1),e_histopen);
	hp = shp->gd->hist_ptr;
	while((flag = optget(argv,sh_opthist))) switch(flag)
	{
	    case 'e':
		edit = opt_info.arg;
		break;
	    case 'n':
		nflag++;
		break;
	    case 'l':
		lflag++;
		break;
	    case 'r':
		rflag++;
		break;
	    case 's':
		edit = "-";
		break;
#if SHOPT_HISTEXPAND
	    case 'p':
		pflag++;
		break;
#endif
	    case 'N':
		if(indx<=0)
		{
			if((flag = hist_max(hp) - opt_info.num-1) < 0)
				flag = 1;
			range[++indx] = flag;
			break;
		}
	    case ':':
		errormsg(SH_DICT,2, "%s", opt_info.arg);
		break;
	    case '?':
		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
		break;
	}
	if(error_info.errors)
		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
	argv += (opt_info.index-1);
#if SHOPT_HISTEXPAND
	if(pflag)
	{
		hist_cancel(hp);
		pflag = 0;
		while(arg=argv[1])
		{
			flag = hist_expand(arg,&replace);
			if(!(flag & HIST_ERROR))
				sfputr(sfstdout, replace, '\n');
			else
				pflag = 1;
			if(replace)
				free(replace);
			argv++;
		}
		return pflag;
	}
#endif
	flag = indx;
	while(flag<1 && (arg=argv[1]))
	{
		/* look for old=new argument */
		if(!replace && strchr(arg+1,'='))
		{
			replace = arg;
			argv++;
			continue;
		}
		else if(isdigit(*arg) || *arg == '-')
		{
			/* see if completely numeric */
			do	arg++;
			while(isdigit(*arg));
			if(*arg==0)
			{
				arg = argv[1];
				range[++flag] = (int)strtol(arg, (char**)0, 10);
				if(*arg == '-')
					range[flag] += (hist_max(hp)-1);
				argv++;
				continue;
			}
		}
		/* search for last line starting with string */
		location = hist_find(hp,argv[1],hist_max(hp)-1,0,-1);
		if((range[++flag] = location.hist_command) < 0)
			errormsg(SH_DICT,ERROR_exit(1),e_found,argv[1]);
		argv++;
	}
	if(flag <0)
	{
		/* set default starting range */
		if(lflag)
		{
			flag = hist_max(hp)-16;
			if(flag<1)
				flag = 1;
		}
		else
			flag = hist_max(hp)-2;
		range[0] = flag;
		flag = 0;
	}
	index2 = hist_min(hp);
	if(range[0]<index2)
		range[0] = index2;
	if(flag==0)
		/* set default termination range */
		range[1] = ((lflag && !edit)?hist_max(hp)-1:range[0]);
	if(range[1]>=(flag=(hist_max(hp) - !lflag)))
		range[1] = flag;
	/* check for valid ranges */
	if(range[1]<index2 || range[0]>=flag)
		errormsg(SH_DICT,ERROR_exit(1),e_badrange,range[0],range[1]);
	if(edit && *edit=='-' && range[0]!=range[1])
		errormsg(SH_DICT,ERROR_exit(1),e_eneedsarg);
	/* 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)
	{
		outfile = sfstdout;
		arg = "\n\t";
	}
	else
	{
		if(!(fname=pathtmp(NIL(char*),0,0,NIL(int*))))
			errormsg(SH_DICT,ERROR_exit(1),e_create,"");
		if((fdo=open(fname,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR)) < 0)
			errormsg(SH_DICT,ERROR_system(1),e_create,fname);
		outfile= sfnew(NIL(Sfio_t*),shp->outbuff,IOBSIZE,fdo,SF_WRITE);
		arg = "\n";
		nflag++;
	}
	while(1)
	{
		if(nflag==0)
			sfprintf(outfile,"%d\t",range[flag]);
		else if(lflag)
			sfputc(outfile,'\t');
		hist_list(shp->gd->hist_ptr,outfile,hist_tell(shp->gd->hist_ptr,range[flag]),0,arg);
		if(lflag)
			sh_sigcheck(shp);
		if(range[flag] == range[1-flag])
			break;
		range[flag] += incr;
	}
	if(lflag)
		return(0);
	sfclose(outfile);
	hist_eof(hp);
	arg = edit;
	if(!arg && !(arg=nv_getval(sh_scoped(shp,HISTEDIT))) && !(arg=nv_getval(sh_scoped(shp,FCEDNOD))))
		arg = (char*)e_defedit;
#ifdef apollo
	/*
	 * Code to support the FC using the pad editor.
	 * Exampled of how to use: HISTEDIT=pad
	 */
	if (strcmp (arg, "pad") == 0)
	{
		extern int pad_create(char*);
		sh_close(fdo);
		fdo = pad_create(fname);
		pad_wait(fdo);
		unlink(fname);
		strcat(fname, ".bak");
		unlink(fname);
		lseek(fdo,(off_t)0,SEEK_SET);
	}
	else
	{
#endif /* apollo */
	if(*arg != '-')
	{
		char *com[3];
		com[0] =  arg;
		com[1] =  fname;
		com[2] = 0;
		error_info.errors = sh_eval(sh_sfeval(com),0);
	}
	fdo = sh_chkopen(fname);
	unlink(fname);
	free((void*)fname);
#ifdef apollo
	}
#endif /* apollo */
	/* don't history fc itself unless forked */
	error_info.flags |= ERROR_SILENT;
	if(!sh_isstate(SH_FORKED))
		hist_cancel(hp);
	sh_onstate(SH_HISTORY);
	sh_onstate(SH_VERBOSE);	/* echo lines as read */
	if(replace)
		hist_subst(error_info.id,fdo,replace);
	else if(error_info.errors == 0)
	{
		char buff[IOBSIZE+1];
		Sfio_t *iop = sfnew(NIL(Sfio_t*),buff,IOBSIZE,fdo,SF_READ);
		/* read in and run the command */
		if(shp->hist_depth++ > HIST_RECURSE)
			errormsg(SH_DICT,ERROR_exit(1),e_toodeep,"history");
		sh_eval(iop,1);
		shp->hist_depth--;
	}
Beispiel #22
0
int
b_tee(int argc, register char** argv, void* context)
{
    register Tee_t*		tp = 0;
    register int		oflag = O_WRONLY|O_TRUNC|O_CREAT|O_BINARY;
    register int*		hp;
    register char*		cp;
    int			line;

    if (argc <= 0)
    {
        if (context && (tp = (Tee_t*)sh_context(context)->data))
        {
            sh_context(context)->data = 0;
            tee_cleanup(tp);
        }
        return 0;
    }
    cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_CALLBACK);
    line = -1;
    for (;;)
    {
        switch (optget(argv, usage))
        {
        case 'a':
            oflag &= ~O_TRUNC;
            oflag |= O_APPEND;
            continue;
        case 'i':
            signal(SIGINT, SIG_IGN);
            continue;
        case 'l':
            line = sfset(sfstdout, 0, 0) & SF_LINE;
            if ((line == 0) == (opt_info.num == 0))
                line = -1;
            else
                sfset(sfstdout, SF_LINE, !!opt_info.num);
            continue;
        case ':':
            error(2, "%s", opt_info.arg);
            break;
        case '?':
            error(ERROR_usage(2), "%s", opt_info.arg);
            break;
        }
        break;
    }
    if (error_info.errors)
        error(ERROR_usage(2), "%s", optusage(NiL));
    argv += opt_info.index;
    argc -= opt_info.index;
#if _ANCIENT_BSD_COMPATIBILITY
    if (*argv && streq(*argv, "-"))
    {
        signal(SIGINT, SIG_IGN);
        argv++;
        argc--;
    }
#endif
    if (argc > 0)
    {
        if (tp = (Tee_t*)stakalloc(sizeof(Tee_t) + argc * sizeof(int)))
        {
            memset(&tp->disc, 0, sizeof(tp->disc));
            tp->disc.writef = tee_write;
            if (context)
                sh_context(context)->data = (void*)tp;
            tp->line = line;
            hp = tp->fd;
            while (cp = *argv++)
            {
                if ((*hp = open(cp, oflag, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
                    error(ERROR_system(0), "%s: cannot create", cp);
                else
                    hp++;
            }
            if (hp == tp->fd)
                tp = 0;
            else
            {
                *hp = -1;
                sfdisc(sfstdout, &tp->disc);
            }
        }
        else
            error(ERROR_exit(0), "out of space");
    }
    if ((sfmove(sfstdin, sfstdout, SF_UNBOUND, -1) < 0 || !sfeof(sfstdin)) && errno != EPIPE)
        error(ERROR_system(0), "read error");
    if (sfsync(sfstdout))
        error(ERROR_system(0), "write error");
    tee_cleanup(tp);
    return error_info.errors;
}
Beispiel #23
0
int
b_fold(int argc, char** argv, Shbltin_t* context)
{
	register int n, width=WIDTH;
	register Sfio_t *fp;
	register char *cp;
	char *cont="\n";
	size_t contsize = 1;
	char cols[1<<CHAR_BIT];

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	memset(cols, 0, sizeof(cols));
	cols['\t'] = T_TAB;
	cols['\b'] = T_BS;
	cols['\n'] = T_NL;
	cols['\r'] = T_RET;
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'b':
			cols['\r'] = cols['\b'] = 0;
			cols['\t'] = cols[' '];
			continue;
		case 'c':
			contsize = stresc(cont = strdup(opt_info.arg));
			continue;
		case 'd':
			if (n = *opt_info.arg)
				cols[n] = T_SP;
			continue;
		case 's':
			cols[' '] = T_SP;
			if(cols['\t']==0)
				cols['\t'] = T_SP;
			continue;
		case 'w':
			if ((width = opt_info.num) <= 0)
				error(2, "%d: width must be positive", opt_info.num);
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			continue;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			continue;
		}
		break;
	}
	argv += opt_info.index;
	argc -= opt_info.index;
	if(error_info.errors)
		error(ERROR_usage(2),"%s", optusage(NiL));
	if(cp = *argv)
		argv++;
	do
	{
		if(!cp || streq(cp,"-"))
			fp = sfstdin;
		else if(!(fp = sfopen(NiL,cp,"r")))
		{
			error(ERROR_system(0),"%s: cannot open",cp);
			error_info.errors = 1;
			continue;
		}
		fold(fp,sfstdout,width,cont,contsize,cols);
		if(fp!=sfstdin)
			sfclose(fp);
	}
	while(cp= *argv++);
	return(error_info.errors);
}
Beispiel #24
0
static int doldd(const char* filename)
{
	STARTUPINFO		si;
	HANDLE			ph; 
	DEBUG_EVENT		event;
	struct spawndata	sdata;
	char*			av[2];
	pid_t			pid;
	int			status;
	int			r = 0;
	char			dllname[PATH_MAX+1];
	char			dllpath[PATH_MAX+1];

	memset(&sdata, 0, sizeof(sdata));
	memset(&si, 0, sizeof(si));
	sdata.start = &si;
	sdata.flags = DEBUG_PROCESS;
	si.cb		= sizeof(si);
	si.dwFlags	= STARTF_FORCEONFEEDBACK|STARTF_USESHOWWINDOW;
	si.wShowWindow	= SW_SHOWNORMAL;
	av[0] = (char*)filename;
	av[1] = 0;
	if ((pid = uwin_spawn(filename, av, NULL, &sdata)) < 0)
	{
		error(ERROR_system(0), "%s cannot create process", filename);
		return -1;
	}
	ph = sdata.handle;
	for (;;)
	{
		if (!WaitForDebugEvent(&event, 1500))
			break;
		if (event.dwProcessId != uwin_ntpid(pid))
			continue;
		switch(event.dwDebugEventCode)
		{
		case EXIT_PROCESS_DEBUG_EVENT:
			CloseHandle(ph);
			ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
			wait(&status);
			return 0;
		case LOAD_DLL_DEBUG_EVENT:
			if (event.u.LoadDll.hFile)
			{
				if (modulenamepath(ph, &event.u.LoadDll, dllname, sizeof(dllname), dllpath, sizeof(dllpath)) < 0)
					r = -1;
				else
					sfprintf(sfstdout, "\t%s => %s\n", dllname, dllpath);
			}
			ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
			break;
		case CREATE_PROCESS_DEBUG_EVENT:
			ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
			break;
		case CREATE_THREAD_DEBUG_EVENT:
		case EXCEPTION_DEBUG_EVENT:
			kill(pid, SIGTERM);
			ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_TERMINATE_PROCESS);
			break;
		default:
			ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
			break;
		}
	}
	return 0;
}
Beispiel #25
0
int
b_cut(int argc, char** argv, void* context)
{
	register char*		cp = 0;
	register Sfio_t*	fp;
	char*			s;
	int			n;
	Cut_t*			cut;
	int			mode = 0;
	Delim_t			wdelim;
	Delim_t			ldelim;
	size_t			reclen = 0;

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	wdelim.chr = '\t';
	ldelim.chr = '\n';
	wdelim.len = ldelim.len = 1;
	for (;;)
	{
		switch (n = optget(argv, usage))
		{
		case 0:
			break;
		case 'b':
		case 'c':
			if(mode&C_FIELDS)
			{
				error(2, "f option already specified");
				continue;
			}
			cp = opt_info.arg;
			if(n=='b')
				mode |= C_BYTES;
			else
				mode |= C_CHARS;
			continue;
		case 'D':
			ldelim.str = opt_info.arg;
			if (mbwide())
			{
				s = opt_info.arg;
				ldelim.chr = mbchar(s);
				if ((n = s - opt_info.arg) > 1)
				{
					ldelim.len = n;
					continue;
				}
			}
			ldelim.chr = *(unsigned char*)opt_info.arg;
			ldelim.len = 1;
			continue;
		case 'd':
			wdelim.str = opt_info.arg;
			if (mbwide())
			{
				s = opt_info.arg;
				wdelim.chr = mbchar(s);
				if ((n = s - opt_info.arg) > 1)
				{
					wdelim.len = n;
					continue;
				}
			}
			wdelim.chr = *(unsigned char*)opt_info.arg;
			wdelim.len = 1;
			continue;
		case 'f':
			if(mode&(C_CHARS|C_BYTES))
			{
				error(2, "c option already specified");
				continue;
			}
			cp = opt_info.arg;
			mode |= C_FIELDS;
			continue;
		case 'n':
			mode |= C_NOSPLIT;
			continue;
		case 'N':
			mode |= C_NONEWLINE;
			continue;
		case 'R':
		case 'r':
			if(opt_info.num>0)
				reclen = opt_info.num;
			continue;
		case 's':
			mode |= C_SUPRESS;
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			break;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	if (error_info.errors)
		error(ERROR_usage(2), "%s",optusage(NiL));
	if(!cp)
	{
		error(2, "b, c or f option must be specified");
		error(ERROR_usage(2), "%s", optusage(NiL));
	}
	if(!*cp)
		error(3, "non-empty b, c or f option must be specified");
	if((mode & (C_FIELDS|C_SUPRESS)) == C_SUPRESS)
		error(3, "s option requires f option");
	cut = cutinit(mode, cp, &wdelim, &ldelim, reclen);
	if(cp = *argv)
		argv++;
	do
	{
		if(!cp || streq(cp,"-"))
			fp = sfstdin;
		else if(!(fp = sfopen(NiL,cp,"r")))
		{
			error(ERROR_system(0),"%s: cannot open",cp);
			continue;
		}
		if(mode&C_FIELDS)
			cutfields(cut,fp,sfstdout);
		else
			cutcols(cut,fp,sfstdout);
		if(fp!=sfstdin)
			sfclose(fp);
	} while(cp = *argv++);
	if (sfsync(sfstdout))
		error(ERROR_system(0), "write error");
	return error_info.errors != 0;
}
Beispiel #26
0
int
b_mkdir(int argc, char** argv, void* context)
{
	register char*	arg;
	register int	n;
	register mode_t	mode = DIRMODE;
	register mode_t	mask = 0;
	register int	mflag = 0;
	register int	pflag = 0;
	register int	vflag = 0;
	char*		name;
	mode_t		dmode;
	struct stat	st;

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 0:
			break;
		case 'm':
			mflag = 1;
			mode = strperm(arg = opt_info.arg, &opt_info.arg, mode);
			if (*opt_info.arg)
				error(ERROR_exit(0), "%s: invalid mode", arg);
			continue;
		case 'p':
			pflag = 1;
			continue;
		case 'v':
			vflag = 1;
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			continue;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			continue;
		}
		break;
	}
	argv += opt_info.index;
	if (error_info.errors || !*argv)
		error(ERROR_usage(2), "%s", optusage(NiL));
	mask = umask(0);
	if (mflag || pflag)
	{
		dmode = DIRMODE & ~mask;
		if (!mflag)
			mode = dmode;
		dmode |= S_IWUSR | S_IXUSR;
	}
	else
	{
		mode &= ~mask;
		umask(mask);
		mask = 0;
	}
	while (arg = *argv++)
	{
		if (mkdir(arg, mode) < 0)
		{
			if (!pflag || !(errno == ENOENT || errno == EEXIST || errno == ENOTDIR))
			{
				error(ERROR_system(0), "%s:", arg);
				continue;
			}
			if (errno == EEXIST)
				continue;

			/*
			 * -p option, preserve intermediates
			 * first eliminate trailing /'s
			 */

			n = strlen(arg);
			while (n > 0 && arg[--n] == '/');
			arg[n + 1] = 0;
			for (name = arg, n = *arg; n;)
			{
				/* skip over slashes */
				while (*arg == '/')
					arg++;
				/* skip to next component */
				while ((n = *arg) && n != '/')
					arg++;
				*arg = 0;
				if (mkdir(name, n ? dmode : mode) < 0 && errno != EEXIST && access(name, F_OK) < 0)
				{
					*arg = n;
					error(ERROR_system(0), "%s:", name);
					break;
				}
				if (vflag)
					error(0, "%s: directory created", name);
				if (!(*arg = n) && (mode & (S_ISVTX|S_ISUID|S_ISGID)))
				{
					if (stat(name, &st))
					{
						error(ERROR_system(0), "%s: cannot stat", name);
						break;
					}
					if ((st.st_mode & (S_ISVTX|S_ISUID|S_ISGID)) != (mode & (S_ISVTX|S_ISUID|S_ISGID)) && chmod(name, mode))
					{
						error(ERROR_system(0), "%s: cannot change mode from %s to %s", name, fmtperm(st.st_mode & (S_ISVTX|S_ISUID|S_ISGID)), fmtperm(mode));
						break;
					}
				}
			}
		}
		else if (vflag)
			error(0, "%s: directory created", arg);
	}
	if (mask)
		umask(mask);
	return error_info.errors != 0;
}
Beispiel #27
0
int	b_ulimit(int argc,char *argv[],void *extra)
{
	register char *limit;
	register int mode=0, n;
	register unsigned long hit = 0;
	Shell_t *shp = ((Shbltin_t*)extra)->shp;
#ifdef _lib_getrlimit
	struct rlimit rlp;
#endif /* _lib_getrlimit */
	const Limit_t* tp;
	char* conf;
	int label, unit, nosupport;
	rlim_t i;
	char tmp[32];
        Optdisc_t disc;
        memset(&disc, 0, sizeof(disc));
        disc.version = OPT_VERSION;
        disc.infof = infof;
	opt_info.disc = &disc;
	while((n = optget(argv,sh_optulimit))) switch(n)
	{
		case 'H':
			mode |= HARD;
			continue;
		case 'S':
			mode |= SOFT;
			continue;
		case 'a':
			hit = ~0;
			break;
		default:
			if(n < 0)
				hit |= (1L<<(-(n+1)));
			else
				errormsg(SH_DICT,2, e_notimp, opt_info.name);
			break;
		case ':':
			errormsg(SH_DICT,2, "%s", opt_info.arg);
			break;
		case '?':
			errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
			break;
	}
	opt_info.disc = 0;
	/* default to -f */
	limit = argv[opt_info.index];
	if(hit==0)
		for(n=0; shtab_limits[n].option; n++)
			if(shtab_limits[n].index == RLIMIT_FSIZE)
			{
				hit |= (1L<<n);
				break;
			}
	/* only one option at a time for setting */
	label = (hit&(hit-1));
	if(error_info.errors || (limit && label) || argc>opt_info.index+1)
		errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
	if(mode==0)
		mode = (HARD|SOFT);
	for(tp = shtab_limits; tp->option && hit; tp++,hit>>=1)
	{
		if(!(hit&1))
			continue;
		nosupport = (n = tp->index) == RLIMIT_UNKNOWN;
		unit = shtab_units[tp->type];
		if(limit)
		{
			if(shp->subshell && !shp->subshare)
				sh_subfork();
			if(strcmp(limit,e_unlimited)==0)
				i = INFINITY;
			else
			{
				char *last;
				if((i=sh_strnum(limit,&last,2))==INFINITY || *last)
					errormsg(SH_DICT,ERROR_system(1),e_number,limit);
				i *= unit;
			}
			if(nosupport)
				errormsg(SH_DICT,ERROR_system(1),e_readonly,tp->name);
			else
			{
#ifdef _lib_getrlimit
				if(getrlimit(n,&rlp) <0)
					errormsg(SH_DICT,ERROR_system(1),e_number,limit);
				if(mode&HARD)
					rlp.rlim_max = i;
				if(mode&SOFT)
					rlp.rlim_cur = i;
				if(setrlimit(n,&rlp) <0)
					errormsg(SH_DICT,ERROR_system(1),e_overlimit,limit);
#else
				if((i=vlimit(n,i)) < 0)
					errormsg(SH_DICT,ERROR_system(1),e_number,limit);
#endif /* _lib_getrlimit */
			}
		}
		else
		{
			if(!nosupport)
			{
#ifdef  _lib_getrlimit
				if(getrlimit(n,&rlp) <0)
					errormsg(SH_DICT,ERROR_system(1),e_number,limit);
				if(mode&HARD)
					i = rlp.rlim_max;
				if(mode&SOFT)
					i = rlp.rlim_cur;
#else
#   ifdef _lib_ulimit
				n--;
#   endif /* _lib_ulimit */
				i = -1;
				if((i=vlimit(n,i)) < 0)
					errormsg(SH_DICT,ERROR_system(1),e_number,limit);
#endif /* _lib_getrlimit */
			}
			if(label)
			{
				if(tp->type != LIM_COUNT)
					sfsprintf(tmp,sizeof(tmp),"%s (%ss)", tp->description, e_units[tp->type]);
				else
					sfsprintf(tmp,sizeof(tmp),"%s", tp->name);
				sfprintf(sfstdout,"%-30s (-%c)  ",tmp,tp->option);
			}
			if(nosupport)
			{
				if(!tp->conf || !*(conf = astconf(tp->conf, NiL, NiL)))
					conf = (char*)e_nosupport;
				sfputr(sfstdout,conf,'\n');
			}
			else if(i!=INFINITY)
			{
				i += (unit-1);
				sfprintf(sfstdout,"%I*d\n",sizeof(i),i/unit);
			}
			else
				sfputr(sfstdout,e_unlimited,'\n');
		}
	}
	return(0);
}
Beispiel #28
0
static void set(char *argv[], struct termios *sp)
{
	const Tty_t *tp;
	register int c,off;
	char *cp;
	char *ep;
	while(cp = *argv++)
	{
		off = 0;
		if(*cp=='-')
		{
			cp++;
			off=1;
		}
		if(!(tp=lookup(cp)) || (off && (tp->type!=BIT) && (tp->type!=TABS)))
			error(ERROR_exit(1),"%s: unknown mode",cp);
		switch(tp->type)
		{
		    case CHAR:
			if(off)
				error(ERROR_exit(1),"%s: unknown mode",cp);
			if(!*argv)
				error(ERROR_exit(1),"missing argument to %s",cp);
			c = gettchar(*argv++);
			if(c>=0)
				sp->c_cc[tp->mask] = c;
			else
				sp->c_cc[tp->mask] = _POSIX_VDISABLE;
			break;
		    case BIT: case BITS:
			switch(tp->field)
			{
			    case C_FLAG:
				if(off)
					sp->c_cflag &= ~tp->mask;
				else
					sp->c_cflag |= tp->mask;
				break;
			    case I_FLAG:
				if(off)
					sp->c_iflag &= ~tp->mask;
				else
					sp->c_iflag |= tp->mask;
				break;
			    case O_FLAG:
				sp->c_oflag &= ~tp->mask;
				sp->c_oflag |= tp->val;
				break;
			    case L_FLAG:
				if(off)
					sp->c_lflag &= ~tp->mask;
				else
					sp->c_lflag |= tp->mask;
				break;
			}
			break;
		    case TABS:
			sp->c_oflag &= ~tp->mask;
			if(off)
				sp->c_oflag |= tp->val;
			break;
#ifdef TIOCSWINSZ
		    case WIND:
		    {
			struct winsize win;
			int n;
			if(ioctl(0,TIOCGWINSZ,&win)<0)
				error(ERROR_system(1),"cannot set %s",tp->name);
			if(!(cp= *argv))
			{
				sfprintf(sfstdout,"%d\n",tp->mask?win.ws_col:win.ws_row);
				break;
			}
			argv++;
			n=strtol(cp,&cp,10);
			if(*cp)
				error(ERROR_system(1),"%d: invalid number of %s",argv[-1],tp->name);
			if(tp->mask)
				win.ws_col = n;
			else
				win.ws_row = n;
			if(ioctl(0,TIOCSWINSZ,&win)<0)
				error(ERROR_system(1),"cannot set %s",tp->name);
			break;
		    }
#endif
		    case NUM:
			cp = *argv;
			if (!cp)
			{
				if (tp->field == C_SPEED)
				{
					if (tp = getspeed(*tp->name == 'i' ? cfgetispeed(sp) : cfgetospeed(sp)))
						sfprintf(sfstdout, "%s\n", tp->name);
					break;
				}
				error(ERROR_exit(1), "%s: missing numeric argument", tp->name);
			}
			argv++;
			c = (int)strtol(cp, &ep, 10);
			if (*ep)
				error(ERROR_exit(1), "%s: %s: numeric argument expected", tp->name, cp);
			switch (tp->field)
			{
#if _mem_c_line_termios
			case C_LINE:
				sp->c_line = c;
				break;
#endif
			case C_SPEED:
				if(getspeed(c))
				{
					if (*tp->name != 'o')
						cfsetispeed(sp, c);
					if (*tp->name != 'i')
						cfsetospeed(sp, c);
				}
				else
					error(ERROR_exit(1), "%s: %s: invalid speed", tp->name, cp);
				break;
			case T_CHAR:
				sp->c_cc[tp->mask] = c;
				break;
			}
			break;
		    case SPEED:
			cfsetospeed(sp, tp->mask);
			cfsetispeed(sp, tp->mask);
			break;
		    case SIZE:
			sp->c_cflag &= ~CSIZE;
			sp->c_cflag |= tp->mask;
			break;
		    case SANE:
			sane(sp);
			break;
#if defined(OLCUC) && defined(IUCLC)
		    case CASE:
			if(off)
			{
				sp->c_iflag |= IUCLC;
				sp->c_oflag |= OLCUC;
			}
			else
			{
				sp->c_iflag &= ~IUCLC;
				sp->c_oflag &= ~OLCUC;
			}
			break;
#endif /* OLCUC && IUCLC */
		}
	}
}