/* * COMM1.C * * Matthew Dillon, August 1986 * * version 2.05M (Manx Version and Additions) by Steve Drew 20-Jan-87 * */ #include "shell.h" typedef struct FileInfoBlock FIB; #define DIR_SHORT 0x01 #define DIR_FILES 0x02 #define DIR_DIRS 0x04 #define DIR_EXCLUDE 0x08 #define BPTR_TO_C(strtag, var) ((struct strtag *)(BADDR( (ULONG) var))) #define C_TO_BPTR(strtag, var) ((struct strtag *)(((ULONG)var)>>2)) extern char *btocstr(); extern int has_wild; char cwd[256]; struct FileLock *Clock; do_sleep() { register int i; if (ac == 2) { i = atoi(av[1]); while (i > 0) { Delay ((long)50*2); i -= 2; if (CHECKBREAK()) break; } } return (0); } do_number() { return (0); } do_cat() { FILE *fopen(), *fi; int i; char buf[256]; if (ac == 1) { while (gets(buf)) { if (CHECKBREAK()) break; puts(buf); } clearerr(stdin); return (0); } for (i = 1; i < ac; ++i) { if ((fi = fopen (av[i], "r")) != 0) { while (fgets(buf,256,fi)) { fputs(buf,stdout); fflush(stdout); if (CHECKBREAK()) { breakreset(); break; } } fclose (fi); } else { fprintf (stderr, "could not open %s\n", av[i]); } } return (0); } /* things shared with disp_entry */ int filecount, col; long bytes, blocks; do_dir(garbage, com) char *garbage; { void disp_entry(); struct DPTR *dp; struct InfoData *info; char *name; int i = 0, stat, clen, more; char options = 0; char *c; char exclude[40]; char lspec[256]; char volume[40]; char *volname(); char *dates(); col = filecount = 0; bytes = blocks = 0L; while((++i < ac) && (av[i][0] == '-')) { for (c = av[i]+1; *c ; c++) { switch(*c) { case 's': options |= DIR_SHORT; break; case 'f': options |= DIR_FILES; break; case 'd': options |= DIR_DIRS; break; case 'e': options |= DIR_EXCLUDE; strcpy(exclude,"*"); strcat(exclude,av[++i]); strcat(exclude,"*"); break; default: break; } } } if (ac == i) { ++ac; av[i] = ""; if (has_wild) return(0); } if (!(options & (DIR_FILES | DIR_DIRS))) options |= (DIR_FILES | DIR_DIRS); for (; i < ac; ++i) { if (!(dp = dopen (av[i], &stat))) continue; if (com < 0) { info = (struct InfoData *)AllocMem((long)sizeof(struct InfoData), MEMF_PUBLIC); if (Info (dp->lock, info)) { printf ("Unit:%2ld Errs:%3ld Used: %-4ld %3ld%% Free: %-4ld Volume: %s\n", info->id_UnitNumber, info->id_NumSoftErrors, info->id_NumBlocksUsed, (info->id_NumBlocksUsed * 100)/ info->id_NumBlocks, (info->id_NumBlocks - info->id_NumBlocksUsed), volname(dp->lock,volume)); } else { pError (av[i]); } FreeMem (info,(long) sizeof(*info)); dclose(dp); continue; return(0); } /* start of directory routine */ c = av[i]; clen = strlen(c); if (!stat || has_wild) { /* if not wild and is a dir don't */ /* extract dir from file name */ while (clen && c[clen] != '/' && c[clen] != ':') clen--; if (c[clen] == ':' || c[clen] == '/') clen++; c[clen] = '\0'; } if (!clen) c = cwd; if (strcmp (c, &lspec) != 0) { strcpy(lspec, c); if (col) printf("\n"); printf ("Directory of %s\n", lspec); fflush(stdout); col = 0; } more = stat; do { if (more && !has_wild) { *lspec = '\0'; if (!(more = dnext(dp, &name, &stat))) break; } if (CHECKBREAK()) { i = ac; break; } disp_entry (dp->fib, options,exclude); } while(more && !has_wild); dclose(dp); } /* end for */ if (col) printf("\n"); if (filecount > 1) { blocks += filecount; /* account for dir blocks */ printf (" %ld Blocks, %ld Bytes used in %d files\n", blocks, bytes, filecount); } return (0); } char * volname(lock,buf) struct FileLock *lock; char *buf; { struct DeviceList *dl; char *p; Forbid(); /* Only way I know to get Volume label since InfoData */ /* seems to always have NULL for this string */ lock = BPTR_TO_C(FileLock, lock); dl = BPTR_TO_C(DeviceList, lock->fl_Volume); p = btocstr(dl->dl_Name,buf); Permit(); return p; } void disp_entry(fib, options, exclude) char options; char *exclude; register struct FileInfoBlock *fib; { char str[5]; int italics; char s; if (!(((options & DIR_FILES) && (fib->fib_DirEntryType < 0)) || ((options & DIR_DIRS) && (fib->fib_DirEntryType > 0)))) return; if ((options & DIR_EXCLUDE) && (compare_ok(exclude,fib->fib_FileName))) return; if (!(options & DIR_SHORT)) { 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) ? '-' : 'e'; str[3] = (fib->fib_Protection & FIBF_DELETE) ? '-' : 'd'; printf (" %-24s %s ", fib->fib_FileName, str); if (fib->fib_DirEntryType < 0) printf("%6ld %4ld", (long)fib->fib_Size, (long)fib->fib_NumBlocks); else printf(" Dir "); printf(" %s", dates(&fib->fib_Date)); fflush(stdout); } else { if ((col == 3) && strlen(fib->fib_FileName)>18) { printf("\n"); col = 0; } if (fib->fib_DirEntryType > 0) { printf ("\033[3m"); italics = 1; } if (strlen(fib->fib_FileName)>18) { printf(" %-37s",fib->fib_FileName); col += 2; } else { printf(" %-18s",fib->fib_FileName); col++; } if (col > 3) { printf("\n"); col = 0; } if (italics) printf("\033[0m"); } fflush(stdout); blocks += fib->fib_NumBlocks; bytes += fib->fib_Size; filecount++; return; } /* converts dos date stamp to a time string of form dd-mmm-yy */ char * dates(dss) struct DateStamp *dss; { register struct tm tm; register long time, t; register int i; static char timestr[20]; static char months[12][4] = { "Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec" }; static char days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; time = dss->ds_Days * 24 * 60 * 60 + dss->ds_Minute * 60 + dss->ds_Tick/TICKS_PER_SECOND; tm.tm_sec = time % 60; time /= 60; tm.tm_min = time % 60; time /= 60; tm.tm_hour= time % 24; time /= 24; tm.tm_wday= time % 7; tm.tm_year= 78 + (time/(4*365+1)) * 4; time %= 4 * 365 + 1; while (time) { t = 365; if ((tm.tm_year&3) == 0) t++; if (time < t) break; time -= t; tm.tm_year++; } tm.tm_yday = ++time; for (i=0;i<12;i++) { t = days[i]; if (i == 1 && (tm.tm_year&3) == 0) t++; if (time <= t) break; time -= t; } tm.tm_mon = i; tm.tm_mday = time; sprintf(timestr,"%02d-%s-%2d %02d:%02d:%02d\n",tm.tm_mday, months[tm.tm_mon],tm.tm_year, tm.tm_hour,tm.tm_min,tm.tm_sec); return(timestr); } date() { struct DateStamp dss; char *s, *dates(); DateStamp(&dss); s = dates(&dss); printf("%s",s); return(0); } 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; } printf("%s",ptr); fflush(stdout); if (nl) printf("\n"); return (0); } do_source(str) char *str; { register FILE *fi; char buf[256]; if (Src_stack == MAXSRC) { printf (stderr,"Too many source levels\n"); return(-1); } if ((fi = fopen (av[1], "r")) == 0) { fprintf (stderr,"Cannot open %s\n", av[1]); return(-1); } set_var(LEVEL_SET, V_PASSED, next_word(next_word(str))); ++H_stack; Src_pos[Src_stack] = 0; Src_base[Src_stack] = (long)fi; ++Src_stack; while (fgets (buf, 256, fi)) { buf[strlen(buf)-1] = '\0'; Src_pos[Src_stack - 1] += 1+strlen(buf); if (Verbose) fprintf(stderr,"%s\n",buf); exec_command (buf); if (CHECKBREAK()) break; } --H_stack; --Src_stack; unset_level(LEVEL_LABEL + Src_stack); unset_var(LEVEL_SET, V_PASSED); fclose (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) char *str; { char sc, *ptr; char *name; if (com < 0) { struct FileLock *lock, *newlock; FIB *fib; int i, len; fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC); if ((Clock = (struct FileLock *)Myprocess->pr_CurrentDir) == 0) attempt_cd(":"); /* if we just booted 0 = root lock */ lock = (struct FileLock *)DupLock(Clock); cwd[i = 255] = '\0'; while (lock) { newlock = (struct FileLock *)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, (long)sizeof(FIB)); bmov(cwd + i, cwd, 256 - i); if (str) puts(cwd); set_var(LEVEL_SET, V_CWD, cwd); /* put the current dir name in our CLI task structure */ ptr = (char *)((ULONG)((struct CommandLineInterface *) BADDR(Myprocess->pr_CLI))->cli_SetName << 2); ptr[0] = strlen(cwd); movmem(cwd,ptr+1,(int)ptr[0]); return (0); } str = next_word(str); if (*str == '\0') puts(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; } do_cd(NULL,-1); } attempt_cd(str) char *str; { struct FileLock *oldlock, *filelock; if (filelock = (struct FileLock *)Lock(str, ACCESS_READ)) { if (isdir(str)) { if (oldlock = (struct FileLock *)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; { char *ptr = str + strlen(str) - 1; while (ptr != str && *ptr != '/' && *ptr != ':') --ptr; if (*ptr != ':') ptr[0] = '\0'; else ptr[1] = '\0'; } do_mkdir() { register int i; register struct FileLock *lock; for (i = 1; i < ac; ++i) { if (lock = (struct FileLock *)CreateDir (av[i])) { UnLock (lock); continue; } pError (av[i]); } return (0); } do_mv() { char dest[256]; register int i; 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("", 507); return (-1); } if (Rename (av[1], av[2])) return (0); } pError (av[i]); return (-1); } rm_file(file) char *file; { if (has_wild) printf(" %s...",file); fflush(stdout); if (!DeleteFile(file)) pError (file); else if (has_wild) printf("Deleted\n"); } do_rm() { register short i, recur; recur = (strncmp(av[1], "-r", 2)) ? 0 : 1; for (i = 1 + recur; i < ac; ++i) { if (CHECKBREAK()) break; if (isdir(av[i]) && recur) rmdir(av[i]); if (!(recur && av[i][strlen(av[i])-1] == ':')) rm_file(av[i]); } return (0); } rmdir(name) char *name; { register struct FileLock *lock, *cwd; register FIB *fib; register char *buf; buf = (char *)AllocMem(256L, MEMF_PUBLIC); fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC); if (lock = (struct FileLock *)Lock(name, ACCESS_READ)) { cwd = (struct FileLock *) CurrentDir(lock); if (Examine(lock, fib)) { buf[0] = 0; while (ExNext(lock, fib)) { if (CHECKBREAK()) break; if (isdir(fib->fib_FileName)) rmdir(fib->fib_FileName); if (buf[0]) { rm_file(buf); } strcpy(buf, fib->fib_FileName); } if (buf[0] && !CHECKBREAK()) { rm_file(buf); } } UnLock(CurrentDir(cwd)); } else { pError(name); } FreeMem(fib, (long)sizeof(FIB)); FreeMem(buf, 256L); } do_history() { register struct HIST *hist; register int i = H_tail_base; register int 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) { printf ("%3d ", i); puts (hist->line); } ++i; if (CHECKBREAK()) break; } return (0); } do_mem() { long cfree, ffree; extern long AvailMem(); Forbid(); cfree = AvailMem (MEMF_CHIP); ffree = AvailMem (MEMF_FAST); Permit(); if (ffree) { printf ("FAST memory: %ld\n", ffree); printf ("CHIP memory: %ld\n", cfree); } printf ("Total Free: %ld\n", cfree + ffree); 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 int 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) { fprintf (stderr,"')' expected\n"); 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) char *str; { int rcode = 0; 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); } /* * CP file file * CP file file file... destdir * CP [-r] dir dir dir... destdir */ char *errstr; /* let's be alittle more informative */ do_copy() { register short recur, i, ierr; register char *destname; register char destisdir; register FIB *fib; errstr = ""; ierr = 0; fib = (FIB *)AllocMem((long)sizeof(FIB), 0); recur = (strncmp(av[1], "-r", 2)) ? 0 : 1; destname = av[ac - 1]; if (ac < recur + 3) { ierr = 500; goto done; } destisdir = isdir(destname); if (ac > recur + 3 && !destisdir) { ierr = 507; goto done; } /* * copy set: reduce to: * file to file file to file * dir to file (NOT ALLOWED) * file to dir dir to dir * dir to dir dir to dir * */ fflush(stdout); stdout->_buflen = 1; for (i = recur + 1; i < ac - 1; ++i) { short srcisdir = isdir(av[i]); if (srcisdir && has_wild && (ac >2)) /* hack to stop dir's from */ continue; /* getting copied if specified */ /* from wild expansion */ if (CHECKBREAK()) break; if (srcisdir) { struct FileLock *srcdir, *destdir; if (!destisdir) { /* disallow dir to file */ ierr = 507; goto done; } if (!(destdir = (struct FileLock *)Lock(destname, ACCESS_READ))) { ierr = 205; errstr = destname; goto done; } if (!(srcdir = (struct FileLock *)Lock(av[i], ACCESS_READ))) { ierr = 205; errstr = av[i]; UnLock(destdir); goto done; } ierr = copydir(srcdir, destdir, recur); UnLock(srcdir); UnLock(destdir); if (ierr) break; } else { /* FILE to DIR, FILE to FILE */ struct FileLock *destdir, *srcdir, *tmp; char *destfilename; srcdir = (struct FileLock *)((struct Process *)FindTask(0))->pr_CurrentDir; if (destisdir) { if ((tmp = (struct FileLock *)Lock(av[i], ACCESS_READ)) == NULL || !Examine(tmp,fib)){ if (tmp) UnLock(tmp); ierr = 205; errstr = av[i]; goto done; } UnLock(tmp); destdir = (struct FileLock *)Lock(destname, ACCESS_READ); destfilename = fib->fib_FileName; } else { destdir = srcdir; destfilename = destname; } printf(" %s..",av[i]); ierr = copyfile(av[i], srcdir, destfilename, destdir); if (destisdir) UnLock(destdir); if (ierr) break; } } done: stdout->_buflen = STDBUF; /* set back to buffr'd */ FreeMem(fib, (long)sizeof(*fib)); if (ierr) { ierror(errstr, ierr); return(20); } return(0); } copydir(srcdir, destdir, recur) register struct FileLock *srcdir, *destdir; { struct FileLock *cwd; register FIB *srcfib; register struct FileLock *destlock, *srclock; int ierr; static int level; level++; ierr = 0; srcfib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC); if (Examine(srcdir, srcfib)) { while (ExNext(srcdir, srcfib)) { if (CHECKBREAK()) break; if (srcfib->fib_DirEntryType < 0) { printf("%*s%s..",(level-1) * 6," ",srcfib->fib_FileName); ierr = copyfile(srcfib->fib_FileName,srcdir,srcfib->fib_FileName,destdir); if (ierr) break; } else { if (recur) { cwd = (struct FileLock *)CurrentDir(srcdir); if (srclock = (struct FileLock *)Lock(srcfib->fib_FileName, ACCESS_READ)) { CurrentDir(destdir); if (!(destlock = (struct FileLock *) Lock(srcfib->fib_FileName))) { destlock = (struct FileLock *)CreateDir(srcfib->fib_FileName); printf("%*s%s (Dir)....[Created]\n",(level-1) * 6, " ",srcfib->fib_FileName); } else printf("%*s%s (Dir)\n",(level-1) * 6," ",srcfib->fib_FileName); if (destlock) { ierr = copydir(srclock, destlock, recur); UnLock(destlock); } else { ierr = (int)((long)IoErr()); } UnLock(srclock); } else { ierr = (int)((long)IoErr()); } CurrentDir(cwd); if (ierr) break; } } } } else { ierr = (int)((long)IoErr()); } --level; FreeMem(srcfib, (long)sizeof(FIB)); return(ierr); } copyfile(srcname, srcdir, destname, destdir) char *srcname, *destname; struct FileLock *srcdir, *destdir; { struct FileLock *cwd; struct FileHandle *f1, *f2; long i; int ierr; char *buf; buf = (char *)AllocMem(8192L, MEMF_PUBLIC|MEMF_CLEAR); if (buf == NULL) { ierr = 103; goto fail; } ierr = 0; cwd = (struct FileLock *)CurrentDir(srcdir); f1 = Open(srcname, MODE_OLDFILE); if (f1 == NULL) { errstr = srcname; ierr = 205; goto fail; } CurrentDir(destdir); f2 = Open(destname, MODE_NEWFILE); if (f2 == NULL) { Close(f1); ierr = (int)((long)IoErr()); errstr = destname; goto fail; } while (i = Read(f1, buf, 8192L)) if (Write(f2, buf, i) != i) { ierr = (int)((long)IoErr()); break; } Close(f2); Close(f1); if (!ierr) { printf("..copied\n"); } else { DeleteFile(destname); printf("..Not copied.."); } fail: if (buf) FreeMem(buf, 8192L); CurrentDir(cwd); return(ierr); }