More updates to browse
Peter da Silva
peter at ficc.uu.net
Fri Feb 9 06:23:47 AEST 1990
In this release I've added code submitted by several people. The screen
handling has been improved, Rename now works on tagged files, and a new
pseudovariable ($*) is available that matches all tagged files.
:
#! /bin/sh
# This is a shell archive, created at Ferranti International Controls Corp.
# by peter (peter da silva,2419T 5180) on Thu Feb 8 13:21:16 1990
# Remove anything before the "#! /bin/sh" line, then unpack it by saving
# it into a file and typing "sh file". If you do not have sh, you need
# unshar, a dearchiving program which is widely available. In the absolute
# wost case, you can crack the files out by hand.
# If the archive is complete, you will see the message "End of archive."
# at the end.
# This archive contains the following files...
# 'Makefile'
# 'browse.doc'
# 'browse.c'
# To extract them, run the following through /bin/sh
echo x - Makefile
sed 's/^X//' > Makefile << '//END_OF_FILE'
XCFILES=browse.c
XOFILES=$(CFILES:.c=.o)
XTFILES=Makefile browse.doc $(CFILES)
X#
X# Standard XENIX/USG flags
X#
XCFLAGS=-O -DUSG=1
XLFLAGS=-O
XLIBS=-ltermlib
X#
X# BSD flags
X#
X#BSD# CFLAGS=-g -DBSD=1
X#BSD# LFLAGS=-g -Bstatic
X#BSD# LIBS=-ltermlib
X
Xbrowse: $(OFILES)
X $(CC) $(LFLAGS) $(OFILES) -o browse $(LIBS)
X
Xbrowse.shar: $(TFILES)
X shar $(TFILES) >! browse.shar
//END_OF_FILE
echo x - browse.doc
sed 's/^X//' > browse.doc << '//END_OF_FILE'
XBrowse is a screen-oriented directory browser, based on the metaphor of using
X'VI' to edit an 'ls -l' listing.
X
XCommands:
X SPACE Enter a subdirectory, or display a file.
X & Run a program that won't clobber the screen.
X ! Run a program.
X = Enter a directory name.
X ? Peek at the current file.
X [ Define a macro.
X H Go to the top of the page.
X J Go to the bottom of the directory.
X K Go to the top of the directory.
X L Go to the bottom of the page.
X ^L Repaint screen.
X M Display macros.
X N,^F Go down 20 lines.
X P,^B Go up 20 lines.
X R Rename a file.
X S Save definitions.
X dd Delete file(s). (ask for verification)
X DD Delete file(s).
X h Place cursor at beginning of line.
X l Move cursor to end of line.
X < Display file names only.
X > Display long directory listing.
X + Make a file permanent.
X ( Make the current file permanent.
X ) Make the current file non-permanent.
X j,^J Go down a line.
X k,^K Go up a line.
X n,^D Go down 11 lines.
X p,^U Go up 11 lines.
X
X qq,QQ,ZZ Exit.
X
X r Re-read directories.
X
X t Toggle tag on current file.
X T Tag all files.
X U Untag all files.
X
XMacros:
X [xtext] Define x as text.
X
XWithin text:
X % Current filename.
X # Current directory.
X ! Previous command.
X $x Macro for key x
X $$ Current process ID
X $* All tagged files.
X ~ Home directory.
X ^K One character from previous command.
X @x Execute macro for key x
X \x Enter special character x
X \nnn nnn, octal
X \^x Control-x
X
XDefault macros:
X SPACE !more %<CR>
X % !%<CR>
X . =.
X / =/
X ~ =~
X v !vi %<CR>
X $ !vi /tmp/br.env.$$<CR>
X -- this file is loaded as your environment
X -- whenever you run a program.
X
XThe contents of the environment variable BROWSE are executed as a macro
Xwhen you start up.
//END_OF_FILE
echo x - browse.c
sed 's/^X//' > browse.c << '//END_OF_FILE'
X/* -- Just what the hell am I ??? --- */
X/* (If this is made from MAKEFILE, BSD or USG should be set.) */
X
X#include <stdio.h>
X
X#ifndef BSD
X# if defined(sun) || defined(sun3)
X# define BSD 1
X# endif
X#endif
X
X#ifndef USG
X# ifdef L_ctermid
X# define USG 1
X# endif
X# ifdef M_XENIX
X# define USG 1
X# endif
X#endif
X
X#ifdef BSD
X# undef USG
X#endif
X
X#ifdef USG
X# define rindex strrchr
X# ifdef M_XENIX
X# define GETCWD
X# define SIGNAL int
X# else
X# define minor(i) ((i)&0xFF)
X# define major(i) minor((i)>>8)
X# define SIGNAL void
X# endif
X#else
X# ifdef BSD
X# define SIGNAL void
X# else
X# define SIGNAL int
X# include <whoami.h>
X# endif
X#endif
X
X/* -- Miscellaneous include files -- */
X
X#include <sys/param.h> /* NCARGS, and others */
X#ifndef M_XENIX
X# include <sys/types.h> /* data types for various files */
X#endif
X#include <sys/stat.h> /* stat data structure for getdir(), statout() */
X#include <sys/dir.h> /* dir data structure for getdir() */
X#include <pwd.h> /* passwd data structure for u_name() */
X#include <grp.h> /* group data structure for g_name() */
X#ifdef BSD
X# include <sys/time.h> /* time data structure for printime() */
X#else
X# include <time.h> /* time data structure for printime() */
X#endif
X#ifdef USG
X# ifdef M_XENIX
X# include <sys/ioctl.h>
X# endif
X# include <termio.h>
X#else
X# include <sgtty.h> /* terminal modes for tinit(), tend() */
X#endif
X#include <signal.h>
X
X#ifndef MAXNAMLEN
X# ifdef BSD
X# define MAXNAMLEN 256
X# else
X# define MAXNAMLEN DIRSIZ
X# endif
X#endif
X
X/* -- make information --
XBUILD
Xbrowse: browse.c
X cc browse.c -O -o browse -ltermlib
XEND
X*/
X
X/* -- Miscellaneous defines -- */
X#define FALSE 0
X#define TRUE 1
X
X#define MAXENTS 320
X#define MAXID 16
X#define MAXLINE 81
X#define NCOL 64
X#define MAXNAME 14
X#define FILENAME 256
X#define MAXARGC (NCARGS/16) /* Estimate max ARGC */
X#define CHARSET 256 /* Number of macros == size of byte */
X#define NOMAC (0) /* Null macro (last) */
X#define TERMBUF 1024 /* Size of term buf for termcap */
X#define SMALLBUF 256
X
X/* -- Extended directory entry format -- */
Xstruct entry {
X char *e_name;
X int e_flags;
X#define FTAGGED (1<<0)
X#define FPERMANENT (1<<1)
X struct stat e_stat; /* file status field */
X char e_uname[9]; /* user name */
X char e_gname[9]; /* user's group name */
X}
X*xentries[MAXENTS], **entries=xentries;
Xint nentries;
X
X/* -- Look-up cache for user names -- */
Xstruct idtab {
X int id_id; /* user (or group) id */
X char id_name[9]; /* name[8] + filler */
X}
Xu_list[MAXID], /* Matched user id's. */
Xg_list[MAXID]; /* ditto group */
Xint u_ptr=0, g_ptr=0; /* current entries */
X
X/* -- Global variables -- */
XFILE *efp; /* Environment file */
Xchar efname[MAXLINE]; /* " name */
Xchar *tent; /* Pointer to tbuf */
Xchar PC; /* Pad character */
Xchar *UP, *BC; /* Upline, backsapce character */
Xshort ospeed; /* Terminal output speed */
Xchar termbuf[TERMBUF]; /* Place to put term info */
X
Xchar *macbuf[CHARSET], ungetbuf[SMALLBUF]; /* Buffers for pushback and macros */
Xchar c_macro=NOMAC; /* current macro */
Xchar *macptr = ""; /* Pointer to currently executing macro */
Xchar *ungetptr = ungetbuf; /* Pointer to pushed-back characters */
X
Xchar *errname; /* Name of file error found in */
Xextern int errno; /* system error number */
Xint xerrno; /* extended error number */
Xint ccol=NCOL; /* Width of used display, current column */
Xint quickmode; /* short display mode (files only) */
X
X#ifdef USG
Xstruct termio rawbuf;
Xstruct termio cookedbuf;
X#else
Xstruct sgttyb sgbuf; /* buffer for terminal mode info */
Xint rawflags, cookflags; /* flags for raw & cooked tty mode */
X#endif
X
Xchar *cm, /* Cursor motion */
X *cs, /* Change scrolling region */
X *sf, /* - scroll forward */
X *sr, /* - scroll backwards */
X *ce, /* Clear to end of line */
X *cl, /* Clear screen */
X *al, /* Insert line */
X *dl, /* delete ditto */
X *so, /* standout */
X *se, /* standout end */
X *us, /* underline */
X *ue, /* underline end */
X *ti, /* Init terminal */
X *te; /* Reset terminal */
Xint li, /* lines on screen */
X co; /* columns ditto */
Xchar xn; /* Magic cookie kludge */
X
X/* -- Global error messages -- */
Xchar *emesg[4]={
X "??",
X#define TOO_MANY 1
X "Too many directory entries",
X#define NOMATCH 2
X "No match",
X 0
X};
X
Xint top, curr; /* Positions of screen in directory */
X#define bottom ((top+nlines>nentries)?nentries:(top+nlines))
Xchar *dot; /* name of current directory */
Xint nlines; /* number of lines displayed on page */
Xchar display_up; /* Does the display exist? */
Xint todump=1; /* Do we want to dump data? */
Xint ended; /* Have we quite finished? */
Xint intrup; /* Have we been interrupted? */
Xchar *HOME; /* Where did I start from? */
Xchar *SHELL; /* How do I run programs? */
X
X/* -- types of functions !!! */
Xchar *getenv(), *tgetstr();
Xchar *malloc();
X
X#define NEW(t) (t *)malloc(sizeof (t))
X#define NIL(t) ((t) 0)
X
X/* -- Code starts here: dummy main -- */
Xmain(ac, av, ep)
Xint ac;
Xchar **av;
Xchar **ep;
X{
X if(ac>1) chdir(av[1]);
X
X sprintf(efname, "/tmp/br.env.%d", getpid());
X HOME=getenv("HOME");
X SHELL=getenv("SHELL");
X dumpenv(ep);
X
X intrup=0;
X tinit(getenv("TERM"));
X clear_all();
X browse();
X tend();
X unlink(efname);
X}
X
Xclear_all()
X{
X int i;
X
X for(i = 0; i < MAXENTS; i++)
X entries[i] = 0;
X}
X
Xchar *clone(name)
Xchar *name;
X{
X char *hold;
X
X hold = (char *)malloc(strlen(name)+1);
X
X if(hold==0)
X return 0;
X strcpy(hold, name);
X return hold;
X}
X
Xnewname(e, name)
Xstruct entry *e;
Xchar *name;
X{
X if(e->e_name)
X free(e->e_name);
X e->e_name = clone(name);
X}
X
X#if BSD
Xreadent(dp, buffer)
XDIR *dp;
Xchar *buffer;
X{
X struct direct *ptr;
X
X do {
X ptr = readdir(dp);
X if(!ptr) return 0;
X } while(ptr->d_ino == 0);
X
X strcpy(buffer, ptr->d_name);
X return 1;
X}
X#else
X#define opendir(n) fopen(n, "r")
X#define DIR FILE
Xreadent(dp, buffer)
XDIR *dp;
Xchar *buffer;
X{
X struct direct db;
X while(fread(&db, sizeof(struct direct), 1, dp)) {
X if(db.d_ino) {
X strncpy(buffer, db.d_name, MAXNAMLEN);
X buffer[MAXNAMLEN] = 0;
X return 1;
X }
X }
X return 0;
X}
X#define closedir fclose
X#endif
X
Xgetdir()
X{
X char *u_name(), *g_name();
X DIR *dp;
X static char buffer[MAXNAMLEN+1];
X int i, p;
X
X if(!(dp = opendir("."))) {
X errname=".";
X return FALSE;
X }
X
X p = 0;
X for(i = 0; i < nentries; i++) {
X if(entries[i]->e_flags & FPERMANENT) {
X if(p != i) {
X struct entry *hold;
X hold = entries[p];
X entries[p] = entries[i];
X entries[i] = hold;
X }
X p++;
X }
X }
X
X for(nentries = p; !intrup && nentries < MAXENTS; nentries++) {
X if(!entries[nentries]) {
X entries[nentries] = NEW(struct entry);
X if(!entries[nentries])
X break;
X entries[nentries]->e_name = NIL(char *);
X }
X
X if(!readent(dp, buffer))
X break;
X
X if(stat(buffer, &entries[nentries]->e_stat)==-1) {
X closedir(dp);
X errname=buffer;
X return FALSE;
X }
X
X newname(entries[nentries], buffer);
X
X entries[nentries]->e_flags = 0;
X
X strcpy(entries[nentries]->e_uname,
X u_name(entries[nentries]->e_stat.st_uid));
X
X strcpy(entries[nentries]->e_gname,
X g_name(entries[nentries]->e_stat.st_gid));
X }
X
X closedir(dp);
X
X if(intrup)
X return FALSE;
X
X if(nentries>=MAXENTS || entries[nentries]==NIL(struct entry *)) {
X errno=0;
X xerrno=TOO_MANY;
X errname=".";
X return FALSE;
X }
X
X sortdir();
X
X if(intrup)
X return FALSE;
X return TRUE;
X}
X
Xat_current()
X{
X at_file(curr);
X}
X
Xat_file(file)
Xint file;
X{
X if(display_up) {
X if(file < top || file >= top+nlines)
X return 0;
X at(0, curr-top+2);
X } else {
X if(file != curr)
X return 0;
X cmdline();
X }
X return 1;
X}
X
Xdisplay_flags(flags)
X{
X outc((flags&FTAGGED)?'+':((flags&FPERMANENT)?'!':' '));
X}
X
Xrepaint_flags()
X{
X if(!display_up) return;
X at(quickmode?0:(ccol-1), curr-top+2);
X display_flags(entries[curr]->e_flags);
X}
X
Xrepaint_current()
X{
X if(!display_up) return;
X at_current();
X dump(curr, curr+1);
X}
X
Xtag()
X{
X entries[curr]->e_flags ^= FTAGGED;
X repaint_flags();
X}
X
Xtag_all(flag)
Xint flag;
X{
X int i;
X
X for(i = 0; i < nentries; i++)
X if(flag)
X entries[i]->e_flags |= FTAGGED;
X else
X entries[i]->e_flags &= ~FTAGGED;
X if(display_up)
X todump = TRUE;
X}
X
Xdelete_from_display(file)
Xint file;
X{
X if(!display_up) return;
X
X if(file>=top+nlines) return;
X
X if(file < top) file = top;
X
X scroll(2+file-top, 2+nlines, 1);
X at(0, 2+nlines-1);
X if(top+nlines >= nentries)
X outc('~');
X else
X dump(bottom, bottom+1);
X}
X
Xdelete_file_entry(file)
Xint file;
X{
X struct entry *hold;
X int i;
X
X delete_from_display(file);
X
X hold = entries[file];
X for(i=file; i<nentries-1; i++)
X entries[i]=entries[i+1];
X entries[nentries-1]=hold;
X nentries--;
X
X if(file < curr || curr >= nentries) {
X curr--;
X if(top >= nentries) {
X top--;
X display_up = 0;
X todump = 1;
X }
X }
X}
X
Xremove_one(file, doit)
Xint file;
Xint doit;
X{
X if(!doit) {
X cmdline();
X outs("Delete ");
X ctlouts(entries[file]->e_name);
X outs(" [n]?");
X doit = getchar() == 'y';
X outs(doit?"Yes.":"No.");
X }
X if(doit) {
X if(unlink(entries[file]->e_name) == 0) {
X cmdline();
X outs("Deleted ");
X ctlouts(entries[file]->e_name);
X outs(".");
X delete_file_entry(file);
X return 1;
X } else {
X wperror(entries[file]->e_name);
X return 0;
X }
X }
X return 0;
X}
X
Xremove(doit)
Xint doit;
X{
X int i;
X int found_tags;
X
X found_tags = 0;
X i = 0;
X while(i < nentries) {
X if(entries[i]->e_flags & FTAGGED) {
X found_tags = 1;
X if(!remove_one(i, doit)) /* decrements nentries */
X break;
X } else
X i++;
X }
X if(!found_tags)
X remove_one(curr, doit);
X}
X
Xinsert_entry_at(ent, i)
Xstruct entry *ent;
Xint i;
X{
X struct entry *hold;
X int j;
X
X /* Allocate slot at end */
X if(!entries[nentries]) {
X entries[nentries] = NEW(struct entry);
X if(!entries[nentries])
X return 0;
X entries[nentries]->e_name = NIL(char *);
X } else if(entries[nentries]->e_name) {
X free(entries[nentries]->e_name);
X entries[nentries]->e_name = NIL(char *);
X }
X
X /* Copy data into slot */
X *entries[nentries] = *ent;
X entries[nentries]->e_name = clone(ent->e_name);
X if(!entries[nentries]->e_name)
X return 0;
X
X if(i != nentries) {
X /* Rotate slot to middle */
X hold = entries[nentries];
X for(j = nentries; j > i; j--)
X entries[j] = entries[j-1];
X entries[i] = hold;
X }
X nentries++;
X
X if(display_up) {
X if(i < top)
X i = top;
X if(i >= bottom)
X return;
X scroll(2+i-top, 2+nlines, -1);
X at(0, 2+i-top);
X dump(i, i+1);
X }
X}
X
Xinsert_entry(ent)
Xstruct entry *ent;
X{
X int i;
X
X if(nentries >= MAXENTS)
X return 0;
X
X for(i = 0; i < nentries; i++)
X if(entcmp(&ent, &entries[i]) < 0)
X break;
X
X return insert_entry_at(ent, i);
X}
X
Xmove()
X{
X char scratch[FILENAME];
X char inps();
X int i;
X
X
X for(i = 0; i < nentries; i++)
X if(entries[i]->e_flags & FTAGGED)
X break;
X cmdline();
X if(i == nentries) {
X outs("Rename ");
X ctlouts(entries[curr]->e_name);
X } else {
X outs("Move ");
X ctlouts(entries[i]->e_name);
X outs(" (...) to ");
X }
X outc(' ');
X if(inps(scratch, entries[curr]->e_name, 0)=='\033') {
X killcmd();
X return;
X }
X if(i == nentries)
X domove(curr, scratch);
X else {
X for(i = 0; i < nentries; i++) {
X if(entries[i]->e_flags & FTAGGED) {
X char tmp[FILENAME+1];
X sprintf(tmp, "%s/%s",
X scratch, entries[i]->e_name);
X domove(i, tmp);
X }
X }
X }
X}
X
Xdomove(ent, newname)
Xint ent;
Xchar *newname;
X{
X struct entry hold;
X hold = *entries[curr];
X
X if(link(entries[ent]->e_name, newname)!=0) {
X char tmbuf[42];
X sprintf(tmbuf, "(rename %s %s)", entries[ent]->e_name, newname);
X wperror(tmbuf);
X return;
X }
X if(unlink(entries[ent]->e_name)!=0) {
X wperror(entries[ent]->e_name);
X return;
X }
X
X hold.e_name = newname;
X hold.e_flags &= ~FTAGGED;
X
X delete_file_entry(ent);
X insert_entry(&hold);
X}
X
Xpname(name, mode)
Xchar *name;
Xint mode;
X{
X int i;
X char *slash, *rindex();
X int max=quickmode?MAXLINE:(MAXNAME+1);
X
X if((mode&S_IFMT)==S_IFDIR)
X max--;
X else if((mode&S_IFMT)==S_IFREG && (mode&0111))
X max--;
X else if((mode&S_IFMT)!=S_IFREG)
X max--;
X
X if(!quickmode && (slash=rindex(name, '/'))) {
X name=slash;
X outc('<');
X max--;
X }
X for(i=0; i<max && *name; name++)
X i += ctlout(*name);
X standend();
X if(i==max && *name)
X outs("\b>");
X if((mode&S_IFMT)==S_IFDIR) {
X outc('/');
X }
X else if((mode&S_IFMT)==S_IFREG && (mode&0111)) {
X outc('*');
X }
X else if((mode&S_IFMT)!=S_IFREG) {
X outc('?');
X }
X}
X
Xsortdir()
X{
X int entcmp();
X qsort(entries, nentries, sizeof(struct entry *), entcmp);
X}
X
Xaddname(flag)
Xchar flag;
X{
X char buf[FILENAME], *ptr, *tmp;
X char scratch[FILENAME];
X struct entry hold;
X char inps();
X
X cmdline();
X outs("Add ");
X if(inps(scratch, entries[curr]->e_name, 0)=='\033') {
X killcmd();
X return;
X }
X
X if(stat(scratch, &hold.e_stat)==-1) {
X wperror(scratch);
X return;
X }
X if(flag!='+' && *scratch != '/') {
X strcpy(buf, dot);
X ptr = scratch;
X for(;;) { /* eat '../' and './' */
X if(ptr[0]=='.' && ptr[1]=='.' &&
X (ptr[2]=='/' || !ptr[2])) {
X tmp = rindex(buf, '/');
X if(!tmp) break;
X *tmp=0;
X ptr += 2+(ptr[2]=='/');
X continue;
X }
X if(ptr[0]=='.' &&
X (ptr[1]=='/' || !ptr[1])) {
X ptr += 1+(ptr[1]=='/');
X continue;
X }
X break;
X }
X if(*ptr) {
X strcat(buf, "/");
X strcat(buf, ptr);
X }
X hold.e_name = buf;
X } else
X hold.e_name = scratch;
X strcpy(hold.e_uname,
X u_name(hold.e_stat.st_uid));
X strcpy(hold.e_gname,
X g_name(hold.e_stat.st_gid));
X hold.e_flags = 0;
X if(flag!='+')
X hold.e_flags |= FPERMANENT;
X insert_entry(&hold);
X}
X
Xaddperm()
X{
X char buf[FILENAME], *ptr, *tmp;
X struct entry hold;
X int entcmp(), i;
X
X if(entries[curr]->e_flags & FPERMANENT)
X return;
X
X if(entries[curr]->e_name[0]!='/') {
X strcpy(buf, dot);
X ptr = entries[curr]->e_name;
X for(;;) { /* eat '../' and './' */
X if(ptr[0]=='.' && ptr[1]=='.' &&
X (ptr[2]=='/' || !ptr[2])) {
X tmp = rindex(buf, '/');
X if(!tmp) break;
X *tmp=0;
X ptr += 2+(ptr[2]=='/');
X continue;
X }
X if(ptr[0]=='.' &&
X (ptr[1]=='/' || !ptr[1])) {
X ptr += 1+(ptr[1]=='/');
X continue;
X }
X break;
X }
X if(*ptr) {
X strcat(buf, "/");
X strcat(buf, ptr);
X }
X hold = *entries[curr];
X
X hold.e_name = buf;
X hold.e_flags &= ~FTAGGED;
X hold.e_flags |= FPERMANENT;
X insert_entry(&hold);
X } else {
X entries[curr]->e_flags |= FPERMANENT;
X entries[curr]->e_flags &= ~FTAGGED;
X repaint_flags();
X }
X}
X
Xdelperm()
X{
X entries[curr]->e_flags &= ~(FPERMANENT|FTAGGED);
X repaint_flags();
X}
X
Xentcmp(e1, e2)
Xstruct entry **e1, **e2;
X{
X if((*e1)->e_name[0] == '/') {
X if((*e2)->e_name[0] != '/')
X return 1;
X } else if((*e2)->e_name[0] == '/')
X return -1;
X
X return strcmp((*e1)->e_name, (*e2)->e_name);
X}
X
Xdump(start, end)
Xint start;
Xint end;
X{
X int i;
X int lo = (start<nentries)?start:nentries;
X int hi = (end<nentries)?end:nentries;
X
X for(i=lo; i<hi; i++) {
X statout(entries[i]->e_name,
X &entries[i]->e_stat,
X entries[i]->e_uname,
X entries[i]->e_gname,
X entries[i]->e_flags);
X nl();
X }
X return TRUE;
X}
X
Xstatout(name, sbuf, user, group, flags)
Xchar *name;
Xstruct stat *sbuf;
Xchar *user, *group;
Xint flags;
X{
X int mode = sbuf->st_mode;
X
X if(!quickmode) {
X printf("%5u ", sbuf->st_ino);
X
X if((mode&S_IFMT)==S_IFCHR) outc('c');
X else if((mode&S_IFMT)==S_IFBLK) outc('b');
X else if((mode&S_IFMT)==S_IFDIR) outc('d');
X else if((mode&S_IFMT)==S_IFREG) outc('-');
X else outc('?');
X triad((mode>>6)&7, mode&S_ISUID, 's');
X triad((mode>>3)&7, mode&S_ISGID, 's');
X triad(mode&7, mode&S_ISVTX, 't');
X outc(' ');
X
X printf("%3u ", sbuf->st_nlink);
X printf("%-8s ", user);
X printf("%-8s ", group);
X
X if((mode&S_IFMT)==S_IFREG || (mode&S_IFMT)==S_IFDIR)
X printf("%7ld ", sbuf->st_size);
X else
X printf("%3d,%3d ",
X major(sbuf->st_rdev),
X minor(sbuf->st_rdev));
X
X outc(' ');
X printime(&sbuf->st_mtime);
X }
X
X display_flags(flags);
X pname(name, sbuf->st_mode);
X}
X
Xchar *
Xu_name(uid)
Xint uid;
X{
X int i;
X struct passwd *pwptr, *getpwuid();
X
X for(i=0; i<u_ptr; i++)
X if(u_list[i].id_id==uid)
X return u_list[i].id_name;
X
X if(u_ptr>=MAXID) /* cache full */
X u_ptr = 0; /* simplistic algorithm, wrap to beginning */
X /* with MAXID >> # common id's it's good enough */
X
X u_list[u_ptr].id_id=uid;
X
X if(pwptr=getpwuid(uid)) { /* Copy name */
X for(i=0; pwptr->pw_name[i]>' '; i++)
X u_list[u_ptr].id_name[i]=pwptr->pw_name[i];
X u_list[u_ptr].id_name[i]=0;
X }
X else /* Default to UID */
X sprintf(u_list[u_ptr].id_name, "%d", uid);
X
X return u_list[u_ptr++].id_name;
X}
X
Xchar *
Xg_name(gid)
Xint gid;
X{
X int i;
X struct group *grptr, *getgrgid();
X
X for(i=0; i<g_ptr; i++)
X if(g_list[i].id_id==gid)
X return g_list[i].id_name;
X
X if(g_ptr>=MAXID) /* cache full */
X g_ptr = 0; /* simplistic algorithm, wrap to beginning */
X /* with MAXID >> # common id's it's good enough */
X
X g_list[g_ptr].id_id=gid;
X
X if(grptr=getgrgid(gid)) { /* Copy name */
X for(i=0; grptr->gr_name[i]>' '; i++)
X g_list[g_ptr].id_name[i]=grptr->gr_name[i];
X g_list[g_ptr].id_name[i]=0;
X }
X else /* Default to UID */
X sprintf(g_list[g_ptr].id_name, "%d", gid);
X
X return g_list[g_ptr++].id_name;
X}
X
Xprintime(clock)
Xlong *clock;
X{
X struct tm *tmbuf, *localtime();
X static char *months[12]= {
X "Jan","Feb","Mar","Apr","May","Jun",
X "Jul","Aug","Sep","Oct","Nov","Dec"
X };
X
X tmbuf=localtime(clock);
X printf("%2d %3s %02d %2d:%02d",
X tmbuf->tm_mday,
X months[tmbuf->tm_mon],
X tmbuf->tm_year,
X tmbuf->tm_hour,
X tmbuf->tm_min);
X}
X
Xheader()
X{
X int i;
X if(quickmode)
X printf(" File Name");
X else
X printf(
X"Inode Long mode LNX User Group Size/Dev Modify Time File name"
X );
X nl();
X}
X
Xtriad(bits, special, code)
Xint bits, special;
Xchar code;
X{
X if(bits&4) outc('r');
X else outc('-');
X
X if(bits&2) outc('w');
X else outc('-');
X
X if(special) outc(code);
X else if(bits&1) outc('x');
X else outc('-');
X}
X
Xouts(s)
Xchar *s;
X{
X int outc();
X
X if(s)
X tputs(s, 0, outc);
X}
X
Xoutc(c)
Xchar c;
X{
X putchar(c);
X}
X
X/* Screen manipulation primitives: dumb set for smart terminals */
Xat(x, y)
Xint x, y;
X{
X outs(tgoto(cm, x, y));
X}
X
Xnl()
X{
X outs(ce);
X outc('\n');
X}
X
X
X/* Scroll lines in window (from:to) n lines */
Xscroll(from, to, n)
Xint from, to, n;
X{
X if(cs && sf && sr) {
X outs(tgoto(cs, from, to-1));
X if(n<0) {
X at(0, from);
X while(n++)
X outs(sr);
X }
X else {
X at(0, to-1);
X while(n--)
X outs(sf);
X }
X outs(tgoto(cs, 0, li-1));
X }
X else if(al && dl) {
X if(n<0) {
X int i=n;
X outs(tgoto(cm, 0, to+n));
X while(i++)
X outs(dl);
X outs(tgoto(cm, 0, from));
X while(n++)
X outs(al);
X }
X else {
X int i=n;
X outs(tgoto(cm, 0, from));
X while(i--)
X outs(dl);
X outs(tgoto(cm, 0, to-n));
X while(n--)
X outs(al);
X }
X }
X}
X
Xwperror(file)
Xchar *file;
X{
X extern int errno;
X extern char *sys_errlist[];
X
X cmdline();
X ctlouts(file);
X ctlouts(": ");
X ctlouts(errno?sys_errlist[errno]:emesg[xerrno]);
X if(!display_up)
X nl();
X}
X
Xfperror(prog, file)
Xchar *prog, *file;
X{
X extern int errno;
X
X fprintf(stderr, "%s -- ", prog);
X if(errno)
X perror(file);
X else
X fprintf(stderr, "%s: %s\n", file, emesg[xerrno]);
X}
X
Xtinit(name)
Xchar *name;
X{
X char *termptr;
X char tbuf[TERMBUF], *tmp;
X SIGNAL intr();
X#ifdef BSD
X SIGNAL stop();
X#endif
X
X termptr = termbuf;
X
X tgetent(tbuf, name);
X
X tmp = tgetstr("pc", &termptr);
X if(tmp) PC = *tmp;
X UP = tgetstr("up", &termptr);
X BC = tgetstr("bc", &termptr);
X cm = tgetstr("cm", &termptr);
X cs = tgetstr("cs", &termptr);
X sf = tgetstr("sf", &termptr);
X sr = tgetstr("sr", &termptr);
X ce = tgetstr("ce", &termptr);
X cl = tgetstr("cl", &termptr);
X al = tgetstr("al", &termptr);
X dl = tgetstr("dl", &termptr);
X us = tgetstr("us", &termptr);
X ue = tgetstr("ue", &termptr);
X so = tgetstr("so", &termptr);
X se = tgetstr("se", &termptr);
X ti = tgetstr("ti", &termptr);
X te = tgetstr("te", &termptr);
X li = tgetnum("li");
X co = tgetnum("co");
X xn = tgetflag("xn");
X
X nlines=li-3;
X
X#ifdef USG
X ioctl(1, TCGETA, &rawbuf);
X cookedbuf = rawbuf;
X rawbuf.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
X rawbuf.c_cc[VMIN] = 1;
X rawbuf.c_cc[VTIME] = 0;
X#else
X gtty(1, &sgbuf);
X ospeed=sgbuf.sg_ospeed;
X quickmode=ospeed<10;
X cookflags=sgbuf.sg_flags;
X sgbuf.sg_flags = (sgbuf.sg_flags&~ECHO)|CBREAK;
X rawflags=sgbuf.sg_flags;
X#endif
X signal(SIGINT, intr);
X#ifdef BSD
X signal(SIGTSTP, stop);
X#endif
X rawtty();
X}
X
Xint tmode=0;
X
Xentty()
X{
X if(!tmode)
X outs(ti);
X tmode=1;
X}
X
Xextty()
X{
X if(tmode)
X outs(te);
X tmode=0;
X}
X
Xrawtty()
X{
X#ifdef USG
X ioctl(1, TCSETA, &rawbuf);
X#else
X sgbuf.sg_flags=rawflags;
X stty(1, &sgbuf);
X#endif
X entty();
X}
X
Xcooktty()
X{
X#ifdef USG
X ioctl(1, TCSETA, &cookedbuf);
X#else
X sgbuf.sg_flags=cookflags;
X stty(1, &sgbuf);
X#endif
X extty();
X}
X
XSIGNAL intr()
X{
X signal(SIGINT, intr);
X intrup=1;
X bell();
X}
X
X#ifdef BSD
XSIGNAL stop()
X{
X signal(SIGTSTP, stop);
X intrup=1;
X tend();
X kill(getpid(), SIGSTOP);
X rawtty();
X display_up=0;
X}
X#endif
X
Xtend()
X{
X cmdline();
X cooktty();
X fflush(stdout);
X}
X
Xchar *
Xpwd()
X#ifdef GETCWD
X{
X static char mydir[FILENAME+1] = "";
X char *getcwd();
X
X return getcwd(mydir, FILENAME);
X}
X#else
X{
X static char mydir[FILENAME] = "";
X int status;
X int pip[2];
X int n;
X SIGNAL (*sigint)();
X SIGNAL (*sigquit)();
X#ifdef BSD
X SIGNAL (*sigtstp)();
X#endif
X
X sigint = signal(SIGINT, SIG_IGN);
X sigquit = signal(SIGQUIT, SIG_IGN);
X#ifdef BSD
X sigtstp = signal(SIGTSTP, SIG_IGN);
X#endif
X
X if(pipe(pip)<0)
X return 0;
X
X if(!fork()) {
X close(1);
X dup(pip[1]);
X close(pip[0]);
X execl("/bin/pwd", "pwd", 0);
X exit(-1);
X }
X close(pip[1]);
X wait(&status);
X signal(SIGINT, sigint);
X signal(SIGQUIT, sigquit);
X#ifdef BSD
X signal(SIGTSTP, sigtstp);
X#endif
X
X if(status) {
X close(pip[0]);
X return "/";
X }
X n = read(pip[0], mydir, FILENAME);
X close(pip[0]);
X if(n<=0)
X return "/";
X mydir[n-1] = 0;
X return mydir;
X}
X#endif
X
Xbrowse()
X{
X int c;
X char *env;
X
X if(env=getenv("BROWSE"))
X macptr = env;
X
X defmacs();
X newdir();
X redraw();
X ended=0;
X
X do {
X if(intrup) {
X intrup=0; /* clear interrupt */
X cmdline(); /* go to the command line */
X outs("Interrupt"); /* let us know about it */
X endmac(); /* clear macros */
X clearin(); /* and input buffer */
X }
X here_i_am();
X fflush(stdout);
X c = getch();
X cmd(c);
X }
X while(!ended);
X}
X
Xclearin()
X{
X fseek(stdin, 0L, 1); /* stay here messily */
X}
X
Xcmd(c)
Xchar c;
X{
X int i;
X
X if(intrup)
X return;
X
X switch(c) {
X case ' ':
X if(isdir(entries[curr])) {
X if(!cd(entries[curr]->e_name))
X wperror(entries[curr]->e_name);
X } else
X if(!macro(c))
X bell();
X else
X cmd(getch());
X break;
X case '&':
X syscom(0);
X break;
X case '!':
X syscom(1);
X break;
X case '=':
X todir();
X break;
X case '?':
X sample(entries[curr]->e_name);
X break;
X case '[':
X define();
X break;
X case 'B'-'@':
X prev(nlines);
X break;
X case 'D'-'@':
X next(nlines/2);
X break;
X case 'F'-'@':
X next(nlines);
X break;
X case 'H':
X curr=top;
X break;
X case 'J':
X tail();
X break;
X case 'K':
X home();
X break;
X case 'L'-'@':
X redraw();
X break;
X case 'L':
X curr=bottom-1;
X break;
X case 'M':
X definitions();
X break;
X case 'N':
X next(nlines);
X break;
X case 'P':
X prev(nlines);
X break;
X case 'R':
X move();
X break;
X case 'S':
X savedefs();
X break;
X case 'U'-'@':
X prev(nlines/2);
X break;
X case 'D':
X case 'd':
X if(getch()==c && !intrup)
X remove(c=='D');
X else
X bell();
X break;
X case 'h':
X ccol=0;
X break;
X case 'l':
X ccol=NCOL;
X break;
X case '<':
X quickmode=1;
X if(display_up) {
X todump=1;
X at(0, 1);
X header();
X }
X break;
X case '+': case '^':
X addname(c);
X break;
X case '(':
X addperm();
X break;
X case ')':
X delperm();
X break;
X case '>':
X quickmode=0;
X if(display_up) {
X todump=1;
X at(0, 1);
X header();
X }
X break;
X case 'J'-'@':
X case 'j':
X newline();
X break;
X case 'K'-'@':
X case 'k':
X upline();
X break;
X case 'n':
X next(nlines/2);
X break;
X case 'p':
X prev(nlines/2);
X break;
X case 'q': case 'Z': case 'Q':
X if(getchar()==c && !intrup)
X ended=1;
X else
X bell();
X break;
X case 'r':
X reload();
X break;
X case 't':
X tag();
X break;
X case 'T': case 'U':
X tag_all(c=='T');
X break;
X default:
X if(!macro(c))
X bell();
X else
X cmd(getch()); /* make sure it does something */
X } /* and thus avoid unneeded redraws */
X}
X
Xcmdline()
X{
X at(0, li-1);
X outs(ce);
X}
X
Xnewdir()
X{
X if(display_up)
X at(0,0);
X fflush(stdout);
X dot=pwd();
X
X if(!getdir())
X wperror(dot);
X
X curr=0;
X top=0;
X topline();
X if(display_up)
X todump=TRUE;
X}
X
Xreload()
X{
X getdir();
X curr=(curr>=bottom)?bottom-1:curr;
X if(display_up) {
X topline();
X todump=TRUE;
X }
X}
X
Xtopline()
X{
X if(display_up)
X at(0,0);
X printf("%s: %d files", dot, nentries);
X nl();
X}
X
Xredraw()
X{
X outs(cl);
X display_up=0;
X topline();
X at(0,1);
X header();
X todump=1;
X display_up=1;
X}
X
Xdumpdata()
X{
X at(0,2);
X dump(top,bottom);
X if(top+nlines>nentries) {
X int i;
X at(0, bottom-top+2);
X for(i=bottom-top; i<nlines; i++) {
X outc('~');
X nl();
X }
X }
X}
X
Xupline()
X{
X if(curr>0)
X curr--;
X else bell();
X}
X
Xhome()
X{
X curr=0;
X}
X
Xnext(l)
X{
X curr += l;
X if(curr>=nentries) curr=nentries-1;
X}
X
Xprev(l)
X{
X curr -= l;
X if(curr<0) curr=0;
X}
X
Xtail()
X{
X curr=nentries-1;
X}
X
Xnewline()
X{
X if(curr<nentries-1)
X curr++;
X else
X bell();
X}
X
Xhere_i_am()
X{
X int c;
X if(*macptr)
X return;
X if(todump)
X display_up = 1;
X if(!display_up) {
X cmdline();
X statout(entries[curr]->e_name,
X &entries[curr]->e_stat,
X entries[curr]->e_uname,
X entries[curr]->e_gname,
X entries[curr]->e_flags);
X at(quickmode?1:ccol, li-1);
X fflush(stdout);
X if((c=getch())=='\n') {
X redraw();
X here_i_am();
X }
X else
X ungetch(c);
X } else if(todump) {
X if(!(curr-top > 0 && curr-top < nlines)) {
X top = curr-nlines/2;
X if(top<0) top=0;
X }
X dumpdata();
X at(quickmode?1:ccol, curr-top+2);
X todump=0;
X } else {
X int lines_to_scroll = curr-top;
X if(lines_to_scroll > 0)
X if((lines_to_scroll -= nlines-1) < 0)
X lines_to_scroll = 0;
X if(lines_to_scroll < 1-nlines) {
X top=curr;
X at(0,2);
X dump(top, bottom);
X } else if(lines_to_scroll > nlines-1) {
X top=curr-nlines+1;
X at(0,2);
X dump(top, bottom);
X } else if(lines_to_scroll) {
X scroll(2, nlines+2, lines_to_scroll);
X top += lines_to_scroll;
X if(lines_to_scroll < 0) {
X at(0, 2);
X dump(top, top-lines_to_scroll);
X } else {
X at(0, 2+nlines-lines_to_scroll);
X dump(bottom-lines_to_scroll, bottom);
X }
X }
X at(quickmode?1:ccol, curr-top+2);
X }
X}
X
Xbell()
X{
X outc(7);
X}
X
Xperform(command)
Xchar *command;
X{
X char cmdbuf[MAXLINE];
X
X cmdline();
X extty();
X outc('!');
X printf(command, entries[curr]->e_name);
X sprintf(cmdbuf, command, entries[curr]->e_name);
X
X system(cmdbuf, 1);
X entty();
X}
X
Xsystem(command, rdflag)
Xchar *command;
Xint rdflag; /* Should I redraw? */
X{
X char scratch[32];
X int status;
X SIGNAL (*sigint)(), (*sigquit)();
X#ifdef BSD
X SIGNAL (*sigtstp)();
X#endif
X char c;
X
X sigint=signal(SIGINT, SIG_IGN);
X sigquit=signal(SIGQUIT, SIG_IGN);
X#ifdef BSD
X sigtstp = signal(SIGTSTP, SIG_IGN);
X#endif
X
X cooktty();
X fflush(stdout);
X strcpy(scratch, entries[curr]->e_name);
X if(!fork()) {
X int i;
X static char *envp[MAXARGC];
X static char env[NCARGS];
X char *hold;
X char line[MAXLINE];
X char *tmp;
X
X signal(SIGINT, SIG_DFL);
X signal(SIGQUIT, SIG_DFL);
X#ifdef BSD
X signal(SIGTSTP, SIG_DFL);
X#endif
X
X if(!(efp=fopen(efname, "r"))) {
X fputc('\n', stderr);
X perror(efname);
X execl(SHELL, SHELL, "-c", command, 0);
X execl("/bin/sh", "sh", "-c", command, 0);
X perror("/bin/sh");
X exit(-77);
X }
X
X i=0;
X tmp=hold=env;
X
X while(!feof(efp)) {
X fgets(line, MAXLINE, efp);
X if(strlen(line)+(tmp-env)>NCARGS)
X break;
X if(line[0]=='$')
X if(tmp>hold) {
X envp[i] = hold;
X i++;
X if(i > MAXARGC-2) break;
X tmp[-1]=0; /* eat line-feed at end */
X hold = tmp;
X }
X strcpy(tmp, line+(line[0]=='$'));
X tmp += strlen(tmp);
X }
X if(tmp>hold) {
X envp[i] = hold;
X i++;
X tmp[-1]=0; /* and eat this one as well */
X }
X sprintf(tmp, "FILE=%s", scratch);
X envp[i++]=tmp;
X envp[i]=0;
X
X if(rdflag)
X putchar('\n');
X else
X putchar('\r');
X fflush(stdout);
X execle(SHELL, SHELL, "-c", command, 0, envp);
X execle("/bin/sh", "sh", "-c", command, 0, envp);
X perror("/bin/sh");
X exit(-77);
X }
X wait(&status);
X signal(SIGINT, sigint);
X signal(SIGQUIT, sigquit);
X#ifdef BSD
X signal(SIGTSTP, sigtstp);
X#endif
X rawtty();
X
X if(rdflag || status!=0)
X display_up=0;
X}
X
Xaddstring(ptr, buf, ip)
Xchar *ptr, *buf;
Xint *ip;
X{
X while(*ptr)
X ctlout(buf[(*ip)++] = *ptr++);
X standend();
X}
X
Xchar
Xinps(buf, text, termin)
Xchar *buf;
Xchar *text;
Xchar termin;
X{
X int i = 0;
X char c, *ptr, *txp;
X int j;
X int found_tags;
X
X txp=text?text:"!";
X
X while(!intrup &&
X (fflush(stdout), c=getch()) != '\033' &&
X c != '\n' &&
X c != termin)
X switch(c) {
X case '\b':
X case '\177':
X if(i>0) {
X printf("\b \b");
X i--;
X }
X else
X bell();
X break;
X case 'U'-'@':
X txp=text?text:"!";
X case 'X'-'@':
X if(i>0)
X while(i>0) {
X printf("\b \b");
X i--;
X }
X else
X bell();
X break;
X case 'K'-'@':
X if(*txp)
X ctloutc(buf[i++] = *txp++);
X break;
X case '%':
X addstring(entries[curr]->e_name, buf, &i);
X break;
X case '#':
X addstring(dot, buf, &i);
X break;
X case '~':
X addstring(HOME, buf, &i);
X break;
X case '@':
X outc(c);
X fflush(stdout);
X c = getch();
X if(!macro(c)) {
X ungetch(c);
X buf[i++]='@';
X }
X else
X outs("\b \b");
X break;
X case '$':
X outc(c);
X fflush(stdout);
X c = getch();
X if(c=='$') {
X char tmp[10];
X sprintf(tmp, "%d", getpid());
X outs("\b \b");
X addstring(tmp, buf, &i);
X }
X else if(c=='*') {
X outs("\b \b");
X for(j = 0; j < nentries; j++)
X {
X if (entries[j]->e_flags & FTAGGED)
X {
X addstring(entries[j]->e_name,
X buf, &i);
X ctlout(buf[i++] = ' ');
X }
X }
X }
X else if(!macbuf[c]) {
X ungetch(c);
X buf[i++]='$';
X }
X else {
X outs("\b \b");
X addstring(macbuf[c], buf, &i);
X }
X break;
X case '!':
X if(*txp)
X addstring(txp, buf, &i);
X else
X ctlout(buf[i++] = '!');
X standend();
X break;
X case '\\':
X outc(c);
X fflush(stdout);
X c=getch();
X if(c=='~' || c=='%' || c=='#' ||
X c=='\\' || c=='!' ||
X c=='K'-'@' || c=='U'-'@' || c=='X'-'@' ||
X c=='\b' || c=='\177' ||
X c==termin || c=='\033' || c=='\n' ||
X c=='@' || c=='$') {
X outc('\b');
X ctloutc(buf[i++]=c);
X break;
X }
X else if(c>='0' && c<='7') {
X int n, val=0;
X for(n=0; n<3 && c>='0' && c<='7'; n++) {
X val = val*8 + c-'0';
X outc('\b');
X ctloutc(val);
X c=getch();
X }
X ungetch(c);
X c=buf[i++]=val;
X break;
X }
X else if(c=='^') {
X outc('\b');
X outc('^');
X fflush(stdout);
X c=getch();
X if(c>='?'&&c<='_') {
X outc('\b');
X ctloutc(buf[i++]=(c-'@')&'\177');
X break;
X }
X else if(c>='`'&&c<='~') {
X outc('\b');
X ctloutc(buf[i++]=c-'`');
X break;
X } /* otherwise default */
X else buf[i++]='^'; /* after adding caret */
X
X } /* otherwise fall through to default */
X else buf[i++]='\\'; /* after adding backslash */
X default:
X ctloutc(buf[i++] = c);
X break;
X }
X
X buf[i] = 0;
X return intrup?'\033':c;
X}
X
Xctlouts(s)
Xchar *s;
X{
X int cnt = 0;
X
X while(*s)
X cnt += ctlout(*s++);
X cnt += standend();
X
X return cnt;
X}
X
Xctloutc(c)
Xchar c;
X{
X int cnt;
X
X cnt = ctlout(c);
X cnt += standend();
X
X return cnt;
X}
X
Xint somode = 0;
Xint ulmode = 0;
X
Xstandout()
X{
X if(!somode) {
X outs(so);
X somode = 1;
X if(xn) return 1;
X }
X return 0;
X}
X
Xunderline()
X{
X if(!ulmode) {
X outs(us);
X ulmode = 1;
X if(xn) return 1;
X }
X return 0;
X}
X
Xstandend()
X{
X int cnt = 0;
X
X if(somode) {
X outs(se);
X somode = 0;
X if(xn) cnt++;
X }
X if(ulmode) {
X outs(ue);
X ulmode = 0;
X if(xn) cnt++;
X }
X return cnt;
X}
X
Xctlout(c)
Xchar c;
X{
X int cnt = 0;
X if(c&'\200') {
X cnt += underline();
X cnt += ctlout(c&'\177');
X return cnt;
X }
X else if(c<' ' || c=='\177') {
X cnt += standout();
X outc((c+'@')&'\177');
X cnt++;
X return cnt;
X }
X else {
X cnt += standend();
X outc(c);
X cnt++;
X return cnt;
X }
X}
X
Xtodir()
X{
X char cmdbuf[MAXLINE];
X static char lastdir[MAXLINE] = ".";
X char *slash, *rindex();
X
X cmdline();
X printf("goto ");
X if(inps(cmdbuf, lastdir, 0)!='\033' && cmdbuf[0]) {
X strcpy(lastdir, cmdbuf);
X if(!cd(cmdbuf, 0)) {
X if(!fgoto(cmdbuf))
X if(slash=rindex(cmdbuf, '/')) {
X *slash++=0;
X if(cd(cmdbuf, 1)) {
X if(!fgoto(slash)) {
X errno=0;
X xerrno=NOMATCH;
X wperror(slash);
X }
X } else
X wperror(cmdbuf);
X } else
X wperror(cmdbuf);
X }
X }
X else
X killcmd();
X}
X
Xfgoto(file)
Xchar *file;
X{
X int i;
X
X for(i = 0; i<nentries; i++)
X if(match(entries[i]->e_name, file)) {
X curr=i;
X return 1;
X }
X
X return 0;
X}
X
Xmatch(target, sample)
Xchar *target, *sample;
X{
X while(*sample && *target==*sample) {
X target++;
X sample++;
X }
X return !*sample;
X}
X
Xkillcmd()
X{
X if(!intrup) {
X cmdline();
X printf("Command killed");
X if(!display_up)
X nl();
X }
X}
X
Xcd(dir, flag)
Xchar *dir;
Xint flag;
X{
X if(flag) {
X cmdline();
X printf("cd %s\r", dir);
X }
X else
X outc('\r');
X fflush(stdout);
X if(access(dir, 5)==0 && chdir(dir)==0) {
X newdir();
X return 1;
X }
X return 0;
X}
X
Xsyscom(rd)
Xint rd; /* should I redraw? */
X{
X char buf[MAXLINE];
X static char lastcmd[MAXLINE] = "";
X char inps();
X
X cmdline();
X extty();
X putchar(rd?'!':'&');
X if(inps(buf, lastcmd, 0)=='\033') {
X entty();
X killcmd();
X return;
X }
X else
X strcpy(lastcmd, buf);
X system(buf, rd);
X entty();
X}
X
Xisdir(entry)
Xstruct entry *entry;
X{
X return((entry->e_stat.st_mode&S_IFMT)==S_IFDIR);
X}
X
Xsample(name)
Xchar *name;
X{
X int col;
X int c, i;
X FILE *tfp;
X
X if(!(tfp = fopen(name, "r"))) {
X wperror(name);
X return;
X }
X
X i=0;
X do {
X cmdline();
X col = 0;
X for(c=fgetc(tfp); col<72 && !feof(tfp); c=fgetc(tfp))
X col+=ctlout(c);
X standend();
X if(display_up)
X outc('\r');
X else
X outc('\n');
X }
X while(!feof(tfp) && (i=getch())=='?');
X
X fclose(tfp);
X
X if(i && i!=' ' && i!='q' && i!='?')
X ungetch(i);
X}
X
Xmacro(c)
Xchar c;
X{
X if(c==NOMAC)
X return 0;
X else if(!macbuf[c])
X return 0;
X else if(c==c_macro) {
X cmdline();
X printf("Recursive macro.");
X endmac();
X return 0;
X }
X else {
X c_macro = c;
X macptr = macbuf[c];
X return 1;
X }
X}
X
Xgetch()
X{
X char c;
X
X if(ungetptr>ungetbuf)
X return *--ungetptr;
X if(*macptr)
X if(*macptr=='\007') {
X macptr++;
X if(*macptr!='\007')
X return getchar();
X else {
X if((c=getchar()) != '\n')
X macptr--;
X else
X macptr++;
X return (c=='\n')?getch():c;
X }
X }
X else if(*macptr=='\\') {
X if(macptr[1]=='\007')
X macptr++;
X return *macptr++;
X }
X else
X return *macptr++;
X else {
X endmac();
X return getchar();
X }
X}
X
Xendmac() {
X c_macro=NOMAC;
X macptr="";
X}
X
Xungetch(c)
Xchar c;
X{
X if(ungetptr-ungetbuf>SMALLBUF)
X return;
X *ungetptr++=c;
X}
X
Xdefine()
X{
X int c;
X char buf[SMALLBUF];
X
X cmdline();
X
X printf("define ");
X c = getch();
X
X if(intrup)
X return;
X
X ctloutc(c);
X printf(" as [");
X if(inps(buf, macbuf[c], ']')=='\033') {
X killcmd();
X return;
X }
X printf("]");
X
X defent(c, buf);
X}
X
Xdefent(c, buf)
Xchar c;
Xchar *buf;
X{
X if(macbuf[c])
X free(macbuf[c]);
X
X if(!buf[0]) {
X macbuf[c]=0;
X return;
X }
X
X macbuf[c] = (char *)malloc(strlen(buf)+1);
X
X if(!macbuf[c]) {
X cmdline();
X printf("No room");
X return;
X }
X
X strcpy(macbuf[c], buf);
X}
X
Xdefmacs()
X{
X defent(' ', "!more %\n");
X defent('%', "!%\n");
X defent('.', "=.");
X defent('/', "=/");
X defent('~', "=~");
X defent('v', "!vi %\n");
X defent('$', "!vi /tmp/br.env.$$\n");
X}
X
Xdefinitions()
X{
X char *ptr;
X int i;
X
X cmdline();
X for(i=0; i<CHARSET; i++)
X if(macbuf[i]) {
X printf("define ");
X ctloutc(i);
X printf(" as [");
X ctlouts(macbuf[i]);
X printf("]\n");
X }
X display_up=0;
X}
X
Xsavedefs()
X{
X int i;
X char filename[MAXLINE];
X static char lastfile[MAXLINE] = "/usr/tmp/macros";
X FILE *fp;
X
X cmdline();
X outs("Save macros as ");
X
X if(inps(filename, lastfile, '\033')=='\033') {
X killcmd();
X return;
X }
X
X strcpy(lastfile, filename);
X
X if(!(fp = fopen(filename, "w"))) {
X wperror(filename);
X return;
X }
X
X for(i=1; i<CHARSET; i++)
X if(macbuf[i])
X fprintf(fp, "[%c%s]\n", i, macbuf[i]);
X
X fclose(fp);
X}
X
Xdumpenv(envp)
Xchar **envp;
X{
X if(!(efp=fopen(efname, "w"))) {
X fperror(efname);
X exit(-1);
X }
X while(*envp)
X fprintf(efp, "$%s\n", *envp++);
X fflush(efp);
X}
X
//END_OF_FILE
echo "End of archive."
# end of archive.
exit 0
--
_--_|\ Peter da Silva. +1 713 274 5180. <peter at ficc.uu.net>.
/ \
\_.--._/ Xenix Support -- it's not just a job, it's an adventure!
v "Have you hugged your wolf today?" `-_-'
More information about the Alt.sources
mailing list