Path: utzoo!attcan!uunet!mcsun!unido!balu!mdnet@cosmo.UUCP From: mdnet@cosmo.UUCP (Dr. Carsten Emde/Klinikum Steglitz der FU Berlin) Newsgroups: comp.os.os9 Subject: Browse (part 2a of 3) Message-ID: <4614@balu.UUCP> Date: 3 Feb 90 09:31:15 GMT Sender: news@balu.UUCP Reply-To: mdnet@cosmo.UUCP (Dr. Carsten Emde/Klinikum Steglitz der FU Berlin) Organization: CosmoNet, D-3000 Hannover 1, FRG Lines: 991 Sorry for problems with this source when posted some weeks ago. "browse.c" comes now in two parts. Any complaints to: ---------------------------------------------------------------------- -- Carsten Emde --- Klinikum Steglitz --- Freie Universitaet Berlin -- -- Med. Klinik --- Hindenburgdamm 30 --- D-1000 Berlin 45 Steglitz -- -- +49307982393 --- Fax: +49307984141 --- Gastrointestinal Motility -- -- E-mail emde@zedat.fu-berlin.dbp.de (checked 0800/1200/1600/2000) -- -- or {anything big}!unido!cosmo!mdnet (checked only occasionally) -- ---------------------------------------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # browse_2a # This archive created: Tue Jan 30 18:04:16 1990 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'browse_2a' then echo shar: "will not over-write existing file 'browse_2a'" else cat << \SHAR_EOF > 'browse_2a' /* -- Just what the hell am I ??? --- */ #include char help[]= "Browse through a directory, written by Peter da Silva\n\ Adapted for OS-9 using TOP's os9lib\n\ Syntax: browse []\n\ Function: show an ls-like directory listing which can be 'edited', i.e.\n\ files may be tagged and inspected, dumped, executed, deleted,\n\ renamed, copied, edited etc.\n\ Options:\n\ none\n"; #ifdef mc68000 #define sr sr_ #define PC PC_ #endif #ifdef OSK #include #define GETCWD #define getcwd getwd #define minor(i) ((i)&0xFF) #define major(i) minor((i)>>8) #define SHELLSYM '$' #define ASSISTCOM "more /dd/sys/browse.hlp" #define SAVEMACROS "/h0/sys/browse.macros" #else #define remote #define SHELLSYM '!' #define ASSISTCOM "more /usr/hlp/browse.doc" #define SAVEMACROS "/usr/tmp/macros" #endif #ifdef M_XENIX #define USG #define rindex strrchr #define GETCWD #else #ifdef L_ctermid #define USG #define rindex strrchr #define minor(i) ((i)&0xFF) #define major(i) minor((i)>>8) #else #ifndef OSK #include #endif #endif #endif /* -- Miscellaneous include files -- */ #ifdef OSK #include #include #include #include #endif #include /* NCARGS, and others */ #ifndef M_XENIX #include /* data types for various files */ #endif #include /* stat data structure for getdir(), statout() */ #include /* dir data structure for getdir() */ #include /* passwd data structure for u_name() */ #include /* group data structure for g_name() */ #ifdef BSD #include /* time data structure for printime() */ #else #ifndef OSK #include /* time data structure for printime() */ #endif #endif #ifdef USG #ifdef M_XENIX #include #endif #include #else #ifndef OSK #include /* terminal modes for tinit(), tend() */ #endif #endif #include /* -- make information -- BUILD browse: browse.c cc browse.c -O -o browse -ltermlib END */ /* -- Miscellaneous defines -- */ #define FALSE 0 #define TRUE 1 #define MAXID 64 #define MAXLINE 256 #ifdef OSK #define MAXENTS 512 #define NCOL 54 #define MAXNAME 24 #else #define MAXENTS 320 #define NCOL 64 #define MAXNAME 14 #endif #define FILENAME 256 #define MAXARGC (NCARGS/16) /* Estimate max ARGC */ #define CHARSET 256 /* Number of macros == size of byte */ #define NOMAC (0) /* Null macro (last) */ #define TERMBUF 1024 /* Size of term buf for termcap */ #define SMALLBUF 256 #define NAME 1 #define SEC 2 /* -- Extended directory entry format -- */ struct entry { char *e_name; int e_flags; #define FTAGGED (1<<0) #define FPERMANENT (1<<1) struct stat e_stat; /* file status field */ char e_uname[9]; /* user name */ char e_gname[9]; /* user's group name */ #ifdef OSK unsigned long e_secno; #endif } *xentries[MAXENTS], **entries=xentries; int nentries; /* -- Look-up cache for user names -- */ struct idtab { int id_id; /* user (or group) id */ char id_name[9]; /* name[8] + filler */ } u_list[MAXID], /* Matched user id's. */ g_list[MAXID]; /* ditto group */ int u_ptr=0, g_ptr=0; /* current entries */ /* -- Global variables -- */ FILE *efp; /* Environment file */ char efname[MAXLINE]; /* " name */ char *tent; /* Pointer to tbuf */ char PC; /* Pad character */ char *UP, *BC; /* Upline, backsapce character */ short ospeed; /* Terminal output speed */ char termbuf[TERMBUF]; /* Place to put term info */ char *macbuf[CHARSET], ungetbuf[SMALLBUF]; /* Buffers for pushback and macros */ char c_macro=NOMAC; /* current macro */ char *macptr = ""; /* Pointer to currently executing macro */ char *ungetptr = ungetbuf; /* Pointer to pushed-back characters */ char *errname; /* Name of file error found in */ extern int errno; /* system error number */ int xerrno; /* extended error number */ int ccol=NCOL; /* Width of used display, current column */ int quickmode; /* short display mode (files only) */ #ifdef USG struct termio rawbuf; struct termio cookedbuf; #else #ifdef OSK struct sgbuf cookopts,rawopts; int signhndl(); #else struct sgttyb sgbuf; /* buffer for terminal mode info */ int rawflags, cookflags; /* flags for raw & cooked tty mode */ #endif #endif char *cm, /* Cursor motion */ *cs, /* Change scrolling region */ *sf, /* - scroll forward */ *sr, /* - scroll backwards */ *ce, /* Clear to end of line */ *cl, /* Clear screen */ *al, /* Insert line */ *dl, /* delete ditto */ *so, /* standout */ *se, /* standout end */ *us, /* underline */ *ue, /* underline end */ *ti, /* Init terminal */ *te; /* Reset terminal */ int li, /* lines on screen */ co; /* columns ditto */ char xn; /* Magic cookie kludge */ /* -- Global error messages -- */ char *emesg[4]={ "??", #define TOO_MANY 1 "Too many directory entries", #define NOMATCH 2 "No match", 0 }; int top, curr; /* Positions of screen in directory */ #define bottom ((top+nlines>nentries)?nentries:(top+nlines)) char *dot; /* name of current directory */ int nlines; /* number of lines displayed on page */ char display_up; /* Does the display exist? */ int todump=1; /* Do we want to dump data? */ int ended; /* Have we quite finished? */ int intrup; /* Have we been interrupted? */ char *HOME; /* Where did I start from? */ char *SHELL; /* How do I run programs? */ /* -- types of functions !!! */ char *getenv(), *tgetstr(); char *malloc(); #define NEW(t) (t *)malloc(sizeof (t)) #define NIL(t) ((t) 0) /* -- Code starts here: dummy main -- */ main(ac, av, ep) int ac; char **av; char **ep; { int i; if(ac>1) { for(i=1; i2) { perror("only one argument may be specified."); exit(0); } if(chdir(av[1])==-1) { perror("can't access directory specified",av[1]); exit(0); } } sprintf(efname, "/tmp/br.env.%d", getpid()); HOME=getenv("HOME"); SHELL=getenv("SHELL"); #ifndef OSK dumpenv(ep); #endif intrup=0; tinit(getenv("TERM")); clear_all(); #ifdef OSK stdin->_flag|=_RBF; stdin->_flag|=_UNBUF; #endif browse(); tend(); #ifndef OSK unlink(efname); #endif } clear_all() { int i; for(i = 0; i < MAXENTS; i++) entries[i] = 0; } char *clone(name) char *name; { char *hold; hold = (char *)malloc(strlen(name)+1); if(hold==0) return 0; strcpy(hold, name); return hold; } newname(e, name) struct entry *e; char *name; { if(e->e_name) free(e->e_name); e->e_name = clone(name); } #if (BSD || OSK) readent(dp, db) DIR *dp; struct direct *db; { struct direct *ptr; ptr = readdir(dp); if(!ptr) return 0; *db = *ptr; /* V7 'C' and above... safe, since UCB=V7+ */ free(ptr); return 1; } #else #define opendir(n) fopen(n, "r") #define DIR FILE readent(dp, db) DIR *dp; struct direct *db; { if(fread(db, sizeof(struct direct), 1, dp)) return 1; /* else */ return 0; } #define closedir fclose #endif getdir() { #ifdef OSK struct fildes f; struct tm t; int physdisk, oldid; char pdot[32], *slash; #endif char *u_name(), *g_name(); DIR *dp; int valid; struct direct *hold = NEW(struct direct); int i, p; if(!(dp = opendir("."))) { errname="."; return FALSE; } p = 0; for(i = 0; i < nentries; i++) { if(entries[i]->e_flags & FPERMANENT) { if(p != i) { struct entry *hold; hold = entries[p]; entries[p] = entries[i]; entries[i] = hold; } p++; } } for(nentries = p; !intrup && nentries < MAXENTS; nentries += valid) { if(!entries[nentries]) { entries[nentries] = NEW(struct entry); if(!entries[nentries]) break; entries[nentries]->e_name = NIL(char *); } if(!readent(dp, hold)) { p=nentries; break; } #ifndef OSK valid = (hold->d_ino != 0); #else valid = TRUE; entries[nentries]->e_secno=hold->d_addr; #endif if(valid) { #ifndef OSK if(stat(hold->d_name, &entries[nentries]->e_stat)==-1) { closedir(dp); errname=hold->d_name; free(hold); return FALSE; } #endif newname(entries[nentries], hold->d_name); #ifndef BSD /* truncate name to 14 characters in non-BSD systems */ #ifndef OSK if(strlen(entries[nentries]->e_name)>14) entries[nentries]->e_name[14] = 0; #endif #endif entries[nentries]->e_flags = 0; #ifndef OSK strcpy(entries[nentries]->e_uname, u_name(entries[nentries]->e_stat.st_uid)); strcpy(entries[nentries]->e_gname, g_name(entries[nentries]->e_stat.st_gid)); #endif } } closedir(dp); free(hold); #ifdef OSK sortdir(SEC); /* optimize head movements */ oldid=getuid(); super(); strcpy(pdot,dot); if(slash=index(pdot+1,'/')) strcpy(slash,"@"); else strcat(pdot,"@"); if((physdisk=open(pdot,S_IREAD))==-1) return FALSE; for(nentries = 0; !intrup && nentries < p; nentries ++) { lseek(physdisk,(entries[nentries]->e_secno)<<8,0); read(physdisk,&f,sizeof(f)); t.tm_year = (int) f.fd_date[0]; t.tm_mon = (int) f.fd_date[1] - 1; t.tm_mday = (int) f.fd_date[2]; t.tm_hour = (int) f.fd_date[3]; t.tm_min = (int) f.fd_date[4]; t.tm_sec = 0; t.tm_isdst = -1; entries[nentries]->e_stat.st_atime = entries[nentries]->e_stat.st_mtime = mktime(&t); t.tm_year = (int) f.fd_dcr[0]; t.tm_mon = (int) f.fd_dcr[1] - 1; t.tm_mday = (int) f.fd_dcr[2]; t.tm_hour = t.tm_min = t.tm_sec = 0; t.tm_isdst = -1; entries[nentries]->e_stat.st_ctime = mktime(&t); memcpy(&(entries[nentries]->e_stat.st_size), f.fd_fsize, sizeof(long)); entries[nentries]->e_stat.st_uid = f.fd_own[1]; entries[nentries]->e_stat.st_gid = f.fd_own[0]; entries[nentries]->e_stat.st_mode = f.fd_att; entries[nentries]->e_stat.st_nlink = f.fd_link; strcpy(entries[nentries]->e_uname, u_name(entries[nentries]->e_stat.st_uid)); strcpy(entries[nentries]->e_gname, g_name(entries[nentries]->e_stat.st_gid)); } close(physdisk); setuid(oldid); #endif if(intrup) return FALSE; if(nentries>=MAXENTS || entries[nentries]==NIL(struct entry *)) { errno=0; xerrno=TOO_MANY; errname="."; return FALSE; } sortdir(NAME); if(intrup) return FALSE; return TRUE; } at_current() { at_file(curr); } at_file(file) int file; { if(display_up) { if(file < top || file >= top+nlines) return 0; at(0, curr-top+2); } else { if(file != curr) return 0; cmdline(); } return 1; } display_flags(flags) { outc((flags&FTAGGED)?'+':((flags&FPERMANENT)?'!':' ')); } repaint_flags() { if(!display_up) return; at(quickmode?0:NCOL-1, curr-top+2); display_flags(entries[curr]->e_flags); } /* repaint_current() { if(!display_up) return; at_current(); dump(curr, curr+1); } */ tag() { entries[curr]->e_flags ^= FTAGGED; repaint_flags(); } tag_all(flag) int flag; { int i; for(i = 0; i < nentries; i++) if(flag) { if(!isdir(entries[i])) entries[i]->e_flags |= FTAGGED; } else entries[i]->e_flags &= ~FTAGGED; if(display_up) todump = TRUE; } delete_from_display(file) int file; { if(!display_up) return; if(file>=top+nlines) return; if(file < top) file = top; scroll(2+file-top, 2+nlines, 1); at(0, 2+nlines-1); if(top+nlines >= nentries) outc('~'); else dump(bottom, bottom+1); } delete_file_entry(file) int file; { struct entry *hold; int i; delete_from_display(file); hold = entries[file]; for(i=file; i= nentries) { curr--; if(top >= nentries) { top--; display_up = 0; todump = 1; } } } remove_one(file, doit) int file; int doit; { if(!doit) { cmdline(); outs("Delete "); ctlouts(entries[file]->e_name); outs(" [n]?"); fflush(stdout); doit = getch() == 'y'; outs(doit?"Yes.":"No."); fflush(stdout); } if(doit) { if(unlink(entries[file]->e_name) == 0) { cmdline(); outs("Deleted "); ctlouts(entries[file]->e_name); outs("."); delete_file_entry(file); return 1; } else { wperror(entries[file]->e_name); return 0; } } return 0; } remove(doit) int doit; { int i; int found_tags; found_tags = 0; i = 0; while(i < nentries) { if(entries[i]->e_flags & FTAGGED) { found_tags = 1; if(!remove_one(i, doit)) /* decrements nentries */ break; } else i++; } if(!found_tags) remove_one(curr, doit); } insert_entry_at(ent, i) struct entry *ent; int i; { struct entry *hold; int j; /* Allocate slot at end */ if(!entries[nentries]) { entries[nentries] = NEW(struct entry); if(!entries[nentries]) return 0; entries[nentries]->e_name = NIL(char *); } else if(entries[nentries]->e_name) { free(entries[nentries]->e_name); entries[nentries]->e_name = NIL(char *); } /* Copy data into slot */ *entries[nentries] = *ent; entries[nentries]->e_name = clone(ent->e_name); if(!entries[nentries]->e_name) return 0; if(i != nentries) { /* Rotate slot to middle */ hold = entries[nentries]; for(j = nentries; j > i; j--) entries[j] = entries[j-1]; entries[i] = hold; } nentries++; if(display_up) { if(i < top) i = top; if(i >= bottom) return; scroll(2+i-top, 2+nlines, -1); at(0, 2+i-top); dump(i, i+1); } } insert_entry(ent) struct entry *ent; { int i; if(nentries >= MAXENTS) return 0; for(i = 0; i < nentries; i++) if(entcmpnam(&ent, &entries[i]) < 0) break; return insert_entry_at(ent, i); } assist() { char cmdbuf[MAXLINE]; sprintf(cmdbuf, ASSISTCOM); if(sys(cmdbuf, 1)) perror(cmdbuf); } hexdump() { char cmdbuf[MAXLINE]; sprintf(cmdbuf, "dump %s", entries[curr]->e_name); if(sys(cmdbuf, 1)) perror(cmdbuf); } move() { char scratch[FILENAME]; struct entry hold; char inps(); hold = *entries[curr]; cmdline(); outs("Rename "); ctlouts(entries[curr]->e_name); outc(' '); if(inps(scratch, entries[curr]->e_name, 0)=='\033') { killcmd(); return; } if(link(entries[curr]->e_name, scratch)!=0) { char tmbuf[42]; sprintf(tmbuf, "(rename %s %s)", entries[curr]->e_name, scratch); wperror(tmbuf); return; } if(unlink(entries[curr]->e_name)!=0) { wperror(entries[curr]->e_name); return; } hold.e_name = scratch; hold.e_flags &= ~FTAGGED; delete_file_entry(curr); insert_entry(&hold); } pname(name, mode) char *name; int mode; { int i; char *slash, *rindex(); int max=quickmode?MAXLINE:(MAXNAME+1); #ifdef OSK if(mode&S_IFDIR) #else if((mode&S_IFMT)==S_IFDIR) #endif max--; #ifndef OSK else if((mode&S_IFMT)==S_IFREG && (mode&0111)) max--; else if((mode&S_IFMT)!=S_IFREG) max--; #endif if(!quickmode && (slash=rindex(name, '/'))) { name=slash; outc('<'); max--; } for(i=0; i"); #ifdef OSK if(mode&S_IFDIR) { #else if((mode&S_IFMT)==S_IFDIR) { #endif outc('/'); } #ifndef OSK else if((mode&S_IFMT)==S_IFREG && (mode&0111)) { outc('*'); } else if((mode&S_IFMT)!=S_IFREG) { outc('?'); } #endif } sortdir(ele) int ele; { int entcmpnam(),entcmpsec(); if(ele==NAME) qsort(entries, nentries, sizeof(struct entry *), entcmpnam); if(ele==SEC) qsort(entries, nentries, sizeof(struct entry *), entcmpsec); } #ifndef OSK addname(flag) char flag; { char buf[FILENAME], *ptr, *tmp; char scratch[FILENAME]; struct entry hold; char inps(); cmdline(); outs("Add "); if(inps(scratch, entries[curr]->e_name, 0)=='\033') { killcmd(); return; } if(stat(scratch, &hold.e_stat)==-1) { wperror(scratch); return; } if(flag!='+' && *scratch != '/') { strcpy(buf, dot); ptr = scratch; for(;;) { /* eat '../' and './' */ if(ptr[0]=='.' && ptr[1]=='.' && (ptr[2]=='/' || !ptr[2])) { tmp = rindex(buf, '/'); if(!tmp) break; *tmp=0; ptr += 2+(ptr[2]=='/'); continue; } if(ptr[0]=='.' && (ptr[1]=='/' || !ptr[1])) { ptr += 1+(ptr[1]=='/'); continue; } break; } if(*ptr) { strcat(buf, "/"); strcat(buf, ptr); } hold.e_name = buf; } else hold.e_name = scratch; strcpy(hold.e_uname, u_name(hold.e_stat.st_uid)); strcpy(hold.e_gname, g_name(hold.e_stat.st_gid)); hold.e_flags = 0; if(flag!='+') hold.e_flags |= FPERMANENT; insert_entry(&hold); } addperm() { char buf[FILENAME], *ptr, *tmp; struct entry hold; int entcmpnam(), i; if(entries[curr]->e_flags & FPERMANENT) return; if(entries[curr]->e_name[0]!='/') { strcpy(buf, dot); ptr = entries[curr]->e_name; for(;;) { /* eat '../' and './' */ if(ptr[0]=='.' && ptr[1]=='.' && (ptr[2]=='/' || !ptr[2])) { tmp = rindex(buf, '/'); if(!tmp) break; *tmp=0; ptr += 2+(ptr[2]=='/'); continue; } if(ptr[0]=='.' && (ptr[1]=='/' || !ptr[1])) { ptr += 1+(ptr[1]=='/'); continue; } break; } if(*ptr) { strcat(buf, "/"); strcat(buf, ptr); } hold = *entries[curr]; hold.e_name = buf; hold.e_flags &= ~FTAGGED; hold.e_flags |= FPERMANENT; insert_entry(&hold); } else { entries[curr]->e_flags |= FPERMANENT; entries[curr]->e_flags &= ~FTAGGED; repaint_flags(); } } delperm() { entries[curr]->e_flags &= ~(FPERMANENT|FTAGGED); repaint_flags(); } #endif entcmpnam(e1, e2) struct entry **e1, **e2; { if((*e1)->e_name[0] == '/') { if((*e2)->e_name[0] != '/') return 1; } else if((*e2)->e_name[0] == '/') return -1; return strcmp((*e1)->e_name, (*e2)->e_name); } entcmpsec(e1, e2) struct entry **e1, **e2; { if((*e1)->e_secno < (*e2)->e_secno) return -1; if((*e1)->e_secno > (*e2)->e_secno) return 1; return 0; } dump(start, end) int start; int end; { int i; int lo = (starte_name, &entries[i]->e_stat, entries[i]->e_uname, entries[i]->e_gname, entries[i]->e_flags); nl(); } return TRUE; } SHAR_EOF fi exit 0 # End of shell archive