/* * COMM1.C * * (c)1986 Matthew Dillon 9 October 1986 * * SLEEP * NUMBER -handles values as commands, actually a NULL command. * CAT * DIR -also handles DEVINFO * QUIT -also handles EXIT * ECHO * SOURCE * CD * MKDIR * MV * RM * HISTORY * MEM * FOREACH * FOREVER * * NOTE: SET/UNSET/ALIAS/UNALIAS handled in SET.C * */ #include #include #include #include #include #include "shell.h" typedef struct FileInfoBlock FIB; typedef struct FileLock LOCK; extern struct FileLock *CreateDir(), *CurrentDir(), *ParentDir(); extern struct FileLock *Lock(), *DupLock(); extern char *AllocMem(); extern long disp_entry(); struct FileLock *Clock; do_sleep() { register int i; if (ac == 2) { i = atoi(av[1]); while (i > 0) { Delay (50*2); i -= 2; if (CHECKBREAK()) break; } } return (0); } do_number() { return (0); } do_cat() { long fi; short i; char buf[256]; if (ac == 1) { while (Ogets(buf)) Oputs(buf); return (0); } for (i = 1; i < ac; ++i) { if (fi = xopen (av[i], "r", 512)) { while (xgets (fi, buf, 256)) { Oputs(buf); if (CHECKBREAK()) break; } xclose (fi); } else { fprintf (Cerr, "could not open %s\n", av[i]); } } return (0); } do_dir(garbage, com) char *garbage; { register struct DPTR *dp; register struct InfoData *info; char *name; register short i; int stat; short longmode = 0; register long total = 0; if (strcmp(av[1], "-l") == 0) longmode = 1; if (ac == 1 + longmode) av[ac++] = ""; for (i = longmode + 1; i < ac; ++i) { if ((dp = dopen (av[i], &stat)) == NULL) continue; if (com < 0) { info = (struct InfoData *)AllocMem(sizeof(struct InfoData), MEMF_PUBLIC); if (Info (dp->lock, info)) { int bpb = info->id_BytesPerBlock; fprintf (Cout, "Unit:%2ld Errs:%3ld Bytes: %-7ld Free: %-7ld %%full: %ld\n", info->id_UnitNumber, info->id_NumSoftErrors, bpb * info->id_NumBlocks, bpb * (info->id_NumBlocks - info->id_NumBlocksUsed), info->id_NumBlocksUsed * 100 / info->id_NumBlocks); } else { perror (av[i]); } FreeMem (info, sizeof(*info)); } else { if (stat) { while (dnext (dp, &name, &stat)) { total += disp_entry (dp->fib, longmode); if (CHECKBREAK()) break; } } else { total += disp_entry(dp->fib, longmode); } } dclose (dp); } fprintf (Cout, "TOTAL: %ld\n", total); return (0); } char * datetos(d) register struct DateStamp *d; { static char stamp[32]; static char dim[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static char *Month[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul", "Aug","Sep","Oct","Nov","Dec" }; register long day, month, year, scr; day = d->ds_Days; /* iteration (could be done w/equations) */ year = 1978; while (day >= (scr = ((year&3)|!(year%100)) ? 365 : 366)) { ++year; day -= scr; } dim[1] = ((year&3)|!(year%100)) ? 28 : 29; for (month = 0; day >= dim[month]; (day -= dim[month]), ++month); sprintf(stamp, "%2ld %s %2ld:%ld%ld %4ld", day + 1, Month[month], d->ds_Minute/60, d->ds_Minute%60/10, d->ds_Minute%10, year); return (stamp); } static long disp_entry(fib, lengthy) register struct FileInfoBlock *fib; { char str[5]; register char *dirstr; str[4] = '\0'; str[0] = (fib->fib_Protection & FIBF_READ) ? '-' : 'r'; str[1] = (fib->fib_Protection & FIBF_WRITE) ? '-' : 'w'; str[2] = (fib->fib_Protection & FIBF_EXECUTE) ? '-' : 'x'; str[3] = (fib->fib_Protection & FIBF_DELETE) ? '-' : 'd'; dirstr = (fib->fib_DirEntryType < 0) ? " " : "DIR"; fprintf (Cout, "%s %6ld %s %-20s", str, (long)fib->fib_Size, dirstr, fib->fib_FileName); if (lengthy) fprintf (Cout, " %s\n", datetos(&fib->fib_Date)); else fprintf (Cout, "\n"); return ((long)fib->fib_Size); } do_quit() { if (Src_stack) { Quit = 1; return(do_return()); } main_exit (0); } do_echo(str) char *str; { register char *ptr; char nl = 1; for (ptr = str; *ptr && *ptr != ' '; ++ptr); if (*ptr == ' ') ++ptr; if (av[1] && strcmp (av[1], "-n") == 0) { nl = 0; ptr += 2; if (*ptr == ' ') ++ptr; } Write(Cout, ptr, strlen(ptr)); if (nl) Oputs(""); return (0); } do_source(str) char *str; { register long fi; char buf[256]; if (Src_stack == MAXSRC) { Eputs ("Too many source levels"); return(-1); } fi = xopen (av[1], "r", 512); if (fi == 0) { fprintf (Cerr, "Cannot open %s\n", next_word(str)); return(-1); } set_var(LEVEL_SET, V_PASSED, next_word(next_word(str))); ++H_stack; Src_pos[Src_stack] = 0; Src_base[Src_stack] = fi; ++Src_stack; while (xgets (fi, buf, 256)) { Src_pos[Src_stack - 1] += 1+strlen(buf); if (Verbose) Eputs(buf); exec_command (buf); if (CHECKBREAK()) break; } --H_stack; --Src_stack; unset_level(LEVEL_LABEL + Src_stack); unset_var(LEVEL_SET, V_PASSED); xclose (fi); return (0); } /* * CD * * CD(str, -1) -do pwd and display current cd. if str = NULL don't disp. * CD(str, 0) -do CD operation. * * standard operation: breakup path by '/'s and process independantly * x: -reset cwd base * .. -remove last cwd element * N -add N or /N to cwd */ do_cd(str, com) register char *str; { static char cwd[256]; register char sc, *ptr; char *name; if (com < 0) { register struct FileLock *lock, *newlock; register FIB *fib; short i, len; fib = (FIB *)AllocMem(sizeof(FIB), 0); Clock = (struct FileLock *)((struct Process *)FindTask(0))->pr_CurrentDir; if (!Clock) CurrentDir(Clock = Lock(":", ACCESS_READ)); lock = DupLock(Clock); cwd[i = 255] = '\0'; while (lock) { newlock = ParentDir(lock); Examine(lock, fib); name = fib->fib_FileName; if (*name == '\0') /* HACK TO FIX RAM: DISK BUG */ name = "ram"; len = strlen(name); if (newlock) { if (i == 255) { i -= len; bmov(name, cwd + i, len); } else { i -= len + 1; bmov(name, cwd + i, len); cwd[i+len] = '/'; } } else { i -= len + 1; bmov(name, cwd + i, len); cwd[i+len] = ':'; } UnLock(lock); lock = newlock; } FreeMem(fib, sizeof(FIB)); bmov(cwd + i, cwd, 256 - i); if (str) Oputs(cwd); goto cdset; } str = next_word(str); if (*str == '\0') Oputs(cwd); str[strlen(str)+1] = '\0'; /* add second \0 on end */ while (*str) { for (ptr = str; *ptr && *ptr != '/' && *ptr != ':'; ++ptr); switch (*ptr) { case ':': sc = ptr[1]; ptr[1] = '\0'; if (attempt_cd(str)) strcpy(cwd, str); ptr[1] = sc; break; case '\0': case '/': *ptr = '\0'; if (strcmp(str, "..") == 0 || str == ptr) str = "/"; if (*str && attempt_cd(str)) { if (*str == '/') { rmlast(cwd); } else { if (cwd[0] == 0 || cwd[strlen(cwd)-1] != ':') strcat(cwd, "/"); strcat(cwd, str); } } break; } str = ptr + 1; } cdset: set_var(LEVEL_SET, V_CWD, cwd); return (0); } attempt_cd(str) char *str; { register struct FileLock *oldlock, *filelock; if (filelock = Lock(str, ACCESS_READ)) { if (isdir(str)) { if (oldlock = CurrentDir(filelock)) UnLock(oldlock); Clock = filelock; return (1); } UnLock(filelock); ierror(str, 212); } else { ierror(str, 205); } return (0); } /* * remove last component. Start at end and work backwards until reach * a '/' */ rmlast(str) char *str; { register char *ptr = str + strlen(str) - 1; while (ptr != str && *ptr != '/' && *ptr != ':') --ptr; if (*ptr != ':') ptr[0] = '\0'; else ptr[1] = '\0'; } do_mkdir() { register short i; register struct FileLock *lock; for (i = 1; i < ac; ++i) { if (lock = CreateDir (av[i])) { UnLock (lock); continue; } perror (av[i]); } return (0); } do_mv() { char dest[256]; register short i; register char *str; --ac; if (isdir(av[ac])) { for (i = 1; i < ac; ++i) { str = av[i] + strlen(av[i]) - 1; while (str != av[i] && *str != '/' && *str != ':') --str; if (str != av[i]) ++str; if (*str == 0) { ierror(av[i], 508); return (-1); } strcpy(dest, av[ac]); if (dest[strlen(dest)-1] != ':') strcat(dest, "/"); strcat(dest, str); if (Rename(av[i], dest) == 0) break; } if (i == ac) return (1); } else { i = 1; if (ac != 2) { ierror("rm:", 507); return (-1); } if (Rename (av[1], av[2])) return (0); } perror (av[i]); return (-1); } do_rm() { register short i, recur; recur = (strncmp(av[1], "-r", 2)) ? 0 : 1; for (i = 1 + recur; i < ac; ++i) { if (isdir(av[i]) && recur) rmdir(av[i]); if (!DeleteFile(av[i])) perror(av[i]); } return (0); } rmdir(name) char *name; { register LOCK *lock, *cwd; register FIB *fib; register char *buf; buf = (char *)AllocMem(256, 0); fib = (FIB *)AllocMem(sizeof(FIB), 0); if (lock = Lock(name, ACCESS_READ)) { cwd = CurrentDir(lock); if (Examine(lock, fib)) { buf[0] = 0; while (ExNext(lock, fib)) { if (isdir(fib->fib_FileName)) rmdir(fib->fib_FileName); if (buf[0]) { if (!DeleteFile(buf)) perror(buf); } strcpy(buf, fib->fib_FileName); } if (buf[0]) { if (!DeleteFile(buf)) perror(buf); } } UnLock(CurrentDir(cwd)); } else { perror(name); } FreeMem(fib, sizeof(FIB)); FreeMem(buf, 256); } do_history() { register struct HIST *hist; register short i = H_tail_base; register short len = (av[1]) ? strlen(av[1]) : 0; for (hist = H_tail; hist; hist = hist->prev) { if (len == 0 || strncmp(av[1], hist->line, len) == 0) { fprintf (Cout, "%3ld ", i); Oputs (hist->line); } ++i; if (CHECKBREAK()) break; } return (0); } do_mem() { register long cfree, ffree; extern long AvailMem(); Forbid(); cfree = AvailMem (MEMF_CHIP); ffree = AvailMem (MEMF_FAST); Permit(); if (ffree) fprintf (Cout, "FAST memory:%10ld\n", ffree); fprintf (Cout, "CHIP memory:%10ld\n", cfree); fprintf (Cout, "Total -----:%5ld K\n", (ffree + cfree) >> 10); return (0); } /* * foreach var_name ( str str str str... str ) commands * spacing is important (unfortunetly) * * ac=0 1 2 3 4 5 6 7 * foreach i ( a b c ) echo $i * foreach i ( *.c ) "echo -n "file ->";echo $i" */ do_foreach() { register short i, cstart, cend, old; register char *cstr, *vname, *ptr, *scr, *args; cstart = i = (*av[2] == '(') ? 3 : 2; while (i < ac) { if (*av[i] == ')') break; ++i; } if (i == ac) { Eputs ("')' expected"); return (-1); } ++H_stack; cend = i; vname = strcpy(malloc(strlen(av[1])+1), av[1]); cstr = compile_av (av, cend + 1, ac); ptr = args = compile_av (av, cstart, cend); while (*ptr) { while (*ptr == ' ' || *ptr == 9) ++ptr; scr = ptr; if (*scr == '\0') break; while (*ptr && *ptr != ' ' && *ptr != 9) ++ptr; old = *ptr; *ptr = '\0'; set_var (LEVEL_SET, vname, scr); if (CHECKBREAK()) break; exec_command (cstr); *ptr = old; } --H_stack; free (args); free (cstr); unset_var (LEVEL_SET, vname); free (vname); return (0); } do_forever(str) register char *str; { long rcode = 0; register char *ptr = next_word(str); ++H_stack; for (;;) { if (CHECKBREAK()) { rcode = 20; break; } if (exec_command (ptr) < 0) { str = get_var(LEVEL_SET, V_LASTERR); rcode = (str) ? atoi(str) : 20; break; } } --H_stack; return (rcode); }