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 2b of 3) Message-ID: <4615@balu.UUCP> Date: 3 Feb 90 09:31:53 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: 1670 #! /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_2b # 4. Merge browse_2a and browse_2b to create browse.c # This archive created: Tue Jan 30 18:04:32 1990 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'browse_2b' then echo shar: "will not over-write existing file 'browse_2b'" else cat << \SHAR_EOF > 'browse_2b' statout(name, sbuf, user, group, flags) char *name; struct stat *sbuf; char *user, *group; int flags; { int mode = sbuf->st_mode; if(!quickmode) { #ifndef OSK printf("%5u ", sbuf->st_ino); #endif #ifdef OSK if(mode&S_IFDIR) outc('d'); else outc('-'); if(mode&S_ISHARE) outc('s'); else outc('-'); if(mode&S_IOEXEC) outc('e'); else outc('-'); if(mode&S_IOWRITE) outc('w'); else outc('-'); if(mode&S_IOREAD) outc('r'); else outc('-'); if(mode&S_IEXEC) outc('e'); else outc('-'); if(mode&S_IWRITE) outc('w'); else outc('-'); if(mode&S_IREAD) outc('r'); else outc('-'); #else if((mode&S_IFMT)==S_IFCHR) outc('c'); else if((mode&S_IFMT)==S_IFBLK) outc('b'); else if((mode&S_IFMT)==S_IFDIR) outc('d'); else if((mode&S_IFMT)==S_IFREG) outc('-'); else outc('?'); triad((mode>>6)&7, mode&S_ISUID, 's'); triad((mode>>3)&7, mode&S_ISGID, 's'); triad(mode&7, mode&S_ISVTX, 't'); #endif outc(' '); printf("%1u ", sbuf->st_nlink); printf("%-8s ", user); printf("%-8s ", group); #ifdef OSK if(!(mode&S_IFDIR)) #else if((mode&S_IFMT)==S_IFREG || (mode&S_IFMT)==S_IFDIR)) #endif printf("%7ld ", sbuf->st_size); else #ifdef OSK printf(" --- "); #else printf("%3d,%3d ", major(sbuf->st_rdev), minor(sbuf->st_rdev)); #endif outc(' '); printime(&sbuf->st_mtime); } display_flags(flags); pname(name, sbuf->st_mode); } char * u_name(uid) int uid; { int i; struct passwd *pwptr, *getpwuid(); for(i=0; i=MAXID) /* cache full */ u_ptr = 0; /* simplistic algorithm, wrap to beginning */ /* with MAXID >> # common id's it's good enough */ u_list[u_ptr].id_id=uid; if(pwptr=getpwuid(uid)) { /* Copy name */ for(i=0; pwptr->pw_name[i]>' '; i++) u_list[u_ptr].id_name[i]=pwptr->pw_name[i]; u_list[u_ptr].id_name[i]=0; } else /* Default to UID */ sprintf(u_list[u_ptr].id_name, "%d", uid); return u_list[u_ptr++].id_name; } char * g_name(gid) int gid; { int i; struct group *grptr, *getgrgid(); for(i=0; i=MAXID) /* cache full */ g_ptr = 0; /* simplistic algorithm, wrap to beginning */ /* with MAXID >> # common id's it's good enough */ g_list[g_ptr].id_id=gid; if(grptr=getgrgid(gid)) { /* Copy name */ for(i=0; grptr->gr_name[i]>' '; i++) g_list[g_ptr].id_name[i]=grptr->gr_name[i]; g_list[g_ptr].id_name[i]=0; } else /* Default to UID */ sprintf(g_list[g_ptr].id_name, "%d", gid); return g_list[g_ptr++].id_name; } printime(clock) long *clock; { struct tm *tmbuf, *localtime(); static char *months[12]= { "Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec" }; tmbuf=localtime(clock); printf("%2d %3s %02d %2d:%02d", tmbuf->tm_mday, months[tmbuf->tm_mon], tmbuf->tm_year, tmbuf->tm_hour, tmbuf->tm_min); } header() { int i; if(quickmode) printf(" File Name"); else printf( #ifdef OSK "Attr Lnk User Group Size Modify Time File name" #else "Inode Long mode LNX User Group Size/Dev Modify Time File name" #endif ); nl(); } #ifndef OSK triad(bits, special, code) int bits, special; char code; { if(bits&4) outc('r'); else outc('-'); if(bits&2) outc('w'); else outc('-'); if(special) outc(code); else if(bits&1) outc('x'); else outc('-'); } #endif outs(s) char *s; { int outc(); if(s) tputs(s, 0, outc); } outc(c) char c; { putchar(c); } /* Screen manipulation primitives: dumb set for smart terminals */ at(x, y) int x, y; { outs(tgoto(cm, x, y)); } nl() { outs(ce); outc('\n'); } /* Scroll lines in window (from:to) n lines */ scroll(from, to, n) int from, to, n; { if(cs && sf && sr) { outs(tgoto(cs, from, to-1)); if(n<0) while(n++) outs(sr); else while(n--) outs(sf); outs(tgoto(cs, 0, li-1)); } else if(al && dl) { if(n<0) { int i=n; outs(tgoto(cm, 0, to+n)); while(i++) outs(dl); outs(tgoto(cm, 0, from)); while(n++) outs(al); } else { int i=n; outs(tgoto(cm, 0, from)); while(i--) outs(dl); outs(tgoto(cm, 0, to-n)); while(n--) outs(al); } } } wperror(file) char *file; { extern int errno; extern remote char *sys_errlist[]; cmdline(); ctlouts(file); ctlouts(": "); ctlouts(errno?sys_errlist[errno]:emesg[xerrno]); if(!display_up) nl(); } fperror(prog, file) char *prog, *file; { extern int errno; fprintf(stderr, "%s -- ", prog); if(errno) perror(file); else fprintf(stderr, "%s: %s\n", file, emesg[xerrno]); } tinit(name) char *name; { char *termptr; char tbuf[TERMBUF], *tmp; #ifndef OSK int intr(); #endif #ifdef BSD int stop(); #endif termptr = termbuf; tgetent(tbuf, name); tmp = tgetstr("pc", &termptr); if(tmp) PC = *tmp; UP = tgetstr("up", &termptr); BC = tgetstr("bc", &termptr); cm = tgetstr("cm", &termptr); cs = tgetstr("cs", &termptr); sf = tgetstr("sf", &termptr); sr = tgetstr("sr", &termptr); ce = tgetstr("ce", &termptr); cl = tgetstr("cl", &termptr); al = tgetstr("al", &termptr); dl = tgetstr("dl", &termptr); us = tgetstr("us", &termptr); ue = tgetstr("ue", &termptr); so = tgetstr("so", &termptr); se = tgetstr("se", &termptr); ti = tgetstr("ti", &termptr); te = tgetstr("te", &termptr); li = tgetnum("li"); co = tgetnum("co"); xn = tgetflag("xn"); nlines=li-3; #ifdef USG ioctl(1, TCGETA, &rawbuf); cookedbuf = rawbuf; rawbuf.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL); rawbuf.c_cc[VMIN] = 1; rawbuf.c_cc[VTIME] = 0; #else #ifdef OSK _gs_opt(1, &cookopts); memcpy(&rawopts,&cookopts,sizeof(cookopts)); rawopts.sg_echo=rawopts.sg_pause=FALSE; rawopts.sg_eofch=rawopts.sg_eorch=0; #else gtty(1, &sgbuf); ospeed=sgbuf.sg_ospeed; quickmode=ospeed<10; cookflags=sgbuf.sg_flags; sgbuf.sg_flags = (sgbuf.sg_flags&~ECHO)|CBREAK; rawflags=sgbuf.sg_flags; #endif #endif #ifdef OSK intercept(signhndl); #else signal(SIGINT, intr); #endif #ifdef BSD signal(SIGTSTP, stop); #endif rawtty(); } int tmode=0; entty() { if(!tmode) outs(ti); tmode=1; } extty() { if(tmode) outs(te); tmode=0; } rawtty() { #ifdef USG ioctl(1, TCSETA, &rawbuf); #else #ifdef OSK _ss_opt(1, &rawopts); #else sgbuf.sg_flags=rawflags; stty(1, &sgbuf); #endif #endif entty(); } cooktty() { #ifdef USG ioctl(1, TCSETA, &cookedbuf); #else #ifdef OSK _ss_opt(1, &cookopts); #else sgbuf.sg_flags=cookflags; stty(1, &sgbuf); #endif #endif extty(); } #ifdef OSK int signhndl(signum) int signum; { switch (signum) { case 2: intrup=1; break; case 3: intrup=1; break; default: break; } } #else intr() { int intr(); signal(SIGINT, intr); intrup=1; bell(); } #endif #ifdef BSD stop() { int stop(); signal(SIGTSTP, stop); intrup=1; tend(); kill(getpid(), SIGSTOP); rawtty(); display_up=0; } #endif tend() { cmdline(); cooktty(); fflush(stdout); } char * pwd() #ifdef GETCWD { static char mydir[FILENAME+1] = ""; char *getcwd(); return getcwd(mydir, FILENAME); } #else { static char mydir[FILENAME] = ""; int status; int pip[2]; int n; int (*sigs[2])(); sigs[0] = signal(2, 1); sigs[1] = signal(3, 1); if(pipe(pip)<0) return 0; if(!fork()) { close(1); dup(pip[1]); close(pip[0]); execl("/bin/pwd", "pwd", 0); exit(-1); } close(pip[1]); wait(&status); signal(2, sigs[0]); signal(3, sigs[1]); if(status) { close(pip[0]); return "/"; } n = read(pip[0], mydir, FILENAME); close(pip[0]); if(n<=0) return "/"; mydir[n-1] = 0; return mydir; } #endif browse() { int c; char *env; if(env=getenv("BROWSE")) macptr = env; defmacs(); newdir(); redraw(); ended=0; do { if(intrup) { intrup=0; /* clear interrupt */ cmdline(); /* go to the command line */ outs("Interrupt"); /* let us know about it */ endmac(); /* clear macros */ clearin(); /* and input buffer */ } here_i_am(); fflush(stdout); c = getch(); cmd(c); } while(!ended); } clearin() { fseek(stdin, 0L, 1); /* stay here messily */ } cmd(c) char c; { int i; if(intrup) return; switch(c) { case ' ': if(isdir(entries[curr])) { if(!cd(entries[curr]->e_name)) wperror(entries[curr]->e_name); } else if(!macro(c)) bell(); else cmd(getch()); break; case '&': syscom(0); break; case SHELLSYM: syscom(1); break; case '=': todir(); break; #ifndef OSK case '?': sample(entries[curr]->e_name); break; #endif case '[': define(); break; #ifdef OSK case '?': #else case 'a': #endif assist(); break; case 'B'-'@': prev(nlines); break; case 'D'-'@': next(nlines/2); break; case 'F'-'@': next(nlines); break; case 'H': curr=top; break; case 'J': tail(); break; case 'K': home(); break; case 'L'-'@': redraw(); break; case 'L': curr=bottom-1; break; case 'M': definitions(); break; #ifdef OSK case '.': #else case 'N': #endif next(nlines); break; #ifdef OSK case 'o': #else case 'P': #endif prev(nlines); break; case 'R': move(); break; case 'S': savedefs(); break; case 'I': installdefs(entries[curr]->e_name); break; case 'U'-'@': prev(nlines/2); break; case 'D': case 'd': if(getch()==c && !intrup) remove(c=='D'); else bell(); break; case 'h': ccol=0; break; case 'l': ccol=NCOL; break; case '<': quickmode=1; if(display_up) { todump=1; at(0, 1); header(); } break; #ifndef OSK case '+': case '^': addname(c); break; case '(': addperm(); break; case ')': delperm(); break; #endif case '>': quickmode=0; if(display_up) { todump=1; at(0, 1); header(); } break; case 'J'-'@': #ifdef OSK case ',': #else case 'j': #endif newline(); break; case 'K'-'@': #ifdef OSK case 'i': #else case 'k': #endif upline(); break; case 'n': next(nlines/2); break; case 'p': prev(nlines/2); break; case 'q': case 'Z': case 'Q': if(getchar()==c && !intrup) ended=1; else bell(); break; case 'r': reload(); break; case 't': tag(); break; case 'T': case 'U': tag_all(c=='T'); break; case 'x': hexdump(); break; default: if(!macro(c)) bell(); else cmd(getch()); /* make sure it does something */ } /* and thus avoid unneeded redraws */ } cmdline() { at(0, li-1); outs(ce); fflush(stdout); } newdir() { if(display_up) at(0,0); fflush(stdout); dot=pwd(); if(!getdir()) wperror(dot); curr=0; top=0; topline(); if(display_up) todump=TRUE; } reload() { getdir(); curr=(curr>=bottom)?bottom-1:curr; if(display_up) { topline(); todump=TRUE; } } topline() { if(display_up) at(0,0); printf("%s: %d files", dot, nentries); nl(); } redraw() { outs(cl); display_up=0; topline(); at(0,1); header(); todump=1; display_up=1; } dumpdata() { at(0,2); dump(top,bottom); if(top+nlines>nentries) { int i; at(0, bottom-top+2); for(i=bottom-top; i0) curr--; else bell(); } home() { curr=0; } next(l) { curr += l; if(curr>=nentries) curr=nentries-1; } prev(l) { curr -= l; if(curr<0) curr=0; } tail() { curr=nentries-1; } newline() { if(curre_name, &entries[curr]->e_stat, entries[curr]->e_uname, entries[curr]->e_gname, entries[curr]->e_flags); at(quickmode?1:ccol, li-1); fflush(stdout); if((c=getch())=='\n') { redraw(); here_i_am(); } else ungetch(c); } else if(todump) { if(!(curr-top > 0 && curr-top < nlines)) { top = curr-nlines/2; if(top<0) top=0; } dumpdata(); at(quickmode?1:ccol, curr-top+2); todump=0; } else { int lines_to_scroll = curr-top; if(lines_to_scroll > 0) if((lines_to_scroll -= nlines-1) < 0) lines_to_scroll = 0; if(lines_to_scroll < 1-nlines) { top=curr; at(0,2); dump(top, bottom); } else if(lines_to_scroll > nlines-1) { top=curr-nlines+1; at(0,2); dump(top, bottom); } else if(lines_to_scroll) { scroll(2, nlines+2, lines_to_scroll); top += lines_to_scroll; if(lines_to_scroll < 0) { at(0, 2); dump(top, top-lines_to_scroll); } else { at(0, 2+nlines-lines_to_scroll); dump(bottom-lines_to_scroll, bottom); } } at(quickmode?1:ccol, curr-top+2); } } bell() { outc(7); } /* (Never used) perform(command) char *command; { char cmdbuf[MAXLINE]; cmdline(); extty(); outc('!'); printf(command, entries[curr]->e_name); sprintf(cmdbuf, command, entries[curr]->e_name); sys(cmdbuf, 1); entty(); } */ #ifdef OSK sys(command, rdflag) int rdflag; /* Should I redraw? */ { char shellstr[MAXLINE+64]; cmdline(); fflush(stdout); cooktty(); sprintf(shellstr,"setenv FILE %s;%s %s", entries[curr]->e_name, SHELL, command); if(errno=system(shellstr)) perror(shellstr); getchar(); if(rdflag) { redraw(); display_up=1; } rawtty(); } #else sys(command, rdflag) char *command; int rdflag; /* Should I redraw? */ { char scratch[32]; int status; int (*sigint)(), (*sigquit)(); char c; sigint=signal(2, 1); sigquit=signal(3, 1); cooktty(); fflush(stdout); strcpy(scratch, entries[curr]->e_name); if(!fork()) { int i; static char *envp[MAXARGC]; static char env[NCARGS]; char *hold; char line[MAXLINE]; char *tmp; signal(2,0); signal(3,0); if(!(efp=fopen(efname, "r"))) { fputc('\n', stderr); perror(efname); execl(SHELL, SHELL, "-c", command, 0); execl("/bin/sh", "sh", "-c", command, 0); perror("/bin/sh"); exit(-77); } i=0; tmp=hold=env; while(!feof(efp)) { fgets(line, MAXLINE, efp); if(strlen(line)+(tmp-env)>NCARGS) break; if(line[0]=='$') if(tmp>hold) { envp[i] = hold; i++; if(i > MAXARGC-2) break; tmp[-1]=0; /* eat line-feed at end */ hold = tmp; } strcpy(tmp, line+(line[0]=='$')); tmp += strlen(tmp); } if(tmp>hold) { envp[i] = hold; i++; tmp[-1]=0; /* and eat this one as well */ } sprintf(tmp, "FILE=%s", scratch); envp[i++]=tmp; envp[i]=0; if(rdflag) putchar('\n'); else putchar('\r'); fflush(stdout); execle(SHELL, SHELL, "-c", command, 0, envp); execle("/bin/sh", "sh", "-c", command, 0, envp); perror("/bin/sh"); exit(-77); } wait(&status); signal(2, sigint); signal(3, sigquit); rawtty(); if(rdflag || status!=0) display_up=0; } #endif char inps(buf, text, termin) char *buf; char *text; char termin; { int i = 0, j, found_tags; char c, *ptr, *txp; txp=text?text:"!"; while(!intrup && (fflush(stdout), c=getch()) != '\033' && c != '\n' && c != termin) switch(c) { case '\b': case '\177': if(i>0) { printf("\b \b"); i--; } else bell(); break; case 'U'-'@': txp=text?text:"!"; case 'X'-'@': if(i>0) while(i>0) { printf("\b \b"); i--; } else bell(); break; case 'K'-'@': if(*txp) ctloutc(buf[i++] = *txp++); break; case '%': found_tags = 0; j = 0; while(j < nentries) { if(entries[j]->e_flags & FTAGGED) { found_tags = 1; if(i+strlen(entries[j]->e_name)+1>=MAXLINE) return '\033'; for(ptr=entries[j]->e_name; *ptr; ptr++) ctlout(buf[i++] = *ptr); ctlout(buf[i++] = ' '); } j++; } if(!found_tags) { if(i+strlen(entries[curr]->e_name)+1>=MAXLINE) return '\033'; for(ptr=entries[curr]->e_name; *ptr; ptr++) ctlout(buf[i++] = *ptr); } standend(); break; case '#': for(ptr=dot; *ptr; ptr++) { if(i>=MAXLINE) return '\033'; ctlout(buf[i++] = *ptr); } standend(); break; case '~': for(ptr=HOME; *ptr; ptr++) { if(i>=MAXLINE) return '\033'; ctlout(buf[i++] = *ptr); } standend(); break; case '@': outc(c); fflush(stdout); c = getch(); if(!macro(c)) { ungetch(c); buf[i++]='@'; } else outs("\b \b"); break; case '$': outc(c); fflush(stdout); c = getch(); if(c=='$') { char tmp[10]; sprintf(tmp, "%d", getpid()); outs("\b \b"); for(ptr=tmp; *ptr; ptr++) { if(i>=MAXLINE) return '\033'; ctlout(buf[i++] = *ptr); } standend(); } else if(!macbuf[c]) { ungetch(c); buf[i++]='$'; } else { outs("\b \b"); for(ptr=macbuf[c]; *ptr; ptr++) { if(i>=MAXLINE) return '\033'; ctlout(buf[i++] = *ptr); } standend(); } break; case '!': while(*txp) { if(i>=MAXLINE) return '\033'; ctlout(buf[i++] = *txp++); } standend(); break; case '\\': outc(c); fflush(stdout); c=getch(); if(c=='~' || c=='%' || c=='#' || c=='\\' || c=='!' || c=='K'-'@' || c=='U'-'@' || c=='X'-'@' || c=='\b' || c=='\177' || c==termin || c=='\033' || c=='\n' || c=='@' || c=='$') { outc('\b'); ctloutc(buf[i++]=c); break; } else if(c>='0' && c<='7') { int n, val=0; for(n=0; n<3 && c>='0' && c<='7'; n++) { val = val*8 + c-'0'; outc('\b'); ctloutc(val); c=getch(); } ungetch(c); c=buf[i++]=val; break; } else if(c=='^') { outc('\b'); outc('^'); fflush(stdout); c=getch(); if(c>='?'&&c<='_') { outc('\b'); ctloutc(buf[i++]=(c-'@')&'\177'); break; } else if(c>='`'&&c<='~') { outc('\b'); ctloutc(buf[i++]=c-'`'); break; } /* otherwise default */ else buf[i++]='^'; /* after adding caret */ } /* otherwise fall through to default */ else buf[i++]='\\'; /* after adding backslash */ default: if(i>=MAXLINE) return '\033'; ctloutc(buf[i++] = c); break; } buf[i] = 0; return intrup?'\033':c; } ctlouts(s) char *s; { int cnt = 0; while(*s) cnt += ctlout(*s++); cnt += standend(); return cnt; } ctloutc(c) char c; { int cnt; cnt = ctlout(c); cnt += standend(); return cnt; } int somode = 0; int ulmode = 0; standout() { if(!somode) { outs(so); somode = 1; if(xn) return 1; } return 0; } underline() { if(!ulmode) { outs(us); ulmode = 1; if(xn) return 1; } return 0; } standend() { int cnt = 0; if(somode) { outs(se); somode = 0; if(xn) cnt++; } if(ulmode) { outs(ue); ulmode = 0; if(xn) cnt++; } return cnt; } ctlout(c) char c; { int cnt = 0; if(c&'\200') { cnt += underline(); cnt += ctlout(c&'\177'); return cnt; } else if(c<' ' || c=='\177') { cnt += standout(); outc((c+'@')&'\177'); cnt++; return cnt; } else { cnt += standend(); outc(c); cnt++; return cnt; } } todir() { char cmdbuf[MAXLINE]; static char lastdir[MAXLINE] = "."; char *slash, *rindex(); cmdline(); printf("goto "); if(inps(cmdbuf, lastdir, 0)!='\033' && cmdbuf[0]) { strcpy(lastdir, cmdbuf); if(!cd(cmdbuf, 0)) { if(!fgoto(cmdbuf)) if(slash=rindex(cmdbuf, '/')) { *slash++=0; if(cd(cmdbuf, 1)) { if(!fgoto(slash)) { errno=0; xerrno=NOMATCH; wperror(slash); } } else wperror(cmdbuf); } else wperror(cmdbuf); } } else killcmd(); } fgoto(file) char *file; { int i; for(i = 0; ie_name, file)) { curr=i; return 1; } return 0; } match(target, sample) char *target, *sample; { while(*sample && *target==*sample) { target++; sample++; } return !*sample; } killcmd() { if(!intrup) { cmdline(); printf("Command killed"); if(!display_up) nl(); } } cd(dir, flag) char *dir; int flag; { if(flag) { cmdline(); #ifdef OSK printf("cd %s", dir); } #else printf("cd %s\r", dir); } else outc('\r'); #endif fflush(stdout); if( #ifndef OSK access(dir, 5)==0 && #endif chdir(dir)==0) { newdir(); return 1; } return 0; } syscom(rd) int rd; /* should I redraw? */ { char buf[MAXLINE]; static char lastcmd[MAXLINE] = ""; char inps(); cmdline(); extty(); putchar(rd?SHELLSYM:'&'); if(inps(buf, lastcmd, 0)=='\033') { entty(); redraw(); display_up=1; killcmd(); return; } else strcpy(lastcmd, buf); sys(buf, rd); entty(); } isdir(entry) struct entry *entry; { #ifdef OSK return((entry->e_stat.st_mode)&S_IFDIR); #else return((entry->e_stat.st_mode&S_IFMT)==S_IFDIR); #endif } sample(name) char *name; { int col; int c, i; FILE *tfp; if(!(tfp = fopen(name, "r"))) { wperror(name); return; } i=0; do { cmdline(); col = 0; for(c=fgetc(tfp); col<72 && !feof(tfp); c=fgetc(tfp)) col+=ctlout(c); standend(); if(display_up) outc('\r'); else outc('\n'); } while(!feof(tfp) && (i=getch())=='?'); fclose(tfp); if(i && i!=' ' && i!='q' && i!='?') ungetch(i); } macro(c) char c; { if(c==NOMAC) return 0; else if(!macbuf[c]) return 0; else if(c==c_macro) { cmdline(); printf("Recursive macro."); endmac(); return 0; } else { c_macro = c; macptr = macbuf[c]; return 1; } } getch() { char c; if(ungetptr>ungetbuf) return *--ungetptr; if(*macptr) if(*macptr=='\007') { macptr++; if(*macptr!='\007') return getchar(); else { if((c=getchar()) != '\n') macptr--; else macptr++; return (c=='\n')?getch():c; } } else if(*macptr=='\\') { if(macptr[1]=='\007') macptr++; return *macptr++; } else return *macptr++; else { endmac(); return getchar(); } } endmac() { c_macro=NOMAC; macptr=""; } ungetch(c) char c; { if(ungetptr-ungetbuf>SMALLBUF) return; *ungetptr++=c; } define() { int c; char buf[SMALLBUF]; cmdline(); fflush(stdout); printf("define "); c = getch(); if(intrup) return; ctloutc(c); printf(" as ["); if(inps(buf, macbuf[c], ']')=='\033') { killcmd(); return; } printf("]"); defent(c, buf); } defent(c, buf) char c; char *buf; { if(macbuf[c]) free(macbuf[c]); if(!buf[0]) { macbuf[c]=0; return; } macbuf[c] = (char *)malloc(strlen(buf)+1); if(!macbuf[c]) { cmdline(); printf("No room"); return; } strcpy(macbuf[c], buf); } defmacs() { #ifdef OSK defent(' ', "$more %\n"); defent('%', "$%\n"); defent('s', "$scred %\n"); defent('b', "=..\n"); defent('c', "$copy % "); #else defent('/', "=/"); defent('.', "=."); defent(' ', "!more %\n"); defent('%', "!%\n"); defent('$', "!vi /tmp/br.env.$$\n"); defent('v', "!vi %\n"); #endif defent('~', "=~\n"); } definitions() { int i; cmdline(); for(i=0; i