/* * system: various support routines for the shell. * * includes: * makepipe() - creates a pipeline, returning a pair of file descriptors. * multitask()- returns YES if the o/s can do multitasking today. * freepipe() - cleans up a pipeline. * kickpipe() - shakes reluctant bits out of the pipeline. * glob() - expands wildcards. */ #define INCL_DOS #include #include #include #include #include "tsh.h" #include "execute.h" #include "system.h" #include "glob.h" #include "args.h" /* * multitask() tells the caller whether or not we're a multitasking system * or not. In the case of os/2, we probably are. */ multitask() { return 1; } /* multitask */ /* * makepipe() generates a pipeline. */ int makepipe(p) struct pipedesc *p; { if (DosMakePipe(&p->p_rdd, &p->p_wrd, 0) != 0) { fprintf(stderr, "tsh: couldn't make pipe.\n"); return (status = ST_SERR); } return 0; } /* makepipe */ /* * freepipe() releases a pipe after we're done with it */ void freepipe(p) struct pipedesc *p; { if (p->p_wrd != -1) close(p->p_wrd); close(p->p_rdd); } /* freepipe */ /* * kickpipe() knocks bits out of a pipe */ kickpipe(p) struct pipedesc *p; { close(p->p_wrd); p->p_wrd = -1; return 0; } /* kickpipe */ /* * glob() expands a wildcard, via calls to DosFindFirst/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 FILEFINDBUF ffb; /* DOS & OS/2 dta */ static int dir; /* directory handle */ register st; /* status from DosFindxxx */ int count=1; /* how many files to find */ 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; dir = HDIR_SYSTEM; if (isdotpattern = (*file_part == '.')) /* DosFindFirst() 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 = DosFindFirst(path, &dir, 0x16, &ffb, sizeof ffb, &count, 0L); } else st = DosFindNext(dir, &ffb, sizeof ffb, &count); while (st == 0 && count > 0) { /* Unless the pattern has a leading ., don't include any file * that starts with . */ if (ffb.achName[0] == '.' && !isdotpattern) { count = 1; st = DosFindNext(dir, &ffb, sizeof ffb, &count); } else { /* found a file - affix the path leading to it, then return * a pointer to the (static) buffer holding the path+the name. */ strlwr(ffb.achName); /* DOS & OS/2 are case-insensitive */ if (dta_bfr) { memcpy(&dta_bfr->wr_date, &ffb.fdateLastWrite, sizeof(short)); memcpy(&dta_bfr->wr_time, &ffb.ftimeLastWrite, sizeof(short)); if (isdotordotdot) strcpy(dta_bfr->name, file_part); else { strncpy(dta_bfr->name, ffb.achName, sizeof(dta_bfr->name)-1); dta_bfr->name[sizeof(dta_bfr->name)-1] = 0; } dta_bfr->size = ffb.cbFile; dta_bfr->attrib = ffb.attrFile; } if (!isdotordotdot) strcpy(file_part, ffb.achName); 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 */ /* * job "control" structures, so we can say when a job has ended in a nice * way. */ struct job_t { char cmd[80]; /* job (program) name + first part of arglist */ int pid; /* process-id of this puppy */ int flags; /* is this particular job alive? */ #define JOB_ACTIVE 1 } ; /* * reasons a job ended */ static char *exitreason[] = { "Done", "Bus error", "Segmentation violation", "Killed" } ; static struct job_t *jobs = (struct job_t*)0; static int job_count=0; /* * jobslot() puts interesting information about a background job into the * jobs table. */ static void jobslot(cmdline, pid) char *cmdline; { register i; register char *p; /* the commandline will have nulls it it - we'll replace them * with spaces for a nice display */ for (p = cmdline;; ++p) if (*p == 0) { *p = ' '; if (p[1] == 0) break; } if (job_count==0) jobs = malloc(1); for (i=0; iargc; i++) siz += (1+strlen(args->argv[i])); if (arguments=malloc(1+siz)) { for (siz=i=0; iargc; i++) { if (i>1) arguments[siz-1] = ' '; strcpy(arguments+siz, args->argv[i]); siz += (1+strlen(args->argv[i])); } arguments[siz] = 0; } else { no_more_core(); return ST_SERR; } if (DosExecPgm(fail, sizeof fail, execmode, arguments, env, &status, pathto) != 0) { fprintf(stderr, "%s: permission denied\n", args->argv[0]); return ST_NOT; } else if (mode==RUN_ASYNC) { /* save info on background processes for later */ jobslot(arguments, status.codeTerminate); return 0; } else if (mode==RUN_PIPE) return 0; if (status.codeTerminate == TC_EXIT) return status.codeResult; fprintf(stderr, "%s\n", exitreason[status.codeTerminate]); return (status.codeTerminate==TC_KILLPROCESS) ? 1 : ST_SERR; } /* doexec */ /* * jobstatus() tells us how many processes are running in background */ jobstatus() { register i, st; RESULTCODES status; short pid; while (DosCwait(0, 1, &status, &pid, 0) == 0) for (i=0; i