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); }
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; }
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; }
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; }
/* * 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); }
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); }
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); }
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; }
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; }
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; }
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); }
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); }
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; }
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); }
// 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; }
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; }
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; }
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; }
/* * 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; } }
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; }
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--; }
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; }
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); }
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; }
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; }
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; }
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); }
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 */ } } }