/* * system: various support routines for the shell. (DOS) * * includes: * makepipe() - creates a pipeline, returning a pipeline descriptor. * multitask()- returns YES if the o/s can do multitasking today. * freepipe() - redirects a file descriptor to someplace else. * kickpipe() - beats upon the pipe to shake data out. * glob() - expands wildcards. * doexec() - run some program. * jobstatus()- tells us whether child processes have finished or not. * sysinit() - initializes various system things at startup. * ttygetc() - get a character. */ #include #include #include #include #include "system.h" #include "execute.h" #include "tsh.h" #include "glob.h" #include "args.h" extern char *mmalloc(); /* * multitask() informs the caller that we don't multitask here */ multitask() { return 0; } /* multitask */ /* * makepipe() generates a pipe descriptor connected to a temporary * file. */ makepipe(p) struct pipedesc *p; { char template[180]; char *tmp = getenv("TMP"); int seq = 0; if (tmp == (char*)0) tmp = "."; do { sprintf(template, "%s/shp%04x.tmp", tmp, seq++); p->p_wrd = open(template, O_RDWR|O_BINARY|O_CREAT|O_EXCL, 0666); } while (p->p_wrd < 0 && seq > 0); if (seq < 0) /* too many open tempfiles */ fprintf(stderr, "too many open tempfiles.\n"); else if ((p->p_tmpfile = mmalloc(strlen(template)+1)) == (char*)0) fprintf(stderr, "out of memory.\n"); else { strcpy(p->p_tmpfile, template); return 0; } return (status=ST_SERR); } /* makepipe */ /* * freepipe() returns a pipeline back to whence it came */ void freepipe(p) struct pipedesc *p; { if (p->p_wrd != EOF) close(p->p_wrd); close(p->p_rdd); unlink(p->p_tmpfile); mfree(p->p_tmpfile); } /* freepipe */ /* * kickpipe() shakes bits out of the pipe */ kickpipe(p) struct pipedesc *p; { close(p->p_wrd); p->p_wrd = EOF; if ((p->p_rdd = open(p->p_tmpfile, O_RDONLY|O_BINARY)) < 0) { fprintf(stderr, "can't read from pipe.\n"); return (status=ST_SERR); } return 0; } /*kickpipe*/ /* * glob() expands a wildcard, via calls to _dos_findfirst/_next() * and pathname retention. */ char * glob(path, dta) char *path; struct glob_t *dta; { static char path_bfr[256]; /* full pathname to return */ static char *file_part; /* points at file - for filling */ static char isdotpattern; /* looking for files starting with . */ static char isdotordotdot; /* special case . or .. */ static struct glob_t *dta_bfr; /* pointer to desired dta */ static struct find_t dird; /* DOS dta */ register st; /* status from _dos_findxxx */ if (path) { /* when we start searching, save the path part of the filename in * a safe place. */ strcpy(path_bfr, path); file_part = basename(path_bfr); /* set up initial parameters for DosFindFirst() */ dta_bfr = dta; if (isdotpattern = (*file_part == '.')) /* _dos_findfirst() magically expands . and .. into their * directory names. Admittedly, there are cases where * this can be useful, but this is not one of them. So, * if we find that we're matching . and .., we just * special-case ourselves into oblivion to get around * this particular bit of DOS silliness. */ isdotordotdot = (file_part[1] == 0 || file_part[1] == '.'); else isdotordotdot = 0; st = _dos_findfirst(path, 0x16, &dird); } else st = _dos_findnext(&dird); while (st == 0) { /* Unless the pattern has a leading ., don't include any file * that starts with . */ if (dird.name[0] == '.' && !isdotpattern) st = _dos_findnext(&dird); else { /* found a file - affix the path leading to it, then return * a pointer to the (static) buffer holding the path+the name. */ strlwr(dird.name); /* DOS & OS/2 are case-insensitive */ if (dta_bfr) { dta_bfr->wr_time = dird.wr_time; dta_bfr->wr_date = dird.wr_date; if (isdotordotdot) strcpy(dta_bfr->name, file_part); else { strncpy(dta_bfr->name, dird.name, sizeof(dta_bfr->name)-1); dta_bfr->name[sizeof(dta_bfr->name)-1] = 0; } dta_bfr->size = dird.size; dta_bfr->attrib = dird.attrib; } if (!isdotordotdot) strcpy(file_part, dird.name); return path_bfr; } } /* nothing matched */ if (path && isdotordotdot) { /* must be at root, so statting dot will most likely fail. Fake a * dta. */ if (dta_bfr) { memset(dta_bfr, 0, sizeof *dta_bfr); dta_bfr->attrib = 0x10; dta_bfr->name[0] = '.'; } return path_bfr; } return (char*)0; } /* glob */ /* pexec() runs a program, returning the status as a coded long: * low 16 bits are program status, unless sign bit is set, then * they are a failure status: * (st & 0xffff) == 2 means not found, for example. */ extern long far pexec(int, char far *, char far *, char far *); /* * doexec() runs a program */ doexec(mode, pathto, args, env) char *pathto, *env; struct arg_t *args; { char tail[128]; register long st; register siz, i; extern void _cdecl _interrupt _far intr_on_ctrlc(); extern void _cdecl _interrupt _far ignore_ctrlc(); /* build commandline so pexec() can have something to stuff into * a DTA */ memset(tail, 0, sizeof tail); for (siz=0, i=1; iargc; i++) { siz += (1+strlen(args->argv[i])); if (siz >= 128) break; strcat(tail, " "); strcat(tail, args->argv[i]); } tail[0] = strlen(1+tail); tail[strlen(1+tail)] = 0x80; _dos_setvect(0x23, intr_on_ctrlc); st = pexec(0, pathto, tail, env); _dos_setvect(0x23, ignore_ctrlc); if (st < 0) { fprintf(stderr, "%s: permission denied\n", pathto); return ST_NOT; } else return 0xff & st; } /* doexec */ /* * jobstatus() tells us how many jobs are still running */ jobstatus() { return 0; } /* jobstatus */ /* * sysinit() sets up our ^C and critical error handlers */ sysinit() { extern void _cdecl _interrupt _far fail_criterr(); extern void _cdecl _interrupt _far ignore_ctrlc(); _dos_setvect(0x23, ignore_ctrlc); _dos_setvect(0x24, fail_criterr); } /* sysinit */ /* * ttygetc() - gets a character from the outside world */ ttygetc() { extern char _far crawcin(); fflush(stdout); return crawcin(); }