Newsgroups: comp.sources.unix From: klin@iat.uni-paderborn.de (Peter Klingebiel) Subject: v26i066: utree - screen oriented filesystem utility (V3.03b-um), Part03/08 Sender: unix-sources-moderator@pa.dec.com Approved: vixie@pa.dec.com Submitted-By: klin@iat.uni-paderborn.de (Peter Klingebiel) Posting-Number: Volume 26, Issue 66 Archive-Name: utree/part03 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'src/defs.h' <<'END_OF_FILE' X/* X * DEFS.H X * UTREE global definitions. X * 3.01-um klin, Tue Jun 4 14:16:55 1991 X * klin, Tue Oct 15 14:01:57 1991, Handling of symlinks changed X * klin, Sat Oct 26 15:27:40 1991, Some additions X * 3.02-um klin, Fri Nov 1 10:43:31 1991, Screen layout changed X * klin, Sun Nov 24 19:30:43 1991, Cd to current directory before X * executing some commands X * 3.03-um klin, Sat Jan 11 19:53:57 1992, Generic list glist added X * List definitions to list.h X * Line editor extended X * klin, Sat Feb 15 19:18:06 1992, Display attributes added X * Partinioning of directory and X * file windows on tree screen X * changed X * klin, Sun Feb 23 18:16:24 1992, Key handlings and key bindings X * changed X * X * Copyright (c) 1991/92 by Peter Klingebiel & UNIX Magazin Muenchen. X * For copying and distribution information see the file COPYRIGHT. X */ X#if defined(_MAIN_) && !defined(lint) static char sccsid_defs[] = "@(#) utree 3.03-um (klin) Feb 23 1992 defs.h"; X#endif /* _MAIN_ && !lint */ X X/* X * Global and local include files. X */ X X#include "conf.h" /* Configurable definitions */ X#include "cmds.h" /* System commands definitions */ X X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#ifdef BSD X# include X# include X#else /* SYSV */ X# include X# include X# ifdef NODIRENT X# include X# else /* !NODIRENT */ X# include X# endif /* NODIRENT */ X#endif /* BSD */ X#include X#include X#include X#include X X#ifdef NULL /* Reset the standard NULL definition */ X# undef NULL X#endif /* NULL */ X#define NULL ((char *) 0) /* The string NIL pointer */ X X#ifdef NOWINCHG X# undef SIGWINCH X# undef TIOCGWINSZ X#endif /* NOWINCHG */ X X/* X * Definitions for utree which should not be changed. X */ X X/* Buffer size definitions to avoid too often alloc() and free() */ X#define NBUFSZ 1024 /* Filename buffer size */ X#define NFILES 64 /* Filename vector size (= NBUFSZ/16) */ X#define NBUFINC 512 /* Filename buffer increment */ X#define NFILINC 32 /* Filename vector incr (= NBUFINC/16) */ X X/* Other global definitions */ X#ifndef MAXPATHLEN X# define NAMELEN 256 /* Max length of pathnames */ X#else /* !MAXPATHLEN */ X# define NAMELEN MAXPATHLEN X#endif /* MAXPATHLEN */ X#define FILELEN 256 /* Max input length of filenames */ X#define INPLEN 256 /* Often used input buffer length */ X#define PATLEN 256 /* Search pattern length */ X#define FNAMSZ 16 /* Max filename length on screen */ X#define FWINSZ 20 /* Filename width in window */ X#define USERCMD 10 /* # of user defined commands */ X#define MININD 3 /* Minimal tree indention */ X#define MAXIND 9 /* Maximal tree indention */ X#define MINFIL 1 /* Minimal number of file lines */ X#define MAXFIL 9 /* Maximal number of file lines */ X#define DEFFIL 3 /* Default number of file lines */ X#define VMODE0 0 /* Minimal video mode: no attributes */ X#define VMODE1 1 /* Middle video mode: reverse+underline */ X#define VMODE2 2 /* Maximal video mode: all attributes */ X#define HLEVEL 9999 /* Huge number for tree level */ X#define EXECLEN (2*NAMELEN) /* Command buffer length */ X#define HLMIN 6 /* Minimal size of history list */ X#define HLMAX 99 /* Maximal size of history list */ X#define HLDEF 22 /* Default size of history list */ X X/* Return values for many functions */ X#define RV_OK IN_OK /* Work is done (See keys.h) */ X#define RV_NUL IN_NUL /* No input (See keys.h) */ X#define RV_INT IN_INT /* Break (See keys.h) */ X#define RV_END IN_EOF /* EOF (See keys.h) */ X#define RV_HLP IN_HLP /* Help requested (See keys.h) */ X#define RV_NXT IN_NXT /* Next requested (See keys.h) */ X#define RV_PRV IN_PRV /* Prev requested (See keys.h) */ X#define RV_SIZ IN_SIZ /* Screen size changed (See keys.h) */ X#define RV_DIR -11 /* Change directory */ X#define RV_RET -12 /* Return from file menu */ X#define RV_ERR -13 /* Memory error */ X X/* X * Generic list type for scrolling in lists. X * Is a component in many other list types. X */ typedef struct _glist { X char *string; /* General used string */ X struct _glist *prev; /* Previous element in list */ X struct _glist *next; /* Next element in list */ X} glist; X X#define GNULL ((glist *) 0) /* The glist NIL pointer */ X X/* X * Access to items of glist record is done with macros X * to hide this record and for abbreviation. X */ X X#define GNAME(p) ((p)->string) X#define GPREV(p) ((p)->prev) X#define GNEXT(p) ((p)->next) X X#include "list.h" /* Directory/file list definitions */ X#include "hist.h" /* History list definitons */ X#include "vars.h" /* Variable/command definitions */ X#include "help.h" /* Help page definitions */ X#include "term.h" /* Terminal/screen definitions */ X#include "keys.h" /* Key definitions */ X X/* X * Screen update flags. X */ X X#define SF_TREE 0x0001 /* Update tree/file window */ X#define SF_LIST 0x0002 /* Update current list entry */ X#define SF_LAST 0x0004 /* Update last list entry */ X#define SF_SEPL 0x0008 /* Update separator line */ X#define SF_HELP 0x0010 /* Update help line */ X#define SF_ECHO 0x0020 /* Update echo line */ X#define SF_MOVE 0x0040 /* Update cursor position */ X#define SF_FILE 0x0080 /* Update file window on tree screen */ X#define SF_PBAR 0x0100 /* Update position bar */ X#define SF_FULL 0xffff /* Full update */ X X/* X * Display attribute flags. X */ X#define DA_NONE 0 /* No attributes */ X#define DA_NORMAL 0 /* Reset to normal state */ X#define DA_REVERSE 1 /* Reverse */ X#define DA_BOLD 2 /* Highlight */ X#define DA_HALF 3 /* Hide */ X#define DA_ERROR 4 /* Error */ X#define DA_MARK 5 /* Special mark in menu line */ X#define DA_BOLDREV 6 /* Reverse highlight */ X#define DA_HALFREV 7 /* Reverse hide */ X#define DA_BLINKREV 8 /* Reverse blink */ X X/* X * Some other useful definitions and macros. X */ X X#define GLOBL X#define LOCAL static X#define EXTRN extern X#ifdef lint /* Don't disturb lint ! */ X# define VOID int X#else /* !lint */ X# define VOID void X#endif /* lint */ X X#define EQU(s1, s2) (strcmp(s1, s2) == 0) X#define CMP(s1, s2) (strcmp(s1, s2)) X X/* Get type of file pointed to by struct stat s */ X#define STFMT(s) ((s)->st_mode & S_IFMT) X X/* Check if file f is a directory */ X#define ISDIR(f, s) ((*statfun)(f, &s) == 0 && STFMT(&s) == S_IFDIR) X X/* Check if file f is a block special file */ X#define ISBLK(f, s) ((*statfun)(f, &s) == 0 && STFMT(&s) == S_IFBLK) X X/* Line is not empty and not a comment */ X#define VALID(c) ( !(c=='\0' || c=='\n' || c=='#' || c==' ' || c=='\t')) X X/* Can we change to directory p? */ X#define CANCD(p) (access(p, 01) == 0) X X/* Can we scroll a window and are we allowed to do this? */ X#define CANSCROLL (scrollcap && VARSET(V_TS)) X X/* X * External system variables. X */ X XEXTRN int errno; /* System error code number */ X X/* X * Global variables declared in main.c. X */ X X#ifndef _MAIN_ XEXTRN char *prgname, *home; XEXTRN int helpline, echoline; XEXTRN int firstdline, lastdline, ndlines; XEXTRN int firstfline, lastfline, nflines, maxnflines; XEXTRN int firstline, lastline; XEXTRN int indent, maxindent; XEXTRN int videomode, videoattr, graphattr; XEXTRN int maxlevel; XEXTRN int filecount, dircount; XEXTRN int treeflag, fileflag; XEXTRN int buildflag, writeflag; XEXTRN int sortbytime; XEXTRN int hiddendirs; XEXTRN int sizechange; XEXTRN dlist *droot, *cdlist, *cwlist; XEXTRN int fperpage, fperline; XEXTRN char rootdir[]; XEXTRN char fpattern[], gpattern[], tpattern[]; XEXTRN char utreemenu[], ufilemenu[]; XEXTRN int (*statfun)(); X# ifdef BSD XEXTRN jmp_buf winchjump; XEXTRN int atread; X# endif /* BSD */ XEXTRN char *who, *hitkey; X#endif /* !_MAIN_ */ X X/* X * Declaration of library and internal utree functions. X */ X X#ifdef S_IFLNK XEXTRN int stat(), lstat(); X#else /* ! S_IFLNK */ X# define lstat stat XEXTRN int stat(); X#endif /* S_IFLNK */ X X#ifdef BSD X# define getcwd(p, n) getwd(p) X# define strchr(s, c) index(s, c) X# define strrchr(s, c) rindex(s, c) X# define memset(s, c, n) bzero(s, n) XEXTRN char *index(), *rindex(); XEXTRN DIR *opendir(); XEXTRN struct direct *readdir(); X#else /* SYSV */ X# ifdef NODIRENT X# define DIR FILE X# define opendir(n) fopen(n, "r") X# define closedir(p) fclose(p) X# define rewinddir(p) rewind(p) X# else /* !NODIRENT */ XEXTRN DIR *opendir(); XEXTRN struct dirent *readdir(); X# endif /* NODIRENT */ XEXTRN char *strchr(), *strrchr(); X#endif /* BSD */ XEXTRN char *strcpy(), *getenv(), *fgets(), *ctime(); XEXTRN time_t time(); X XEXTRN dlist *newdlist(); XEXTRN char *ualloc(), *basename(), *pathname(), *fileaccess(), *strsav(); X END_OF_FILE if test 11179 -ne `wc -c <'src/defs.h'`; then echo shar: \"'src/defs.h'\" unpacked with wrong size! fi # end of 'src/defs.h' fi if test -f 'src/echo.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/echo.c'\" else echo shar: Extracting \"'src/echo.c'\" \(10086 characters\) sed "s/^X//" >'src/echo.c' <<'END_OF_FILE' X/* X * ECHO.C X * UTREE input and output routines. X * 3.01-um klin, Wed May 1 15:37:35 1991 X * klin, Sat Oct 26 15:30:11 1991, putfile() changed X * 3.02-um klin, Fri Nov 1 13:40:54 1991, putfile() changed X * klin, Sun Nov 24 15:30:35 1991, Video attributes changed X * 3.03-um klin, Tue Feb 11 19:39:09 1992, Generic list glist added X * getline() and putfxy() changed X * printf() no more needed X * klin, Sun Feb 23 17:14:20 1992, Key handling and key bindings X * changed X * X * Copyright (c) 1991/92 by Peter Klingebiel & UNIX Magazin Muenchen. X * For copying and distribution information see the file COPYRIGHT. X */ X#ifndef lint static char sccsid[] = "@(#) utree 3.03-um (klin) Feb 23 1992 echo.c"; X#endif /* !lint */ X X#include "defs.h" X X/* ---- Local variables and definitions ------------------------------- */ X X#ifdef BUFSIZ X# define FBUFLEN BUFSIZ /* Format buffer length */ X#else /* !BUFSIZ */ X# define FBUFLEN 512 X#endif /* BUFSIZ */ X LOCAL char helpbuf[FBUFLEN]; /* Help line buffer */ LOCAL char echobuf[FBUFLEN]; /* Echo line buffer */ X X/* ---- Functions and procedures -------------------------------------- */ X X/* Switch graphical character on/off */ GLOBL int setgraphic(f) X register int f; X{ X if(graphcap && VARSET(V_GC)) { X graphattr = f; X return(1); X } X return(0); X X} /* setgraphic() */ X X/* Set video attributes from display attribute f */ GLOBL VOID setvideo(f) X register int f; X{ X if(videomode > 0) { X switch(f) { X case DA_NORMAL: /* Reset attributes */ X videoattr = VA_NORMAL; X break; X case DA_REVERSE: /* Invert */ X videoattr = VA_REVERSE; X break; X case DA_BOLD: /* Highlight */ X if(videomode > 1) X videoattr = VA_BOLD; X break; X case DA_HALF: /* Hide */ X if(videomode > 1) X videoattr = VA_HALF; X break; X case DA_ERROR: /* Error */ X if(videomode > 1) X videoattr = VA_BOLD|VA_BLINK; X break; X case DA_MARK: /* Menu mark */ X videoattr = videomode > 1 ? VA_BOLD|VA_REVERSE : VA_UNDERLINE|VA_REVERSE; X break; X case DA_BOLDREV: /* Reverse hightlight */ X videoattr = videomode > 1 ? VA_BOLD|VA_REVERSE : VA_REVERSE; X break; X case DA_HALFREV: /* Reverse hide */ X videoattr = videomode > 1 ? VA_HALF|VA_REVERSE : VA_REVERSE; X break; X case DA_BLINKREV: /* Reverse blink */ X videoattr = videomode > 1 ? VA_BLINK|VA_REVERSE : VA_REVERSE; X break; X default: X break; X } X } X else X videoattr = VA_NORMAL; X X} /* setvideo() */ X X/* Write character c to column x at line y */ GLOBL VOID putcxy(x, y, c) X register int x, y, c; X{ X if(cursorxy(x, y)) X (void) putchar(c); X X} /* putcxy() */ X X/* Write string s to column x at line y. Return new column position */ GLOBL int putsxy(x, y, s) X int x, y; X register char *s; X{ X (void) cursorxy(x, y); X while(*s && *s != '\n' && putchar(*s)) X ++s; X cursorpos(&x, &y); X return(x); X X} /* putsxy() */ X X/* Write formatted to column x at line y */ X#if !defined(BSD) || defined(HASVSPRINTF) X/*VARARGS3*/ GLOBL int putfxy(x, y, c, va_alist) X register int x, y, c; X va_dcl X{ X va_list ap; X char buf[FBUFLEN]; X register char *fmt; X register int n; X X va_start(ap); X fmt = va_arg(ap, char *); X (void) vsprintf(buf, fmt, ap); X va_end(ap); X#else /* BSD && !HASVSPRINTF */ X/*VARARGS4*/ GLOBL int putfxy(x, y, c, fmt, p1, p2, p3, p4, p5, p6) X int x, y, c; X char *fmt, *p1, *p2, *p3, *p4, *p5, *p6; X{ X char buf[FBUFLEN]; X register int n; X X (void) sprintf(buf, fmt, p1, p2, p3, p4, p5, p6); X#endif /* !BSD || HASVSPRINTF */ X n = putsxy(x, y, buf); X if(n < columns && c) X clearline(); X return(n); X X} /* putfxy() */ X X/* Write formatted to echoline, return new column position */ X#if !defined(BSD) || defined(HASVSPRINTF) X/*VARARGS0*/ GLOBL int putecho(va_alist) X va_dcl X{ X va_list ap; X register char *fmt; X register int n; X X va_start(ap); X fmt = va_arg(ap, char *); X (void) vsprintf(echobuf, fmt, ap); X va_end(ap); X#else /* BSD && !HASVSPRINTF */ X/*VARARGS1*/ GLOBL int putecho(fmt, p1, p2, p3, p4, p5, p6) X char *fmt, *p1, *p2, *p3, *p4, *p5, *p6; X{ X register int n; X X (void) sprintf(echobuf, fmt, p1, p2, p3, p4, p5, p6); X#endif /* !BSD || HASVSPRINTF */ X if((n = putsxy(0, echoline, echobuf)) < columns) { X (void) putchar(' '); X ++n; X clearline(); X } X treeflag |= SF_ECHO; X fileflag |= SF_ECHO; X return(n); X X} /* putecho() */ X X/* Write formatted to helpline */ X#if !defined(BSD) || defined(HASVSPRINTF) X/*VARARGS0*/ GLOBL VOID puthelp(va_alist) X va_dcl X{ X va_list ap; X register char *fmt; X X va_start(ap); X fmt = va_arg(ap, char *); X (void) vsprintf(helpbuf, fmt, ap); X va_end(ap); X#else /* BSD && !HASVSPRINTF */ X/*VARARGS1*/ GLOBL VOID puthelp(fmt, p1, p2, p3, p4, p5, p6) X char *fmt, *p1, *p2, *p3, *p4, *p5, *p6; X{ X (void) sprintf(helpbuf, fmt, p1, p2, p3, p4, p5, p6); X#endif /* !BSD || HASVSPRINTF */ X setvideo(DA_REVERSE); X (void) putsxy(0, helpline, helpbuf); X while(putchar(' ')) X ; X setvideo(DA_NORMAL); X treeflag |= SF_HELP; X fileflag |= SF_HELP; X X} /* puthelp() */ X X/* Write menu title t and commands line s to help line */ GLOBL VOID putmenu(t, s) X register char *t, *s; X{ X (void) cursorxy(0, helpline); X setvideo(DA_REVERSE); X while(*t && putchar(*t)) /* Title */ X ++t; X while(*s && putchar(*s)) { /* Menu line */ X if(*s == ' ' && *(s+1) && *(s+1) != ' ') { X setvideo(DA_MARK); X (void) putchar(*++s); X setvideo(DA_REVERSE); X } X ++s; X } X while(putchar(' ')) X ; X setvideo(DA_NORMAL); X treeflag |= SF_HELP; X fileflag |= SF_HELP; X X} /* putmenu() */ X X/* Write filename and mode or tag flag */ GLOBL VOID putfile(dp, f, fs) X register dlist *dp; X register int f, fs; X{ X register char *s; X register int i; X X /* File on file screen? */ X if(fs && FFROW(dp, f) >= firstline && FFROW(dp, f) <= lastline) X (void) cursorxy(FFCOL(dp, f), FFROW(dp, f)); X /* Or file window on tree screen? */ X else if( !fs && FTROW(f) >= firstfline && FTROW(f) <= lastfline) X (void) cursorxy(FTCOL(f), FTROW(f)); X /* Out of bounds */ X else X return; X X if(DNFIL(dp) > 0 && DFVEC(dp)) { X if(ISTAG(dp, f) && setgraphic(GC_ON)) { X (void) putchar(GC_TG); X (void) setgraphic(GC_OFF); X } X else X (void) putchar(FITAG(dp, f)); X /* Mark tagged or current file */ X if(fs) { X if(fs == FF_MARK) X setvideo(DA_BLINKREV); X else if(f == DFCUR(dp)) X setvideo(DA_BOLDREV); X } X /* Write file mode and filename */ X (void) putchar(FMODE(dp, f)); X for(s = FFNAM(dp, f), i = 0; i < FNAMSZ && s[i]; i++) X (void) putchar(s[i]); X /* Cut off too long filenames */ X if(s[i]) X (void) putchar(s[i+1] ? '>' : s[i]); X else X while(i++ <= FNAMSZ && putchar(' ')) X ; X if(fs) X setvideo(DA_NORMAL); X } X X} /* putfile() */ X X/* Write message s to line l with videoattr v and get a key */ X/*VARARGS1*/ GLOBL int hitakey(s, l, v) X register char *s; X register int l, v; X{ X register int c; X X if(s) { X if(v) X setvideo(v); X if(l == echoline) { X (void) putfxy(0, l, 1, "%s ", s); X treeflag |= SF_ECHO; X fileflag |= SF_ECHO; X } X else X (void) putfxy(0, l, 1, " %s ", s); X if(v) X setvideo(DA_NORMAL); X } X cursorset(CF_VISIBLE); X c = getkey(); X cursorset(CF_INVISIBLE); X flushout(); X switch(c) { X case K_BRK: /* Interrupt */ X case K_CANC: X return(RV_INT); X case K_SIZE: /* Screen size changed */ X return(RV_SIZ); X case K_EOF: /* EOF */ X return(RV_END); X case K_SEL: /* CR or NL */ X return(K_SEL); X default: /* Return lower character */ X return(isupper(c) ? tolower(c) : c); X } X X} /* hitakey() */ X X/* Write error message to echo line and get a key */ GLOBL int errequest(fn, s) X register char *fn, *s; X{ X bell(1); X setvideo(DA_ERROR); X (void) putecho("!! %s: %s", fn, s); X setvideo(DA_NORMAL); X return(hitakey(NULL)); X X} /* errequest() */ X X/* Read and edit a line */ GLOBL int getline(buf, max, cur, hk, pre, rp, f) X char *buf, *pre; X register int max, cur, hk, f; X glist *rp; X{ X char help[FBUFLEN], echo[FBUFLEN]; X int xmin, xpos; X register int c; X X (void) strcpy(help, helpbuf); /* Save current help and echo lines */ X (void) strcpy(echo, echobuf); X xmin = xpos = 0; /* Setup input buffer variables */ X if(pre) X (void) strcpy(buf, pre); X else X buf[0] = '\0'; X while(1) { /* Edit line loop */ X cursorset(CF_VISIBLE); X c = editline(buf, max, cur, &xmin, &xpos); X cursorset(CF_INVISIBLE); X flushout(); X switch(c) { X case RV_HLP: /* Help requested */ X if((c = showhelp(hk)) == RV_END) X return(c); X puthelp("%s", help); X (void) putecho("%s", echo); X break; X case RV_PRV: /* Previous in list */ X if(rp) { X if(f) X f = 0; X else if(GPREV(rp)) X rp = GPREV(rp); X else { X while(GNEXT(rp)) X rp = GNEXT(rp); X bell(1); X } X (void) strcpy(buf, GNAME(rp)); X } X else X bell(1); X break; X case RV_NXT: /* Next in list */ X if(rp) { X if(f) X f = 0; X else if(GNEXT(rp)) X rp = GNEXT(rp); X else { X while(GPREV(rp)) X rp = GPREV(rp); X bell(1); X } X (void) strcpy(buf, GNAME(rp)); X } X else X bell(1); X break; X default: /* Others: return */ X return(c); X } X } X /*NEVER REACHED*/ X X} /* getline() */ X END_OF_FILE if test 10086 -ne `wc -c <'src/echo.c'`; then echo shar: \"'src/echo.c'\" unpacked with wrong size! fi # end of 'src/echo.c' fi if test -f 'src/edit.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/edit.c'\" else echo shar: Extracting \"'src/edit.c'\" \(8769 characters\) sed "s/^X//" >'src/edit.c' <<'END_OF_FILE' X/* X * EDIT.C X * UTREE simple line editor. X * 3.01-um klin, Wed May 1 16:13:20 1991 X * 3.02-um klin, Sun Nov 24 15:28:27 1991, Video attributes changed X * 3.03-um klin, Tue Feb 11 19:39:09 1992, Line editor changed X * klin, Sun Feb 23 17:15:13 1992, Key handling and key bindings X * changed X * b klin, Thu Mar 19 10:34:41 1992, Bug in editline() fixed X * X * Copyright (c) 1991/92 by Peter Klingebiel & UNIX Magazin Muenchen. X * For copying and distribution information see the file COPYRIGHT. X */ X#ifndef lint static char sccsid[] = "@(#) utree 3.03b-um (klin) Mar 19 1992 edit.c"; X#endif /* !lint */ X X#include "defs.h" X X/* ---- Local variables and definitions ------------------------------- */ X LOCAL char *line; /* Line buffer */ LOCAL int pos, len, xpos; /* Lines position and length */ LOCAL int size, xmin, xmax, xdiff; /* Window variables */ LOCAL int omode = 1; /* Insert/overwrite mode flag */ X X/* ---- Local/global functions and procedures ------------------------- */ X X/* X * INTERNAL USED ROUTINES X */ X X/* Update/show line */ LOCAL VOID putline(from, to, clear) X register int from, to, clear; X{ X register int i; X X for(i = from; line[i] && i < to && i <= xmax; i++) X (void) putchar(line[i]); X if(clear && i < xmax) X clearline(); X (void) cursorxy(xpos + pos - xmin, echoline); X X} /* putline() */ X X/* Scroll forward line */ LOCAL VOID scrollforw(to) X register int to; X{ X xmin += xdiff; X xmax += xdiff; X if(to) { X (void) cursorxy(xpos, echoline); X putline(xmin, to, 1); X } X X} /* scrollforw() */ X X/* Scroll backward line */ LOCAL VOID scrollback(to) X register int to; X{ X xmin -= xdiff; X xmax -= xdiff; X if(to) { X (void) cursorxy(xpos, echoline); X putline(xmin, to, 0); X } X X} /* scrollback() */ X X/* Move cursor one character forward */ LOCAL VOID charforw() X{ X if(xmax < len && pos == xmax) X scrollforw(len); X (void) putchar(line[pos++]); X X} /* charforw() */ X X/* Move cursor one character backward */ LOCAL VOID charback() X{ X if(xmin > 0 && pos == xmin) X scrollback(len); X --pos; X backspace(); X X} /* charback() */ X X/* Show insert/overwrite mode setting at end of helpline */ LOCAL VOID showmode() X{ X setvideo(DA_REVERSE); X (void) putsxy(-11, helpline, omode ? "[OVERWRITE]" : " [INSERT]"); X setvideo(DA_NORMAL); X (void) cursorxy(xpos + pos - xmin, echoline); X X} /* showmode() */ X X/* X * LINE EDITOR X*/ X X/* Read and edit a line */ GLOBL int editline(buf, max, cur, xm, xp) X char *buf; X register int max, cur; X register int *xm, *xp; X{ X register int rv, maxc, mark, c, oc, i, j; X X /* Adjust to at least 32 columns window size */ X if((columns - cur) < 32) { X xpos = columns - 32; X (void) cursorxy(xpos-2, echoline); X clearline(); X (void) putchar(':'); X (void) putchar(' '); X flushout(); X } X else X xpos = cur; X X /* Calculate window sizes for scrolling */ X maxc = columns - xpos; X size = max < maxc ? max : maxc; X --max; X --size; X X /* Calculate scrolling sizes */ X xdiff = size / 4; X xmin = *xm; X xmax = xmin + size; X X /* Setup input buffer variables */ X line = buf; X pos = *xp; X len = strlen(buf); X mark = 0; X rv = IN_OK + 99; X X /* Set up mode string */ X showmode(); X X /* Display input buffer if not empty */ X if(len > 0) { X (void) cursorxy(xpos, echoline); X putline(xmin, xmax, 1); X } X X /* Line editor loop */ X do { X switch(c = getkey()){ X case K_EOF: /* EOF */ X line[0] = '\0'; X rv = IN_EOF; X break; X case K_BRK: /* Interrupt */ X line[0] = '\0'; X rv = IN_INT; X break; X case K_SIZE: /* Screen size changed */ X line[0] = '\0'; X rv = IN_SIZ; X break; X case K_HELP: /* Help */ X line[len] = '\0'; X rv = IN_HLP; X break; X case K_PREV: /* Previous */ X line[len] = '\0'; X rv = IN_PRV; X break; X case K_NEXT: /* Next */ X line[len] = '\0'; X rv = IN_NXT; X break; X case K_SEL: /* End edit and accept line */ X while(len > 0 && line[len-1] <= ' ') X line[--len] = '\0'; X if(line[0] == ' ') { X for(i = 0; line[i] && line[i] == ' '; i++) X --len; X for(j = 0; j <= len; j++, i++) X line[j] = line[i]; X } X rv = len > 0 ? IN_OK : IN_NUL; X break; X case K_INS: /* Switch insert/overwrite mode */ X omode = !omode; X showmode(); X break; X case K_CANC: /* Cancel line */ X len = pos = 0; X line[len] = '\0'; X xmin = 0; X xmax = size; X mark = 0; X case K_REFR: /* Refresh line */ X (void) cursorxy(xpos, echoline); X putline(xmin, xmax, 1); X break; X case K_KILL: /* Kill rest of line */ X line[len = pos] = '\0'; X clearline(); X mark = 0; X break; X case K_MARK: /* Set mark */ X mark = pos; X break; X case K_GOTO: /* Goto mark */ X i = mark; X mark = pos; X if(pos < i) X while(pos < len && pos < i) X charforw(); X else if(pos > i) X while(pos > 0 && pos > i) X charback(); X break; X case K_TAG: /* Transpose characters */ X if(pos > 0 && pos < len) { X oc = buf[pos]; X buf[pos] = buf[pos-1]; X buf[pos-1] = oc; X charback(); X charforw(); X charforw(); X } X break; X case K_FORW: /* Cursor forward */ X if(pos < len) X charforw(); X break; X case K_BACK: /* Cursor backward */ X if(pos > 0) X charback(); X break; X case K_HOME: /* Cursor to beginning of line */ X mark = pos; X if(pos > 0) { X pos = 0; X (void) cursorxy(xpos, echoline); X if(xmin > 0) { X xmin = 0; X xmax = size; X putline(pos, len, 1); X } X } X break; X case K_END: /* Cursor to end of line */ X mark = pos; X if(pos < len) { X pos = len; X if(xmax > len) X (void) cursorxy(xpos + pos - xmin, echoline); X else { X do { X xmin += xdiff; X xmax += xdiff; X } while(xmax < len); X (void) cursorxy(xpos, echoline); X putline(xmin, len, 1); X } X } X break; X case K_NPAG: /* Scroll line forward */ X if(xmax < len) { X if((pos - xdiff) < (xmin + xdiff)) X pos += xdiff; X scrollforw(len); X } X else X for(i = 0; pos < len && i < xdiff; i++) X charforw(); X break; X case K_PPAG: /* Scroll line backward */ X if(xmin > 0) { X if((pos + xdiff) > (xmax - xdiff)) X pos -= xdiff; X scrollback(len); X } X else X for(i = 0; pos > 0 && i < xdiff; i++) X charback(); X break; X case K_DEL: /* Delete char left from cursor */ X if(pos <= 0) X break; X --pos; X if(xmin > 0 && pos == xmin) X scrollback(pos); X else X backspace(); X case K_DOWN: /* Delete character under cursor */ X if(pos == len || len == 0) X break; X --len; X for(i = pos; i < len; i++) X line[i] = line[i+1]; X line[len] = '\0'; X if(xmax < len || !deletechar()) X putline(pos, len, 1); X break; X case K_UP: /* Not handled symbols */ X case K_STR: X case K_INV: X bell(1); X break; X default: /* Insert character */ X if( !(len < max && isprint(c))) { X bell(1); X break; X } X if(pos == len || omode) { X if(pos == xmax) X scrollforw(len); X line[pos] = c; X (void) putchar(c); X if(pos == len) X buf[++len] = '\0'; X ++pos; X } X else { X for(i = pos; i <= len; i++) { X oc = line[i]; X line[i] = c; X c = oc; X } X line[++len] = '\0'; X if(pos == xmax) { X scrollforw(len); X (void) putchar(line[pos++]); X } X else if(insertchar()) X (void) putchar(line[pos++]); X else { X (void) putchar(line[pos++]); X putline(pos, len, 1); X } X } X break; X } X } while(rv > IN_OK); X X *xm = xmin; X *xp = pos; X return(rv); X X} /* editline() */ X END_OF_FILE if test 8769 -ne `wc -c <'src/edit.c'`; then echo shar: \"'src/edit.c'\" unpacked with wrong size! fi # end of 'src/edit.c' fi if test -f 'src/hist.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/hist.c'\" else echo shar: Extracting \"'src/hist.c'\" \(11853 characters\) sed "s/^X//" >'src/hist.c' <<'END_OF_FILE' X/* X * HIST.C X * UTREE shell escape, shell execution and command history. X * 3.03-um klin, Tue Feb 11 22:35:55 1992, Derived from comm.c and X * shell command history added X * klin, Sat Feb 15 14:44:52 1992, Video handling changed X * klin, Sun Feb 23 18:45:19 1992, Keybindings and variable X * AUTOSAVE added X * klin, Fri Mar 6 07:24:57 1992, Minor changes X * a klin, Sun Mar 15 19:08:25 1992, Search in history list added X * X * Copyright (c) 1991/92 by Peter Klingebiel & UNIX Magazin Muenchen. X * For copying and distribution information see the file COPYRIGHT. X */ X#ifndef lint static char sccsid[] = "@(#) utree 3.03a-um (klin) Mar 15 1992 hist.c"; X#endif /* !lint */ X X#include "defs.h" X X/* ---- Local variables and definitions ------------------------------- */ X LOCAL jmp_buf intrjump; /* Buffer for longjump */ LOCAL clist *chcurr = CHNULL; /* Current entry in history list */ LOCAL int chsiz = 0; /* Size of history list */ LOCAL int chmax = HLDEF; /* Max size of history list */ LOCAL int chnum = 0; /* Event number */ LOCAL int hlchg = 0; /* History list changed */ X X/* ---- External variables and functions ------------------------------ */ X XEXTRN char *getversion(); X X/* ---- Functions and procedures -------------------------------------- */ X X/* X * INTERNAL USED ROUTINES X */ X X/* Catch signals SIGINT and SIGQUIT */ LOCAL int oninterrupt() X{ X (void) signal(SIGINT, SIG_IGN); X (void) signal(SIGQUIT, SIG_IGN); X longjmp(intrjump, RV_INT); X /*NOTREACHED*/ X X} /* oninterrupt() */ X X/* Insert command cmd into history list */ LOCAL clist *inserthistory(cmd, f) X register char *cmd; X register int f; X{ X register clist *cp, *p; X X /* Check if command is already in history list */ X if(cp = chcurr) { X do { X if(EQU(cmd, CHCMD(cp))) { X ++CHCNT(cp); X if(cp != chcurr) { X p = (clist *) CHPRV(cp); X CHNXT(p) = CHNXT(cp); X p = (clist *) CHNXT(cp); X CHPRV(p) = CHPRV(cp); X p = (clist *) CHNXT(chcurr); X CHPRV(p) = CHNXT(chcurr) = (glist *) cp; X CHPRV(cp) = (glist *) chcurr; X CHNXT(cp) = (glist *) p; X chcurr = cp; X } X return(cp); X } X cp = (clist *) CHNXT(cp); X } while(cp != chcurr); X } X X /* Create root of history list */ X if(chsiz == 0) { X chcurr = (clist *) ualloc(1, sizeof(clist)); X CHCMD(chcurr) = strsav(cmd); X CHLEN(chcurr) = strlen(cmd); X CHPRV(chcurr) = CHNXT(chcurr) = (glist *) chcurr; X CHNUM(chcurr) = ++chnum; X CHCNT(chcurr) = f ? 1 : 0; X ++chsiz; X } X /* Create new entry in history list */ X else if(chsiz < chmax) { X cp = (clist *) ualloc(1, sizeof(clist)); X CHCMD(cp) = strsav(cmd); X CHLEN(cp) = strlen(cmd); X CHNUM(cp) = ++chnum; X CHCNT(cp) = f ? 1 : 0; X CHPRV(cp) = (glist *) chcurr; X CHNXT(cp) = CHNXT(chcurr); X p = (clist *) CHNXT(chcurr); X CHPRV(p) = (glist *) cp; X CHNXT(chcurr) = (glist *) cp; X chcurr = cp; X ++chsiz; X } X /* Overwrite existing entry = the next in the chain */ X else { X chcurr = (clist *) CHNXT(chcurr); X if(CHLEN(chcurr) < strlen(cmd)) { X ufree(CHCMD(chcurr)); X CHCMD(chcurr) = strsav(cmd); X CHLEN(chcurr) = strlen(cmd); X } X else X (void) strcpy(CHCMD(chcurr), cmd); X CHNUM(chcurr) = ++chnum; X CHCNT(chcurr) = f ? 1 : 0; X } X X /* Update changed flag and return */ X if(f) X hlchg = 1; X return(chcurr); X X} /* inserthistory() */ X X/* Display history list */ LOCAL int showhistory() X{ X register clist *cp; X register int l, c, n; X X l = firstline; X c = RV_OK; X clearwindow(firstline, lastline); X cp = chcurr; X do { X n = putfxy(0, l, 0, "%-6d %s", CHNUM(cp), CHCMD(cp)); X (void) putfxy(n > columns/2 ? n : columns/2, l, 0, "#%d", CHCNT(cp)); X cp = (clist *) CHNXT(cp); X if(++l > lastline && cp != chcurr) { X puthelp("COMMAND HISTORY (CR:continue Q:quit ELSE:give command)"); X c = hitakey("More commands ?", echoline, DA_NONE); X if( !(c == ' ' || c == '\n')) X break; X clearwindow(firstline, lastline); X l = firstline; X } X } while(cp != chcurr); X X treeflag = fileflag = SF_FULL; X return(c); X X} /* showhistory() */ X X/* Execute a shell command */ LOCAL int callcommand(w) X register int w; X{ X char buf[EXECLEN]; X register clist *cp; X register int c, rv, f; X X who = "SHELL"; X if(chcurr) X puthelp("%s: Give command line or select from history (CR:quit)", who); X else X puthelp("%s: Give command line (CR:quit)", who); X /* Get command loop. Handle command given by history number */ X f = 1; X buf[0] = '\0'; X while(1) { X c = putecho("Command:"); X c = getline(buf, sizeof(buf), c, 'l', buf, chcurr ? CHLST(chcurr) : GNULL, f); X if(c == RV_OK && buf[0] == '!') { X if(cp = chcurr) { X if(buf[1] == '!' && chcurr) { /* Recall last command */ X (void) strcpy(buf, CHCMD(chcurr)); X continue; X } X else if(buf[1] >= '1' && buf[1] <= '9') { /* Search for number */ X c = atoi(&buf[1]); X do { X if(CHNUM(cp) == c) { /* Found */ X (void) strcpy(buf, CHCMD(cp)); X chcurr = cp; X f = 0; X break; X } X cp = (clist *) CHNXT(cp); X } while(cp != chcurr); X continue; X } X else { /* Search for string */ X (void) strcat(buf, "*"); X do { X if(match(CHCMD(cp), &buf[1])) { /* Found */ X (void) strcpy(buf, CHCMD(cp)); X chcurr = cp; X f = 0; X break; X } X cp = (clist *) CHNXT(cp); X } while(cp != chcurr); X continue; X } X } X continue; X } X else X break; X } X X /* Command given: insert into history list and execute */ X if(c == RV_OK) { X cp = inserthistory(buf, 1); X if(strchr(buf, '%')) { X c = userformat(buf, CHCMD(cp), w, "SHELL"); X if(c == RV_NUL) { X puthelp("%s %s", who, hitkey); X return(errequest("SHELL", "Bad format")); X } X else if(c != RV_OK) X return(c); X } X puthelp("%s: %s", who, buf); X rv = callsystem(buf, 1, 0); X treeflag = fileflag = SF_FULL; X } X else X return(c); X X if(rv == RV_INT) X return(errequest("Shell escape", "Interrupted")); X return(hitakey("Return from shell (Hit a key)", lines-1, DA_REVERSE)); X X} /* callcommand() */ X X/* Call shell interactively */ LOCAL int callshell() X{ X register int pid, rpid; X int status; X X /* Ignore signals SIGINT and SIGQUIT */ X (void) signal(SIGINT, SIG_IGN); X (void) signal(SIGQUIT, SIG_IGN); X /* Clear screen and reset terminal to cooked mode */ X clearscreen(); X setvideo(DA_REVERSE); X#define LINE \ X"SHELL ESCAPE: Hit \'EOF character\' or \'exit\' to return to utree" X bell(VARSET(V_BL)); X (void) putsxy(0, 0, LINE); X while(putchar(' ')) X ; X#undef LINE X setvideo(DA_NORMAL); X cursorset(CF_VISIBLE); X terminalreset(0); X /* Fork child process */ X#if defined(BSD) || defined(HASVFORK) X if((pid = vfork()) < 0) { X#else /* SYSV && !HASVFORK */ X if((pid = fork()) < 0) { X#endif /* BSD || HASVFORK */ X (void) errequest(prgname, "Cannot fork"); X status = 0; X } X /* Start the shell in child process */ X else if(pid == 0) { X /* Reset signal interrupt and quit */ X (void) signal(SIGINT, SIG_DFL); X (void) signal(SIGQUIT, SIG_DFL); X /* Execute interactive shell */ X (void) execlp(VARVAL(V_SH), VARVAL(V_SH), "-i", NULL); X _exit(1); X } X /* Parent: wait for return from shell */ X else { X while((rpid = wait(&status)) != -1 && rpid != pid) X ; X status >>= 8; X } X /* Reset terminal to raw mode und set screen flags */ X cursorset(CF_INVISIBLE); X terminalraw(0); X treeflag = fileflag = SF_FULL; X X return(status); X X} /* callshell() */ X X/* X * COMMON USED COMMAND EXECUTION X */ X X/* Execute a command, return exit code */ GLOBL int callsystem(cmd, c, s) X register char *cmd; X register int c, s; X{ X register int pid, rpid, rv; X int status; X X if(c) { X /* Reset terminal to cooked mode */ X if(s) X clearscreen(); X else X clearwindow(helpline + 1, lines - 1); X cursorset(CF_VISIBLE); X terminalreset(0); X } X else X /* Turn on signal handling */ X enablesignals(); X flushout(); X /* Fork child process */ X#if defined(BSD) || defined(HASVFORK) X if((pid = vfork()) < 0) { X#else /* SYSV && !HASVFORK */ X if((pid = fork()) < 0) { X#endif /* BSD || HASVFORK */ X (void) errequest(prgname, "Cannot fork"); X status = 0; X } X /* Child process */ X else if(pid == 0) { X /* Reset signals interrupt and quit for child */ X (void) signal(SIGINT, SIG_DFL); X (void) signal(SIGQUIT, SIG_DFL); X if( !c) { X (void) close(0); /* Close stdin */ X (void) close(1); /* stdout */ X (void) close(2); /* and stderr */ X } X /* Let the shell execute the command line */ X (void) execlp(SHELL, SHELL, "-c", cmd, NULL); X _exit(1); X } X /* Parent: wait for termination of child */ X else { X /* Set up here if an interrupt was catched */ X if( !(rv = setjmp(intrjump))) { X /* Catch signals interrupt and quit */ X (void) signal(SIGINT, oninterrupt); X (void) signal(SIGQUIT, oninterrupt); X } X while((rpid = wait(&status)) != -1 && rpid != pid) X ; X if(rv != RV_INT) X rv = status >> 8 ? RV_NUL : RV_OK; X } X if(c) { X /* Set terminal to raw mode and set screen flags */ X terminalraw(0); X treeflag = fileflag = SF_FULL; X } X else X /* Turn off signal handling */ X disablesignals(); X X cursorset(CF_INVISIBLE); X flushout(); X return(rv); X X} /* callsystem() */ X X/* X * COMMAND HISTORY X */ X X/* Set size of history list */ GLOBL int sethistorysize(n) X register int n; X{ X static char buf[4]; X X if(n < HLMIN || n > HLMAX) X return(1); X chmax = n; X (void) sprintf(buf, "%d", n); X VARDEF(V_HS) = VARVAL(V_HS) = buf; X return(0); X X} /* sethistorysize() */ X X/* Init history list */ GLOBL VOID inithistory() X{ X#ifdef UTHIST X char name[NAMELEN], cmd[INPLEN]; X register FILE *fp; X register int l; X X (void) strcpy(name, pathname(UTHIST, home)); X if(fp = fopen(name, "r")) { X while(fgets(cmd, sizeof(cmd), fp)) { X if(VALID(cmd[0])) { X l = strlen(cmd) - 1; X if(cmd[l] == '\n') X cmd[l] = '\0'; X (void) inserthistory(cmd, 0); X } X } X (void) fclose(fp); X } X#endif /* UTHIST */ X X} /* inithistory() */ X X/* Save history list to history file in $HOME */ GLOBL VOID savehistory() X{ X#ifdef UTHIST X char name[NAMELEN]; X register FILE *fp; X register clist *cp; X time_t t; X X if(VARVAL(V_AS) && chcurr && hlchg) { X (void) strcpy(name, pathname(UTHIST, home)); X if(fp = fopen(name, "w")) { X t = time((time_t *) 0); X (void) fprintf(fp, "# %s: ~/%s, %s", getversion(), UTHIST, ctime(&t)); X cp = (clist *) CHNXT(chcurr); X do { X (void) fprintf(fp, "%s\n", CHCMD(cp)); X cp = (clist *) CHNXT(cp); X } while(cp != (clist *) CHNXT(chcurr)); X (void) fclose(fp); X } X } X#endif /* UTHIST */ X X} /* savehistory() */ X X/* Display history list, execute shell or command */ GLOBL int history(c, w) X register int c, w; X{ X if(c == '$') /* Execute interactive shell */ X return(callshell()); X X do { /* Sehll command loop */ X if(chcurr) { /* Display history list */ X if((c = showhistory()) < RV_NUL || c == 'q') X break; X } X c = callcommand(w); /* Execute command */ X } while(c > RV_NUL); X return(c); X X} /* history() */ X X END_OF_FILE if test 11853 -ne `wc -c <'src/hist.c'`; then echo shar: \"'src/hist.c'\" unpacked with wrong size! fi # end of 'src/hist.c' fi if test -f 'src/keys.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/keys.h'\" else echo shar: Extracting \"'src/keys.h'\" \(7692 characters\) sed "s/^X//" >'src/keys.h' <<'END_OF_FILE' X/* X * KEYS.H X * UTREE key definitions. X * 3.01-um klin, Sat Apr 20 11:02:33 1991 X * 3.02-um klin, Sun Nov 10 19:46:21 1991, Function key handling changed X * klin, Sun Nov 24 12:12:13 1991, Extensions for XENIX reported X * by Rolf Gebhardt (RG 11/22/91) X * 3.03-um klin, Sat Feb 11 19:52:04 1992, Line editor extended X * klin, Sun Feb 23 17:34:01 1992, Key handling and key bindings X * a klin, Sun Mar 15 19:08:25 1992, Bug fix in handling 8 bit chars X * X * Copyright (c) 1991/92 by Peter Klingebiel & UNIX Magazin Muenchen. X * For copying and distribution information see the file COPYRIGHT. X */ X#if defined(_MAIN_) && !defined(lint) static char sccsid_keys[] = "@(#) utree 3.03a-um (klin) Mar 15 1992 keys.h"; X#endif /* _MAIN_ && !lint */ X X/* X * Return values from getline() and editline() X */ X X#define IN_OK 1 /* Input not empty and ok */ X#define IN_NUL 0 /* Input empty */ X#define IN_INT -1 /* Interrupt on input */ X#define IN_EOF -2 /* EOF on input */ X#define IN_HLP -3 /* Help key on input */ X#define IN_NXT -4 /* Next key on input */ X#define IN_PRV -5 /* Previous key on input */ X#define IN_SIZ -6 /* Screen size changed */ X X/* X * Key symbols and initial bindings = return values from getkey() X */ X X#define K_SEL 0x000a /* Select/accept line = NEWLINE */ X#define K_FORW 0xff10 /* Forward character/file/directory */ X#define K_BACK 0xff11 /* Backward character/file/directory */ X#define K_NEXT 0xff12 /* Next listentry/file/directory */ X#define K_PREV 0xff13 /* Previous listentry/file/directory */ X#define K_NPAG 0xff14 /* Next page */ X#define K_PPAG 0xff15 /* Previous page */ X#define K_HOME 0xff16 /* Beginning line/files/directories */ X#define K_END 0xff17 /* End line/files/directories */ X#define K_UP 0xff18 /* Scroll up files/directories */ X#define K_DOWN 0xff19 /* Scroll down or delete character */ X#define K_INS 0xff20 /* Change to dir/toggle insert mode */ X#define K_DEL 0xff21 /* Change to parent/delete char back */ X#define K_KILL 0xff22 /* Kill line */ X#define K_MARK 0xff23 /* Set mark on line/file/directory */ X#define K_GOTO 0xff24 /* Goto mark on line/file/directory */ X#define K_TAG 0xff25 /* Goto tagged dir/file or transpose */ X#define K_HELP 0xff26 /* Help */ X#define K_REFR 0xff27 /* Refresh */ X#define K_CANC 0xff28 /* Cancel line */ X#define K_BRK 0xff29 /* Break command/line */ X#define K_EOF 0xff30 /* EOF */ X#define K_STR 0xffe0 /* Insert string */ X#define K_INV 0xffff /* Invalid symbol */ X#define K_SIZE 0xff /* Screen size changed */ X X/* X * All key symbol definitions are hold in an array of record type X * struct _kname to permit dynamic key bindings. X */ X typedef unsigned short ksym; /* Type of key symbol */ typedef unsigned char kchar; /* Type of key strings */ X#define UNULL ((kchar *) 0) /* The kchar NIL pointer */ X typedef struct _kname { X glist list; /* Contains key name and pointers */ X ksym symbol; /* Key symbol (See definitions above) */ X char *comment; /* Meaning of key */ X} kname; X X#ifdef _MAIN_ kname keynames[] = { X { { "SELECT", GNULL, GNULL }, K_SEL, "Select/accept line" }, X { { "FORWARD", GNULL, GNULL }, K_FORW, "Forward character/file/directory" }, X { { "BACKWARD", GNULL, GNULL }, K_BACK, "Backward character/file/directory" }, X { { "NEXT", GNULL, GNULL }, K_NEXT, "Next string/file/directory" }, X { { "PREVIOUS", GNULL, GNULL }, K_PREV, "Previous string/file/directory" }, X { { "NEXTPAGE", GNULL, GNULL }, K_NPAG, "Next page/scroll forward line" }, X { { "PREVPAGE", GNULL, GNULL }, K_PPAG, "Previous page/scroll backward line" }, X { { "BEGIN", GNULL, GNULL }, K_HOME, "Beginning of line/files/directories" }, X { { "END", GNULL, GNULL }, K_END, "End of line/files/directories" }, X { { "UP", GNULL, GNULL }, K_UP, "Scroll up files/directories" }, X { { "DOWN", GNULL, GNULL }, K_DOWN, "Scroll down or delete character" }, X { { "INSERT", GNULL, GNULL }, K_INS, "Change to dir/toggle insert mode" }, X { { "DELETE", GNULL, GNULL }, K_DEL, "Change to parent/delete char backward" }, X { { "KILL", GNULL, GNULL }, K_KILL, "Kill input line", }, X { { "SETMARK", GNULL, GNULL }, K_MARK, "Set mark on line/file/directory" }, X { { "GOTOMARK", GNULL, GNULL }, K_GOTO, "Goto mark on line/file/directory" }, X { { "GOTOTAG", GNULL, GNULL }, K_TAG, "Goto tagged dir/file or transpose" }, X { { "HELP", GNULL, GNULL }, K_HELP, "Help" }, X { { "REFRESH", GNULL, GNULL }, K_REFR, "Refresh screen/input line" }, X { { "CANCEL", GNULL, GNULL }, K_CANC, "Delete input line" }, X { { "BREAK", GNULL, GNULL }, K_BRK, "Break command/line" }, X { { "EXIT", GNULL, GNULL }, K_EOF, "Exit" }, X { { "\"", GNULL, GNULL }, K_STR, "Insert string" }, X { { NULL } } /* End of entries */ X}; X#else /* ! _MAIN_ */ extern kname keynames[]; X#endif /* _MAIN_ */ X X/* X * Access to entries in the keyname list is done with macros X * to hide this record and for abbreviation. X */ X X#define KNLST(n) (&keynames[n].list) X#define KNNAM(n) (keynames[n].list.string) X#define KNPRV(n) (keynames[n].list.prev) X#define KNNXT(n) (keynames[n].list.next) X#define KNSYM(n) (keynames[n].symbol) X#define KNCOM(n) (keynames[n].comment) X X/* X * Key bindings are hold in a dynamically linked list of X * record type klist. The key binding and translation list X * is built up at startup time from default bindings and X * user defined bindings. X */ X typedef struct _klist { X glist list; /* Contains key name and pointers */ X kchar *string; /* Key string */ X ksym symbol; /* Key symbol (See defines above) */ X char *insert; /* String to insert */ X int userdefined; /* User defined binding */ X} klist; X X#define KNULL ((klist *) 0) /* The klist NIL pointer */ X X/* X * Acces to items of klist record is done with macros X * to hide this record and for abbreviation. X */ X X#define KBNAM(p) ((p)->list.string) X#define KBPRV(p) ((p)->list.prev) X#define KBNXT(p) ((p)->list.next) X#define KBSYM(p) ((p)->symbol) X#define KBSTR(p) ((p)->string) X#define KBINS(p) ((p)->insert) X#define KBUSR(p) ((p)->userdefined) X X/* Special macro for key string comparison character per character */ X#define KBCHR(p, n) ((p)->string[n]) X X#ifdef _MAIN_ klist *kroot = KNULL; X#else extern klist *kroot; X#endif /* _MAIN_ */ X END_OF_FILE if test 7692 -ne `wc -c <'src/keys.h'`; then echo shar: \"'src/keys.h'\" unpacked with wrong size! fi # end of 'src/keys.h' fi if test -f 'src/list.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/list.h'\" else echo shar: Extracting \"'src/list.h'\" \(7471 characters\) sed "s/^X//" >'src/list.h' <<'END_OF_FILE' X/* X * LIST.H X * UTREE tree and file list definitions. X * 3.03-um klin, Sat Jan 11 19:53:57 1992, Splitted from defs.h X * X * Copyright (c) 1991/92 by Peter Klingebiel & UNIX Magazin Muenchen. X * For copying and distribution information see the file COPYRIGHT. X */ X#if defined(_MAIN_) && !defined(lint) static char sccsid_list[] = "@(#) utree 3.03-um (klin) Feb 11 1992 list.h"; X#endif /* _MAIN_ && !lint */ X X/* X * Files in a directory are hold in dynamically allocated array X * of a record type flist which is linked into directory type dlist. X */ X typedef struct _flist { X char *filename; /* File name */ X time_t modtime; /* Modification time */ X off_t filesize; /* File size */ X char istagged; /* File is tagged */ X char filemode; /* File modes */ X} flist; X X#define FNULL ((flist *) 0) /* The flist NIL pointer */ X X/* X * Directories are hold in a double linked list of a record type X * dlist which is built up at startup time or later at runtime. X */ X typedef struct _dlist { X glist list; /* Containing pathname and pointers */ X char *filename; /* Directory basename */ X flist *filevec; /* Pointer to flist entries */ X char *zoompattern; /* File zooming pattern */ X char *filebuf; /* Buffer of filenames */ X unsigned bufsize; /* Size of filename buffer */ X int number; /* Directory number */ X int level; /* Subdirectory level */ X unsigned long treeinfo; /* Tree information flag */ X int nfils; /* Number of files */ X int ndirs; /* Number of subdirectories */ X int ntags; /* Number of tagged files */ X int curfile; /* Current file in file list */ X int topfile; /* First file on screen in file list */ X char cancd; /* Can change to this directory */ X char flag; /* Filelist flag */ X char sort; /* Sort criteria flag */ X time_t modtime; /* Modification time of directory */ X time_t chgtime; /* Status change time of directory */ X} dlist; X X#define DNULL ((dlist *) 0) /* The dlist NIL pointer */ X X/* X * Access to items of dlist record is done with macros X * to hide this record and for abbreviation. X */ X X#define DLIST(p) (&(p)->list) X#define DPNAM(p) ((p)->list.string) X#define DPREV(p) ((p)->list.prev) X#define DNEXT(p) ((p)->list.next) X#define DFNAM(p) ((p)->filename) X#define DFVEC(p) ((p)->filevec) X#define DZOOM(p) ((p)->zoompattern) X#define DFBUF(p) ((p)->filebuf) X#define DBSIZ(p) ((p)->bufsize) X#define DDNUM(p) ((p)->number) X#define DLEVL(p) ((p)->level) X#define DINFO(p) ((p)->treeinfo) X#define DNFIL(p) ((p)->nfils) X#define DNDIR(p) ((p)->ndirs) X#define DNTAG(p) ((p)->ntags) X#define DFCUR(p) ((p)->curfile) X#define DFTOP(p) ((p)->topfile) X#define DCANC(p) ((p)->cancd) X#define DFLAG(p) ((p)->flag) X#define DSORT(p) ((p)->sort) X#define DMTIM(p) ((p)->modtime) X#define DCTIM(p) ((p)->chgtime) X X/* X * The same access macros as above for current directory entry. X */ X X#define CLIST (&cdlist->list) X#define CPNAM (cdlist->list.string) X#define CPREV (cdlist->list.prev) X#define CNEXT (cdlist->list.next) X#define CFNAM (cdlist->filename) X#define CFVEC (cdlist->filevec) X#define CZOOM (cdlist->zoompattern) X#define CFBUF (cdlist->filebuf) X#define CBSIZ (cdlist->bufsize) X#define CDNUM (cdlist->number) X#define CLEVL (cdlist->level) X#define CINFO (cdlist->treeinfo) X#define CNFIL (cdlist->nfils) X#define CNDIR (cdlist->ndirs) X#define CNTAG (cdlist->ntags) X#define CFCUR (cdlist->curfile) X#define CFTOP (cdlist->topfile) X#define CCANC (cdlist->cancd) X#define CFLAG (cdlist->flag) X#define CSORT (cdlist->sort) X#define CMTIM (cdlist->modtime) X#define CCTIM (cdlist->chgtime) X X/* Compare modification and change time from dlist p with status s */ X#define CHKTIM(p, s) ((p)->modtimechgtimelevel*indent) X#define DTROW(p) ((p)->number-tdlist->number+firstdline) X X/* X * Access to items of flist record is done with macros X * to hide this record and for abbreviation. X */ X X/* Access macros to flist items pointed to by flist ptr f */ X#define FPFIL(f) (f->filename) X#define FPTIM(f) (f->modtime) X#define FPSIZ(f) (f->filesize) X#define FPTAG(f) (f->istagged) X#define FPMOD(f) (f->filemode) X X/* Access macros to flist items in flist vector v with index n */ X#define FVFIL(v, n) (v[n].filename) X#define FVTIM(v, n) (v[n].modtime) X#define FVSIZ(v, n) (v[n].filesize) X#define FVTAG(v, n) (v[n].istagged) X#define FVMOD(v, n) (v[n].filemode) X X/* Access macros to flist with index n from directory pointed to by p */ X#define FLIST(p, n) (p->filevec[n]) X#define FFNAM(p, n) (p->filevec[n].filename) X#define FMTIM(p, n) (p->filevec[n].modtime) X#define FSIZE(p, n) (p->filevec[n].filesize) X#define FITAG(p, n) (p->filevec[n].istagged) X#define FMODE(p, n) (p->filevec[n].filemode) X X/* Column and row of file n from directory p */ X#define FFCOL(p, n) (((n-p->topfile)%fperline)*FWINSZ) X#define FFROW(p, n) ((n-p->topfile)/fperline+firstline) X X/* Column and row of file n in file window on tree screen */ X#define FTCOL(n) ((n%fperline)*FWINSZ) X#define FTROW(n) (n/fperline+firstfline) X X/* Values for directory list file list flag */ X#define FL_NUL 0x00 /* File list not read in */ X#define FL_CHG 0x01 /* File list changed */ X#define FL_FIL 0x02 /* File list read in */ X X/* Values for file mode and flags */ X#define FF_NONE ' ' /* Ordinary file */ X#define FF_ERR '?' /* Can't stat file */ X#define FF_EXEC '*' /* Executable */ X#define FF_DIR '/' /* Directory */ X#define FF_SLNK '@' /* Symbolic link */ X#define FF_SOCK '=' /* Socket AF_UNIX */ X#define FF_TAG '+' /* File is tagged */ X#define FF_MARK '>' /* Mark on file */ X X#define ISTAG(p, n) (FITAG(p, n) == FF_TAG) X END_OF_FILE if test 7471 -ne `wc -c <'src/list.h'`; then echo shar: \"'src/list.h'\" unpacked with wrong size! fi # end of 'src/list.h' fi if test -f 'src/stat.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/stat.c'\" else echo shar: Extracting \"'src/stat.c'\" \(12422 characters\) sed "s/^X//" >'src/stat.c' <<'END_OF_FILE' X/* X * STAT.C X * UTREE file status functions. X * 3.03-um klin, Tue Feb 11 22:47:06 1992, Splitted from comm.c X * X * Copyright (c) 1991/92 Peter Klingebiel & UNIX Magazin Muenchen. X * For copying and distribution information see the file COPYRIGHT. X */ X#ifndef lint static char sccsid[] = "@(#) utree 3.03-um (klin) Feb 11 1992 stat.c"; X#endif /* !lint */ X X#include "defs.h" X X/* ---- Local variables and definitions ------------------------------- */ X X#ifndef major /* Major number part of a device */ X# define major(x) ((x >> 8) & 0377) X#endif /* !major */ X#ifndef minor /* Minor number part of a device */ X# define minor(x) (x & 0377) X#endif /* !minor */ X X/* ---- External variables and functions ------------------------------ */ X XEXTRN struct passwd *getpwuid(); XEXTRN struct passwd *getpwnam(); XEXTRN struct group *getgrgid(); XEXTRN struct group *getgrnam(); XEXTRN char *readdname(); X X/* ---- Functions and procedures -------------------------------------- */ X X/* X * INTERNAL USED ROUTINES X */ X X/* Return device name for device with device number r from /dev */ LOCAL char *devicename(r) X dev_t r; X{ X static char pn[NAMELEN]; X struct stat st; X register DIR *dp; X register char *fn; X X if(dp = opendir("/dev")) { X (void) strcpy(pn, "/dev/"); X /* Read in all valid entries in /dev */ X while(fn = readdname(dp)) { X (void) strcpy(&pn[5], fn); X if(ISBLK(pn, st) && st.st_rdev == r) { X /* Match: return pathname of device */ X closedir(dp); X return(pn); X } X } X closedir(dp); X } X return(NULL); X X} /* devicename() */ X X/* Get and return type of file from stat data st */ LOCAL char *filetype(st) X register struct stat *st; X{ X register int f; X X f = STFMT(st); X if(f == S_IFDIR) /* Directory */ X return("directory"); X else if(f == S_IFBLK) /* Block special */ X return("block special"); X else if(f == S_IFCHR) /* Character special */ X return("character special"); X else if(f == S_IFREG) /* Regular file */ X return("regular"); X#ifdef S_IFSOCK X else if(f == S_IFSOCK) /* Socket */ X return("socket"); X#endif X#ifdef S_IFIFO X else if(f == S_IFIFO) /* Named pipe */ X return("fifo"); X#endif X#ifdef S_IFLAN X else if(f == S_IFLAN) /* LAN special */ X return("network lan special"); X#endif X#ifdef S_IFLNK X else if(f == S_IFLNK) /* Symbolic link */ X return("symbolic link"); X#endif X return("unkown"); /* Unknown type */ X X} /* filetype() */ X X/* Build string containing current permissions */ LOCAL char *currentperms(m) X int m; X{ X static char ps[4]; X register char *p = ps; X X if(m & 04) X *p++ = 'r'; X if(m & 02) X *p++ = 'w'; X if(m & 01) X *p++ = 'x'; X *p = '\0'; X return(ps); X X} /* currentperms() */ X X/* Parse permission string s */ LOCAL int parseperms(s) X register char *s; X{ X register int p; X X p = 0; X while(*s) { X switch(*s) { X case '0': /* Permission are given octal */ X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X return(*s - '0'); X case 'r': /* Read */ X p |= 004; break; X case 'w': /* Write */ X p |= 002; break; X case 'x': /* Execute/change */ X p |= 001; break; X case '-': /* No permission */ X p = 0; break; X default: X return(-1); X } X ++s; X } X return(p); X X} /* parseperms() */ X X/* Get and display status of file pn. Return status record */ LOCAL struct stat *filestatus(pn) X register char *pn; X{ X static struct stat st; X char *uid = "???"; X char *gid = "???"; X register struct passwd *pw; X register struct group *gr; X register char *dev; X register int isdir, isdev, l; X#ifdef S_IFLNK X char sym[NAMELEN]; X struct stat lst; X int n, issym = 0; X#endif /* S_IFLNK */ X X if(lstat(pn, &st)) /* Get file status information */ X return((struct stat *) 0); X X clearwindow(firstline, lastline); X l = firstline; X isdir = isdev = 0; X X /* Display type of file */ X (void) putfxy(0, ++l, 0, "Path: %s", pn); X (void) putfxy(0, ++l, 0, "Type: %s (octal %06o)", filetype(&st), STFMT(&st)); X switch(STFMT(&st)) { X case S_IFDIR: /* Directory */ X ++isdir; X break; X case S_IFBLK: /* Block special */ X case S_IFCHR: /* Character special */ X#ifdef S_IFLAN X case S_IFLAN: /* LAN special */ X#endif X ++isdev; X break; X#ifdef S_IFLNK X case S_IFLNK: /* Symbolic link */ X ++issym; X break; X#endif X } X X /* Display device number if file is a device */ X if(isdev) X (void) putfxy(0, ++l, 0, "Device major no: %d, minor no %d", X major(st.st_rdev), minor(st.st_rdev)); X X /* Display device the file resides on */ X if( !(dev = devicename(st.st_dev))) X dev = "???"; X (void) putfxy(0, ++l, 0, "Resides on device: %s (major: %d, minor: %d)", X dev, major(st.st_dev), minor(st.st_dev)); X X /* Display inode, # of links and size */ X (void) putfxy(0, ++l, 0, "Inode: %d, Links: %d, Size: %ld bytes", X st.st_ino, st.st_nlink, st.st_size); X#ifdef BSD X /* Display blocksize and allocated blocks */ X (void) putfxy(0, ++l, 0, "Optimal IO blocksize: %ld, Allocated blocks: %ld", X st.st_blksize, st.st_blocks); X#endif /* BSD */ X X /* Display owner and group of file */ X if(pw = getpwuid((int) st.st_uid)) X uid = pw->pw_name; X (void) putfxy(0, ++l, 0, "Owner: %s (uid: %d)", uid, st.st_uid); X if(gr = getgrgid((int) st.st_gid)) X gid = gr->gr_name; X (void) putfxy(0, ++l, 0, "Group: %s (gid: %d)", gid, st.st_gid); X X /* Display file permissions for user, group and others */ X (void) putfxy(0, ++l, 0, "Permissions for user:"); X if(st.st_mode & 0400) X (void) putfxy(24, l, 0, "read "); X if(st.st_mode & 0200) X (void) putfxy(29, l, 0, "write"); X if(st.st_mode & 0100) X (void) putfxy(35, l, 0, isdir ? "search" : "execute"); X (void) putfxy(16, ++l, 0, "group:"); X if(st.st_mode & 0040) X (void) putfxy(24, l, 0, "read "); X if(st.st_mode & 0020) X (void) putfxy(29, l, 0, "write"); X if(st.st_mode & 0010) X (void) putfxy(35, l, 0, isdir ? "search" : "execute"); X (void) putfxy(16, ++l, 0, "all:"); X if(st.st_mode & 004) X (void) putfxy(24, l, 0, "read "); X if(st.st_mode & 0002) X (void) putfxy(29, l, 0, "write"); X if(st.st_mode & 0001) X (void) putfxy(35, l, 0, isdir ? "search" : "execute"); X X /* Display special access rights */ X if(st.st_mode & (S_ISUID|S_ISGID)) X (void) putfxy(16, ++l, 0, "Set user and group ID (%s, %s) on execution", X uid, gid); X else if((st.st_mode & S_ISUID) == S_ISUID) X (void) putfxy(16, ++l, 0, "Set user ID (%s) on execution", uid); X else if((st.st_mode & S_ISGID) == S_ISGID) X (void) putfxy(16, ++l, 0, "Set group ID (%s) on execution", gid); X if((st.st_mode & S_ISVTX) == S_ISVTX) X (void) putfxy(16, ++l, 0, "Save text image after execution"); X (void) putfxy(16, ++l, 0, "Short form: %s (octal: %04o)", X fileaccess(&st), st.st_mode & 07777); X X /* Display file dates */ X (void) putfxy(0, ++l, 0, "Last access: %s", ctime(&st.st_atime)); X (void) putfxy(0, ++l, 0, "Last modification: %s", ctime(&st.st_mtime)); X (void) putfxy(0, ++l, 0, "Last status change: %s", ctime(&st.st_ctime)); X X#ifdef S_IFLNK X /* Read and display symbolic link */ X if(issym && (n = readlink(pn, sym, sizeof(sym))) > 0) { X sym[n] = '\0'; X (void) putfxy(0, ++l, 0, "Symbolic link to: %s", sym); X if((*statfun)(sym, &lst)) X (void) putfxy(0, ++l, 0, "Cannot stat type of file"); X else X (void) putfxy(0, ++l, 0, "Type: %s (octal %06o)", X filetype(&lst), STFMT(&lst)); X } X#endif /* S_IFLNK */ X X return(&st); X X} /* filestatus() */ X X/* X * FILE STATUS ROUTINES X */ X X/* Get and return file access string (like ls -l) */ GLOBL char *fileaccess(st) X register struct stat *st; X{ X static char perm[12]; X X perm[0] = STFMT(st) == S_IFDIR ? 'd' : '-'; X perm[1] = st->st_mode & 0400 ? 'r' : '-'; X perm[2] = st->st_mode & 0200 ? 'w' : '-'; X if(st->st_mode & S_ISUID) X perm[3] = 's'; X else X perm[3] = st->st_mode & 0100 ? 'x' : '-'; X perm[4] = st->st_mode & 0040 ? 'r' : '-'; X perm[5] = st->st_mode & 0020 ? 'w' : '-'; X if(st->st_mode & S_ISGID) X perm[6] = 's'; X else X perm[6] = st->st_mode & 0010 ? 'x' : '-'; X perm[7] = st->st_mode & 0004 ? 'r' : '-'; X perm[8] = st->st_mode & 0002 ? 'w' : '-'; X if(st->st_mode & S_ISVTX) X perm[9] = 't'; X else X perm[9] = st->st_mode & 0001 ? 'x' : '-'; X perm[10] = '\0'; X return(perm); X X} /* fileaccess() */ X X/* Show all file status information for file fn */ X/* Change owner and/or permissions if flag f is set */ GLOBL int statusfile(fn, f) X register char *fn; X register int f; X{ X char pnbuf[NAMELEN], buf[INPLEN]; X register struct passwd *pw; X register struct group *gr; X register struct stat *st; X register char *pn, *ps; X register int mode; X register int c; X X /* Build full pathname if needed */ X if(f) { X (void) strcpy(pnbuf, pathname(fn, CPNAM)); X pn = pnbuf; X } X else X pn = fn; X X who = "STATUS"; X /* File status loop */ X do { X /* Get and display file status information */ X#ifdef BSD X enablesignals(); X#endif X st = filestatus(pn); X#ifdef BSD X disablesignals(); X#endif X if( !st) { X c = errequest(fn, "Cannot stat"); X break; X } X flushout(); X X if(f && STFMT(st) == S_IFDIR) { X /* Changes for directories from tree menu only */ X puthelp("%s (CR:continue Q:quit)", who); X (void) putecho("Status %s: ", fn); X c = hitakey(NULL); X break; X } X puthelp("%s (CR:continue P:permissions O:owner G:group ELSE:quit)", who); X (void) putecho("Change status %s:", fn); X c = hitakey(NULL); X if(c == 'p') { /* Change permissions */ X mode = 0; X puthelp("CHANGE PERMISSIONS: Octal or string from \'rwx-\' (CR:quit))"); X c = putecho("Set permissions for owner to:"); X ps = currentperms((int) (st->st_mode & 0700) >> 6); X if((c = getline(buf, sizeof(buf), c, 0, ps, GNULL, 0)) != RV_OK) X break; X else if((c = parseperms(buf)) < 0) { X c = errequest(buf, "Bad permissions"); X break; X } X mode = c << 6; X c = putecho("Set permissions for group to:"); X ps = currentperms((int) (st->st_mode & 0070) >> 3); X if((c = getline(buf, sizeof(buf), c, 0, ps, GNULL, 0)) != RV_OK) X break; X else if((c = parseperms(buf)) < 0) { X c = errequest(buf, "Bad permissions"); X break; X } X mode |= c << 3; X c = putecho("Set permissions for all to:"); X ps = currentperms((int) (st->st_mode & 0007)); X if((c = getline(buf, sizeof(buf), c, 0, ps, GNULL, 0)) != RV_OK) X break; X else if((c = parseperms(buf)) < 0) { X c = errequest(buf, "Bad permissions"); X break; X } X mode |= c; X if(chmod(pn, mode) < 0) { X c = errequest(fn, "Cannot change permissions"); X break; X } X ++buildflag; X c = 'p'; X } X else if(c == 'o') { /* Change owner */ X puthelp("CHANGE OWNER: Give new owner name (CR:quit)"); X c = putecho("Change owner of %s to:", fn); X if((c = getline(buf, sizeof(buf), c, 0, NULL, GNULL, 0)) != RV_OK) X break; X if( !(pw = getpwnam(buf))) { X c = errequest(buf, "Unknown user"); X break; X } X else if(chown(pn, (int) pw->pw_uid, (int) st->st_gid) < 0) { X c = errequest(fn, "Cannot change owner"); X break; X } X ++buildflag; X c = 'o'; X } X else if(c == 'g') { /* Change group */ X puthelp("CHANGE GROUP: Give new group name (CR:quit)"); X c = putecho("Change group of %s to:", fn); X if((c = getline(buf, sizeof(buf), c, 0, NULL, GNULL, 0)) != RV_OK) X break; X if( !(gr = getgrnam(buf))) { X c = errequest(buf, "Unknown group"); X break; X } X else if(chown(pn, (int) st->st_uid, (int) gr->gr_gid) < 0) { X c = errequest(fn, "Cannot change group"); X break; X } X ++buildflag; X c = 'g'; X } X } while(c == 'p' || c == 'o' || c == 'g'); X X /* Set screen flags and return */ X treeflag = fileflag = SF_FULL; X return(c); X X} /* statusfile() */ X END_OF_FILE if test 12422 -ne `wc -c <'src/stat.c'`; then echo shar: \"'src/stat.c'\" unpacked with wrong size! fi # end of 'src/stat.c' fi if test -f 'src/util.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/util.c'\" else echo shar: Extracting \"'src/util.c'\" \(6251 characters\) sed "s/^X//" >'src/util.c' <<'END_OF_FILE' X/* X * UTIL.C X * UTREE utility functions. X * 3.01-um klin, Sat Apr 20 11:02:33 1991 X * klin, Tue Oct 15 14:02:37 1991, Handling of symlinks changed X * 3.02-um klin, Fri Nov 1 10:46:14 1991, APOLLO stuff added X * 3.03-um klin, Tue Feb 11 22:58:03 1992, statusfile() into stat.c X * getopt() into sup/getopt.c X * klin, Fri Mar 6 10:45:49 1992, strclean() added X * X * Copyright (c) 1991/92 Peter Klingebiel & UNIX Magazin Muenchen. X * For copying and distribution information see the file COPYRIGHT. X */ X#ifndef lint static char sccsid[] = "@(#) utree 3.03-um (klin) Mar 6 1992 util.c"; X#endif /* !lint */ X X#include "defs.h" X X/* ---- Local variables and definitions ------------------------------- */ X X#define TRASH(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '#') X X/* ---- Functions and procedures -------------------------------------- */ X X/* X * COMMON USED UTILITIY FUNCTIONS X * X */ X X/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ X/* ! This function is a modified version of adjustname() `stolen' ! */ X/* ! from the public domain editor MICRO GNU EMACS (mg) version 2a. ! */ X/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ X X/* Return pathname of filename fn and current directory cwd */ GLOBL char *pathname(fn, cwd) X register char *fn, *cwd; X{ X static char pn[NAMELEN]; X register char *cp; X X if(*fn == '/') { X cp = pn; X#ifdef APOLLO /* Stuff for APOLLO node names: //node */ X if(fn[1] == '/') X *cp++ = *fn++; X#endif /* APOLLO */ X while(fn[1] == '/') X ++fn; X#ifdef MUNET /* Stuff for MUNIX/NET: /../node */ X if(fn[1] == '.' && fn[2] == '.') { X *cp++ = *fn++; X *cp++ = *fn++; X } X#endif /* MUNET */ X *cp++ = *fn++; X } X else { X (void) strcpy(pn, cwd); X cp = pn + strlen(pn); X } X if(cp != pn && cp[-1] != '/') X *cp++ = '/'; X while(*fn) { X switch(*fn) { X case '.': X switch(fn[1]) { X case '\0': X *--cp = '\0'; X return(pn); X case '/': X fn += 2; X continue; X case '.': X if(fn[2]=='/' || fn[2] == '\0') { X --cp; X while(cp > pn && *--cp != '/') X ; X ++cp; X if(fn[2]=='\0') { X *--cp = '\0'; X return(pn); X } X fn += 3; X continue; X } X break; X default: X break; X } X break; X case '/': X fn++; X continue; X default: X break; X } X while(*fn && (*cp++ = *fn++) != '/') X ; X } X#ifdef APOLLO X if(cp != &pn[2] && cp[-1] == '/') X#else /* !APOLLO */ X if(cp != &pn[1] && cp[-1] == '/') X#endif /* APOLLO */ X --cp; X *cp = '\0'; X X return(pn); X X} /* pathname() */ X X/* Return basename of filename s */ GLOBL char *basename(s) X register char *s; X{ X register char *sp; X X sp = s + strlen(s); X while(sp >= s) X if(*sp == '/') X return(*(++sp) ? sp : s); X else X --sp; X return(s); X X} /* basename() */ X X/* Save string s */ GLOBL char *strsav(s) X register char *s; X{ X register char *sp; X X if(sp = ualloc((unsigned) strlen(s) + 1, sizeof(char))) X (void) strcpy(sp, s); X return(sp); X X} /* strsav() */ X X/* Convert string from lower to upper case */ GLOBL VOID strupper(s) X register char *s; X{ X while(*s) { X if(islower(*s)) X *s = toupper(*s); X ++s; X } X X} /* strupper() */ X X/* Delete leading and trailing trash characters from s */ GLOBL char *strclean(s) X register char *s; X{ X register char *p; X X while(*s && TRASH(*s)) X ++s; X p = s + strlen(s); X while(p > s && TRASH(*(p-1))) X --p; X *p = '\0'; X return(s); X X} /* strclean() */ X X/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ X/* ! This function is a modified and tuned version of a wild card ! */ X/* ! pattern matcher written by Rich Salz (mirror!rs, Nov 26 1986) ! */ X/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ X X/* Shell like pattern matching for meta characters *, ?, [class] */ X/* Check string s against pattern p and return 1 on match 0 else */ GLOBL int match(s, p) X register char *s, *p; X{ X register int lc, ok, ex; X X for( ; *p; s++, p++) { X switch(*p) { X case '\\': /* Literal match next char */ X ++p; X /*FALLTHRU*/ X default: /* Literal match char */ X if(*s != *p) X return(0); X continue; X case '?': /* Match any char */ X if(*s == '\0') X return(0); X continue; X case '*': /* Match any chars */ X if(*++p == '\0') /* Matches all */ X return(1); X for( ; *s; s++) X if(match(s, p)) X return(1); X return(0); X case '[': /* Class */ X if(ex = (p[1] == '^' || p[1] == '!')) X ++p; X for(lc = 0400, ok = 0; *++p && *p != ']'; lc = *p) X if(*p == '-' ? *s <= *++p && *s >= lc : *s == *p) X ok = 1; X if(ok == ex) X return(0); X continue; X } X } X return(*s == '\0'); X X} /* match() */ X X/* Get and return next valid filename entry from directory file d */ GLOBL char *readdname(dp) X register DIR *dp; X{ X#if defined(BSD) || !defined(NODIRENT) X#ifdef BSD X register struct direct *d; X#else /* SYSV */ X register struct dirent *d; X#endif /* BSD */ X register char *f; X X /* Get next valid directory entry and return filename */ X while(d = readdir(dp)) { X f = d->d_name; X /* Skip "." and ".." */ X if(f[0] == '.' && (f[1] == '\0' || (f[1] == '.' && f[2] == '\0'))) X continue; X return(f); X#else /* SYSV && NODIRENT */ X static char n[DIRSIZ+1]; X struct direct d; X register char *f; X X while(fread(&d, sizeof(struct direct), 1, dp) > 0) { X f = d.d_name; X /* Skip removed files, "." and ".." */ X if(d.d_ino == 0 || (f[0] == '.' && (f[1] == '\0' || (f[1] == '.' && f[2] == '\0')))) X continue; X (void) strncpy(n, d.d_name, DIRSIZ); X n[DIRSIZ] = '\0'; X return(n); X#endif /* BSD || !NODIRENT */ X } X return(NULL); X X} /* readdname() */ X END_OF_FILE if test 6251 -ne `wc -c <'src/util.c'`; then echo shar: \"'src/util.c'\" unpacked with wrong size! fi # end of 'src/util.c' fi if test -f 'src/vars.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/vars.h'\" else echo shar: Extracting \"'src/vars.h'\" \(11380 characters\) sed "s/^X//" >'src/vars.h' <<'END_OF_FILE' X/* X * VARS.H X * UTREE variables definitions. X * 3.01-um klin, Wed May 1 10:29:37 1991 X * 3.03-um klin, Tue Feb 11 14:18:50 1992, Generic lists for variables X * and file type commands X * klin, Sat Feb 15 14:44:52 1992, Video handling and partinioning of X * directory and file windows changed X * klin, Sun Feb 23 18:45:19 1992, Keybindings and variable X * AUTOSAVE added X * X * Copyright (c) 1991/92 by Peter Klingebiel & UNIX Magazin Muenchen. X * For copying and distribution information see the file COPYRIGHT. X */ X#if defined(_MAIN_) && !defined(lint) static char sccsid_vars[] = "@(#) utree 3.03-um (klin) Feb 23 1992 vars.h"; X#endif /* _MAIN_ && !lint */ X X/* X * File type dependent commands are hold in a dynamically linked X * list of struct _xlist. X */ X typedef struct _xlist { X glist list; /* Contains filetype and pointers */ X char *command; /* Command format to execute */ X char *comment; /* Additional comment */ X} xlist; X X#define XNULL ((xlist *) 0) /* The xlist NIL pointer */ X X/* X * Access to entries in the file type command list is done X * with macros to hide this record and for abbreviation. X */ X X#define XLIST(p) (&(p)->list) X#define XTYPE(p) ((p)->list.string) X#define XPREV(p) ((p)->list.prev) X#define XNEXT(p) ((p)->list.next) X#define XCOMD(p) ((p)->command) X#define XCOMM(p) ((p)->comment) X X#ifdef _MAIN_ xlist *xroot = XNULL; /* Root of file type command list */ X#else /* !_MAIN_ */ extern xlist *xroot; X#endif /* _MAIN_ */ X X/* X * Variables are hold in a table of struct _vlist which is X * initialized and linked at startup. All predefined variables X * are accessed via index into this table. X */ X typedef struct _vlist { X glist list; /* Contains variable name and pointers */ X char *shortcut; /* Variable short cut */ X int type; /* Type of variable */ X int number; /* Variable number (see below) */ X char *defval; /* Default value (if defined) */ X char *value; /* Variable value */ X char *comment; /* Additional comment */ X} vlist; X X#define VNULL ((vlist *) 0) /* The vlist NIL pointer */ X X/* X * Access to entries in the variable list is done with macros X * to hide this record and for abbreviation. X */ X X#define VARLST(n) (&vtable[n].list) X#define VARNAM(n) (vtable[n].list.string) X#define VARPRV(n) (vtable[n].list.prev) X#define VARNXT(n) (vtable[n].list.next) X#define VARCUT(n) (vtable[n].shortcut) X#define VARTYP(n) (vtable[n].type) X#define VARNUM(n) (vtable[n].number) X#define VARDEF(n) (vtable[n].defval) X#define VARVAL(n) (vtable[n].value) X#define VARCOM(n) (vtable[n].comment) X X/* Assign vtable entry to vlist pointer. Check if variable is set */ X#define VARTAB(n) (&vtable[n]) X#define VARSET(n) (vtable[n].value) X X/* X * The same macros for access via pointers. X */ X X#define VLIST(p) (&(p)->list) X#define VNAME(p) ((p)->list.string) X#define VPREV(p) ((p)->list.prev) X#define VNEXT(p) ((p)->list.next) X#define VSCUT(p) ((p)->shortcut) X#define VTYPE(p) ((p)->type) X#define VNUMB(p) ((p)->number) X#define VDFLT(p) ((p)->defval) X#define VVALE(p) ((p)->value) X#define VCOMM(p) ((p)->comment) X X/* Flag values for variables/commands settings */ X#define VC_TST 0 /* Test only. Don't set */ X#define VC_SET 1 /* Set but don't effect change flag */ X#define VC_CHG 2 /* Set and affect change flag */ X X/* Types of variables */ X#define VT_B 0 /* Boolean type */ X#define VT_N 1 /* Numerical value */ X#define VT_S 2 /* General string */ X#define VT_U 3 /* User tree or file command string */ X#define VT_O 4 /* Other user defined strings */ X X/* Values for boolean variables */ X#define VB_ON ((char *) 1) X#define VB_OFF ((char *) 0) X X/* Indices in variable table. See variable table below */ X#define V_BL 0 /* Allow bell */ X#define V_CL 1 /* Clock in echo line */ X#define V_GC 2 /* Use graphic character set */ X#define V_TS 3 /* Use terminal scroll funcs */ X#define V_ST 4 /* Scan tree for changes */ X#define V_WD 5 /* Warn about unreadable dirs */ X#define V_LS 6 /* Lexical sort filelists */ X#define V_AS 7 /* Save definition changes */ X#define V_VM 8 /* Video attribute using */ X#define V_TI 9 /* Tree indention */ X#define V_FL 10 /* File lines on tree screen */ X#define V_HS 11 /* Size of history list */ X#define V_SH 12 /* Interaktive shell */ X#define V_ED 13 /* File editor */ X#define V_EDO 14 /* Editor options */ X#define V_PG 15 /* File viewer/pager */ X#define V_PGO 16 /* Viewer options */ X#define V_XD 17 /* File hex dumper */ X#define V_XDO 18 /* Hex dumper options */ X#define V_LP 19 /* File printer */ X#define V_LPO 20 /* Printer options */ X#define V_BK 21 /* Directory backup */ X#define V_BKO 22 /* Backup options */ X#define V_TC0 22 /* Dummy: used for calculation only */ X#define V_TC1 23 /* User defined tree commands */ X#define V_TC2 24 X#define V_TC3 25 X#define V_TC4 26 X#define V_TC5 27 X#define V_TC6 28 X#define V_TC7 29 X#define V_TC8 30 X#define V_TC9 31 X#define V_FC0 31 /* Dummy: used for calculation only */ X#define V_FC1 32 /* User defined file commands */ X#define V_FC2 33 X#define V_FC3 34 X#define V_FC4 35 X#define V_FC5 36 X#define V_FC6 37 X#define V_FC7 38 X#define V_FC8 39 X#define V_FC9 40 X X/* X * Table defining default variable settings (See cmds.h). X */ X X#ifdef _MAIN_ vlist vtable[] = { X { { "BELL", GNULL, GNULL }, "BL", VT_B, V_BL, VB_ON, NULL, "Allow ringing of bell" }, X#ifdef UTCLOCK X { { "CLOCK", GNULL, GNULL }, "CL", VT_B, V_CL, VB_ON, NULL, "Display/update clock" }, X#else /* !UTCLOCK */ X { { "CLOCK", GNULL, GNULL }, "CL", VT_B, V_CL, VB_OFF, NULL, "Display/update clock" }, X#endif /* UTCLOCK */ X { { "GRAPHCHARS", GNULL, GNULL }, "GC", VT_B, V_GC, VB_ON, NULL, "Use graphic charset" }, X { { "TERMSCROLL", GNULL, GNULL }, "TS", VT_B, V_TS, VB_ON, NULL, "Use terminal scrolling" }, X { { "SCANTREE", GNULL, GNULL }, "ST", VT_B, V_ST, VB_ON, NULL, "Scan tree for changes" }, X { { "WARNDIRS", GNULL, GNULL }, "WD", VT_B, V_WD, VB_ON, NULL, "Directory warnings" }, X { { "LEXSORT", GNULL, GNULL }, "LS", VT_B, V_LS, VB_ON, NULL, "Lexical sort of filelists" }, X { { "AUTOSAVE", GNULL, GNULL }, "AS", VT_B, V_AS, VB_ON, NULL, "Save definition/history changes" }, X { { "VIDEOMODE", GNULL, GNULL }, "VM", VT_N, V_VM, "2", NULL, "Video mode setting (0..2)" }, X { { "TREEINDENT", GNULL, GNULL }, "TI", VT_N, V_TI, "9", NULL, "Max tree indention (3..9)" }, X { { "FILELINES", GNULL, GNULL }, "FL", VT_N, V_FL, "3", NULL, "Max file lines (1..9)" }, X { { "HISTSIZE", GNULL, GNULL }, "HS", VT_N, V_HS, "22", NULL, "Size of history list (readonly)" }, X { { "SHELL", GNULL, GNULL }, "SH", VT_S, V_SH, SHELL, NULL, "Shell" }, X { { "EDITOR", GNULL, GNULL }, "ED", VT_S, V_ED, EDITPRG, NULL, "Text editor" }, X { { "EDITOPTS", GNULL, GNULL }, "EO", VT_S, V_EDO, NULL, NULL, "Editor options" }, X { { "PAGER", GNULL, GNULL }, "PG", VT_S, V_PG, PAGEPRG, NULL, "Text pager" }, X { { "PAGEOPTS", GNULL, GNULL }, "PO", VT_S, V_PGO, NULL, NULL, "Pager options" }, X { { "XDUMPER", GNULL, GNULL }, "XD", VT_S, V_XD, DUMPPRG, NULL, "Hex dumper" }, X { { "XDUMPOPTS", GNULL, GNULL }, "XO", VT_S, V_XDO, NULL, NULL, "Dumper options" }, X { { "LPRINTER", GNULL, GNULL }, "LP", VT_S, V_LP, PRINTPRG, NULL, "Printer command" }, X { { "LPRINTOPTS", GNULL, GNULL }, "LO", VT_S, V_LPO, NULL, NULL, "Printer options" }, X#ifdef UTBCKUP X { { "BACKUP", GNULL, GNULL }, "BK", VT_S, V_BK, UTBCKUP, NULL, "Backup program" }, X#else /* !UTBCKUP */ X { { "BACKUP", GNULL, GNULL }, "BK", VT_S, V_BK, NULL, NULL, "Backup program" }, X#endif /* UTBCKUP */ X { { "BACKUPOPTS", GNULL, GNULL }, "BO", VT_S, V_BKO, NULL, NULL, "Backup options" }, X { { "TREECMD1", GNULL, GNULL }, "T1", VT_U, V_TC1, NULL, NULL, NULL }, X { { "TREECMD2", GNULL, GNULL }, "T2", VT_U, V_TC2, NULL, NULL, NULL }, X { { "TREECMD3", GNULL, GNULL }, "T3", VT_U, V_TC3, NULL, NULL, NULL }, X { { "TREECMD4", GNULL, GNULL }, "T4", VT_U, V_TC4, NULL, NULL, NULL }, X { { "TREECMD5", GNULL, GNULL }, "T5", VT_U, V_TC5, NULL, NULL, NULL }, X { { "TREECMD6", GNULL, GNULL }, "T6", VT_U, V_TC6, NULL, NULL, NULL }, X { { "TREECMD7", GNULL, GNULL }, "T7", VT_U, V_TC7, NULL, NULL, NULL }, X { { "TREECMD8", GNULL, GNULL }, "T8", VT_U, V_TC8, NULL, NULL, NULL }, X { { "TREECMD9", GNULL, GNULL }, "T9", VT_U, V_TC9, NULL, NULL, NULL }, X { { "FILECMD1", GNULL, GNULL }, "F1", VT_U, V_FC1, NULL, NULL, NULL }, X { { "FILECMD2", GNULL, GNULL }, "F2", VT_U, V_FC2, NULL, NULL, NULL }, X { { "FILECMD3", GNULL, GNULL }, "F3", VT_U, V_FC3, NULL, NULL, NULL }, X { { "FILECMD4", GNULL, GNULL }, "F4", VT_U, V_FC4, NULL, NULL, NULL }, X { { "FILECMD5", GNULL, GNULL }, "F5", VT_U, V_FC5, NULL, NULL, NULL }, X { { "FILECMD6", GNULL, GNULL }, "F6", VT_U, V_FC6, NULL, NULL, NULL }, X { { "FILECMD7", GNULL, GNULL }, "F7", VT_U, V_FC7, NULL, NULL, NULL }, X { { "FILECMD8", GNULL, GNULL }, "F8", VT_U, V_FC8, NULL, NULL, NULL }, X { { "FILECMD9", GNULL, GNULL }, "F9", VT_U, V_FC9, NULL, NULL, NULL }, X { { NULL } } /* End of predefined variables */ X}; X/* Possible user defined variables may follow, but are not implemented */ X#else extern vlist vtable[]; X#endif /* _MAIN_ */ X END_OF_FILE if test 11380 -ne `wc -c <'src/vars.h'`; then echo shar: \"'src/vars.h'\" unpacked with wrong size! fi # end of 'src/vars.h' fi echo shar: End of archive 3 \(of 8\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 4 5 6 7 8 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 8 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0