home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume25
/
ils
/
ils.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-28
|
26KB
|
882 lines
/**************************************************************************
* ils - interactive "ls" library for ascii terminals.
*
* Subroutine ils expects variable "rows", and "cols" to be set prior to
* calling. rows should contain the verticle size of the window to
* be used, and cols should contain horizontal size (in characters).
*
*
* Author: Jack Alexander
* jack@marley
*
*/
#include "ils.h"
#include <curses.h>
#include <stdio.h>
#include <sys/dir.h>
#include <fcntl.h>
#include <errno.h>
#include "get.h" /* need key definitions from getstring routine */
extern char *pnam; /* program name */
int a_num, a_ind; /* work variables for argument processing */
int syms=0; /* number of symbols in table */
struct symbol *symtab[MAX_SYMBOLS]; /* symbol table */
char *args[ILS_MAX_ARGS]; /* argument list */
int modes; /* hold behavioral data */
char cur_path[MAXPATH]; /* current path */
/* interactive directory browser -- main routine
**
** variable pattern in a two dimensional array containing all of the patterns
** to use for pattern matching. If pattern[0] == NULL, then no
** patterns are used, and all files are shown.
**
** variable path is a string containing the path of the directory from which
** browsing will begin (typically, same as pwd(1)).
**
** ulx, uly, lrx, and lry are the coordinates (in screen coordinates where
** units are characters.
**
** m is an integer which may contain any behavioral charactaristics.
** various bits, as described in ils.h can be ored into this variable to
** change the behavior of ils.
**
** title is a string which is displayed on the top line of the window. If
** title is NULL, then no title is shown, and you get an extra line for
** editing.
**/
ils(pattern,path,ulx,uly,lrx,lry,m,title)
char *pattern[],*path,*title;
int ulx, uly, lrx, lry, m;
{
struct d_entry *top; /* the very top of the known directory tree */
modes = m; /* makes user defined modes global */
top = (struct d_entry *) NULL; /* haven't read any directories yet */
clear();
read_ils_defines(); /* read this user's definitions */
read_directory(pattern,path,&top); /* read in current directory */
edit_directory(pattern,path,&top,ulx,uly,lrx,lry,title); /* do it */
}
/* read_ils_defines() looks and the ".ils" file for the user. This file
contains all user-specific key sequences and correspoding actions for
the key sequences. */
read_ils_defines()
{
char *getenv(), *a, dummy[MAXPATH];
FILE *fopen(), *fp;
int lnum=0;
a=getenv("HOME"); /* get path to user's home directory */
sprintf(dummy,"%s/.ils",a); /* set up path to the .ils file */
if((fp=fopen(dummy,"r"))==NULL)
return; /* no ".ils" file in home directory */
while(fgets(dummy,MAXPATH,fp)!=NULL) {
lnum++; /* line number counter */
if(dummy[0]=='#')
continue; /* a comment line */
parse_line(dummy,lnum); /* enter into symbol table */
}
fclose(fp);
}
#ifdef BSD
/******
* Berkeley UNIX version. read directory reads all files in the current
* directory.
*/
read_directory(pattern,path,dptr)
char *pattern[],path[];
struct d_entry **dptr;
{
DIR *dp, *opendir();
struct direct *dirptr, *readdir();
if(chdir(path)<0)
return; /* can't change to desired directory */
if((dp=opendir("."))==NULL)
return; /* can't open the directory file itself */
while((dirptr=readdir(dp))!=NULL) /* end of directory */
add_entry(pattern,dirptr->d_fileno,dirptr->d_name,dptr);
closedir(dp);
}
#endif BSD
#ifdef SYSTEMV
/* SYSTEM V Unix version of the read_directory routine. */
read_directory(pattern,path,dptr)
char *pattern[],path[];
struct d_entry **dptr;
{
struct direct d;
int fd;
if(chdir(path)<0) /* can't change to the desired directory */
return;
if((fd=open(".",O_RDONLY))<0) /* can't open the directory file */
return;
while(read(fd,&d,sizeof(struct direct)) == sizeof(struct direct))
add_entry(pattern,d.d_ino,d.d_name,dptr); /* add file */
close(fd);
}
#endif SYSTEMV
/* showpath displays the string in "path" on the top line of the window.
The top line is defined in ulx, ily. Only as much of the path as
can be seen is displayed, the rest is cust out. */
showpath(path,ulx, uly, lrx, lry)
char path[];
int ulx, uly, lrx, lry;
{
int l;
char dummy[80];
standout(); /* invert the line */
move(uly,ulx); /* move to top line of the window */
if((l=strlen(path))>(lrx-uly-1)) { /* is string too long? */
/* if string is too long, truncate it. preceed all truncated
paths with "..." to show user that the path was indeed
truncated. */
sprintf(dummy,"...%c%d.%ds",'%',(lrx-ulx-3),(lrx-ulx-3));
printw(dummy,path+(l-(lrx-ulx-3))); /* print path */
}
else /* string is not too long, just print it */
printw(path);
standend(); /* end inverted mode */
clrtoeol(); /* get rid of standend char on some types of terminals */
}
/* display an error message on the top line of the window, wait for RETURN
key to be pressed so that user can acknowledge the error */
ils_error(msg,ulx,uly,lrx,lry)
char msg[];
int ulx, uly, lrx, lry;
{
int l;
char dummy[80];
standout(); /* all errors in inverse mode */
move(uly,ulx); /* go to top line */
sprintf(dummy,">> %s << Press RETURN...",msg);
if((l=strlen(dummy))>(lrx-uly-1)) { /* does message need truncation? */
if(strlen(msg) > (lrx-uly-1)) {
/* truncate the message. Preceed truncated with "..." */
sprintf(dummy,"...%c%d.%ds",'%',(lrx-ulx-3),(lrx-ulx-3));
printw(dummy,msg+(l-(lrx-ulx-3)));
}
else
strcpy(dummy,msg); /* no truncation needed */
}
printw(dummy);
standend(); /* end inverse mode */
refresh();
ils_wait_key(ILS_ENTER); /* wait for RETURN key to be pressed */
}
/* wait for key (passed in variable 'c') to be pressed. Keep asking
for more keys until the one waited for is pressed. */
ils_wait_key(c)
int c;
{
while((getch()&0x7f)!=c);
}
/* edit a directory, using a rectangle in the screen with (ulx, uly) as
the coordinates of the upper-left corner of the rectangle, and
(lrx, lry) as the lower-right corner of the rectangle. title is
a character string that will be printed in the top line of the rectangle,
unless a NULL is passed, in which case nothing is printed, and you
have another line to use as part of the directory. */
edit_directory(pattern,path,dptr,ulx,uly,lrx,lry,title)
char *pattern[],path[];
struct d_entry **dptr;
int ulx, uly, lrx, lry;
char *title;
{
static int level=0;
char newpath[80], trailer, *p, line[MAXPATH], this_dir[MAXPATH],
last_active[MAXPATH];
struct d_entry *cur, *t, *active_list[ILS_MAX_ENTRIES];
int height, width, widest, entries, i, j, horiz_fit, vert_fit,
x, y, more_line, first_visible, orig_uly,
column_height, cur_entry, state, next_state, c,
last_x, last_y, z, up_x, up_y, down_x, down_y,
done, new_entries, low, high, middle;
clear();
raw(); /* need characters AS THEY ARE PRESSED */
noecho(); /* don't show user's input */
orig_uly = uly;
if(title != (char *)NULL) /* is there a title? */
uly++; /* account for title line */
uly++; /* account for "current directory" line */
height = lry - uly; /* height of window */
width = lrx - ulx; /* width of window */
strcpy(cur_path,path); /* make path globally known */
level++; /* count the levels down */
state = ILS_INITIAL;
next_state = ILS_INITIAL2;
cur_entry = 0;
while(1) { /* loop will end with an exit() call */
switch(state) {
case ILS_INITIAL:
cur = *dptr; /* get all entries in directory into a sorted list */
widest = 6; /* default longest string length */
entries = first_visible = 0;
/* loop through and find the longest filename in the list */
while(cur != (struct d_entry *)NULL) {
if((i=strlen(cur->name)) > widest)
widest = i; /* found a longer string */
active_list[entries++] = cur;
cur = cur->next; /* get next in list */
}
/* get number of strings that can fit => how many columns */
horiz_fit = width / (widest+2);
column_height = entries / horiz_fit + ((entries%horiz_fit)==0? 0:1);
vert_fit = lry-uly; /* how many can fit verticall into window */
if(vert_fit > column_height)
vert_fit = column_height; /* safeguard */
state = next_state;
break;
case ILS_INITIAL2:
if(!entries) { /* is this an empty directory? */
showpath(path,ulx,orig_uly+(title==NULL? 0:1),lrx,lry);
ils_error("EMPTY DIRECTORY",ulx,orig_uly,lrx,lry);
level--;
return; /* empty: allow no editing */
}
state = ILS_TOTAL_DRAW; /* redraw screen */
break;
case ILS_FIND_CURSOR: /* locate best place for cursor */
done = 0;
low = 0; /* base value for binary search */
high = entries; /* high value for binary search */
/* binary search to position where the cursor should be */
while(!done) { /* binary search to the place to put cursor */
middle = (low+high)/2;
i = strcmp(last_active,active_list[middle]->name);
if(i==0)
done = 1; /* found entry! */
if(i<0) {
if(middle==high) /* found where to put cursor */
done=1;
else
high = middle; /* try lower half */
}
else {
if(middle==low) /* found where to put cursor */
done=1;
else
low = middle; /* try upper half */
}
}
/* middle is now equal to entry number where cursor should be */
cur_entry = middle;
first_visible = 0; /* for now, top line shown is line 0 */
i = middle % column_height; /* get offset from top of column */
if(i>=vert_fit) /* is the active entry off the screen? */
first_visible = i-vert_fit+1;/* YES make it visible */
if(first_visible<0 || first_visible>=entries || first_visible>=vert_fit)
first_visible = i; /* safeguard */
if(first_visible >= entries) /* another safeguard */
first_visible;
state = ILS_INITIAL2;
break;
case ILS_TOTAL_DRAW: /* redraw the whole window */
clear();
if(title != NULL) { /* is there a title to display? */
move(orig_uly,ulx);
clrtoeol();
printw("%s",title); /* display the title */
}
/* display the path either just below the title, or on top */
showpath(path,ulx,orig_uly+(title==NULL? 0:1),lrx,lry);
case ILS_DRAW: /* show files in directory */
up_x=up_y=down_x=down_y= -1;
for(i=0,z=first_visible;i<horiz_fit;i++) {
for(j=0;j<vert_fit && z<entries;j++,z++) {
y=uly+j;
x=1+ulx+(width/horiz_fit)*i;
move(y,x);
if(!i)
clrtoeol();
if(!i && !j && first_visible) {
standout();
printw("< more",first_visible*horiz_fit+1);
standend();
up_x = x;
up_y = y;
}
else {
trailer=' ';
if(modes & ILS_F_TYPE) {
if(active_list[z]->stat.st_mode & 040000)
trailer='/';
else if(active_list[z]->stat.st_mode & 0100)
trailer='*';
}
printw("%s%c",active_list[z]->name,trailer);
}
}
z+=column_height-vert_fit;
}
if((first_visible+vert_fit) < column_height) {
y=uly+vert_fit-1;
x=1+ulx+(width/horiz_fit)*(horiz_fit-1);
move(y,x);
standout();
printw("more >");
standend();
clrtoeol();
down_x = x;
down_y = y;
}
refresh();
state = ILS_SHOW_CURSOR;
next_state = ILS_KEYBOARD;
break;
case ILS_SHOW_PATH:
showpath(path,ulx,orig_uly+(title==NULL? 0:1),lrx,lry);
case ILS_MOVE_CURSOR:
move(last_y,last_x);
addch(' ');
case ILS_SHOW_CURSOR:
last_y=y=uly + cur_entry%column_height-first_visible;
last_x=x=ulx + (width/horiz_fit) * (cur_entry / column_height);
if((x+1)==up_x && y==up_y) {
first_visible--;
state = ILS_DRAW;
break;
}
if((x+1)==down_x && y==down_y) {
first_visible++;
state = ILS_DRAW;
break;
}
move(y,x);
addch('>');
move(y,x);
refresh();
state = next_state;
break;
case ILS_KEYBOARD:
switch((c=(getch()&0x7f))) {
case ILS_ESCAPE: /* go back up or QUIT! */
if(level==1)
state=ILS_ASCEND;
else
state = ILS_EXIT;
break;
case ILS_EXIT_KEY: /* QUIT NOW! */
ils_exit(1);
break;
case ILS_ENTER:
case ILS_RETURN: /* descend into a directory */
if(active_list[cur_entry]->stat.st_mode & 040000) {
if(strcmp(active_list[cur_entry]->name,".")==0) {
flash(); /* change to current directory */
break;
}
if(strcmp(active_list[cur_entry]->name,"..")==0) {
if(level==1)
state = ILS_ASCEND;
else
state = ILS_EXIT;
break;
}
if(path[1]=='\0')
sprintf(newpath,"/%s",active_list[cur_entry]->name);
else
sprintf(newpath,"%s/%s",path,active_list[cur_entry]->name);
strcpy(last_active,active_list[cur_entry]->name);
if(active_list[cur_entry]->contents == (struct d_entry *)NULL) {
read_directory(pattern,newpath,&(active_list[cur_entry]->contents));
}
else {
chdir(newpath);
strcpy(cur_path,newpath);
re_read_dir(pattern,&(active_list[cur_entry]->contents));
}
refresh();
edit_directory(pattern,newpath,&(active_list[cur_entry]->contents),ulx,orig_uly,lrx,lry,title);
chdir(path); /* back up */
strcpy(cur_path,path);
state = ILS_INITIAL;
if((new_entries=re_read_dir(pattern,dptr))!=entries)
next_state = ILS_FIND_CURSOR;
else
next_state = ILS_INITIAL2;
}
break;
case ILS_UP: /* move cursor up */
if(cur_entry==0 || (cur_entry%column_height)==0)
break; /* can't move up one */
cur_entry--;
y=uly+cur_entry%column_height-first_visible;
if(y<uly) {
state = ILS_DRAW;
first_visible--;
}
else {
state = ILS_MOVE_CURSOR;
next_state = ILS_KEYBOARD;
}
break;
case ILS_DOWN: /* move cursor down */
if(cur_entry==(entries-1) || (cur_entry%column_height)==column_height-1)
break; /* can't move down one */
cur_entry++;
y=uly+cur_entry%column_height-first_visible;
if(y>=lry) {
state = ILS_DRAW;
first_visible++;
}
else {
state = ILS_MOVE_CURSOR;
next_state = ILS_KEYBOARD;
}
break;
case ILS_RIGHT: /* move cursor right */
if(cur_entry+column_height >= entries)
break; /* can't move right */
else {
cur_entry+=column_height;
state = ILS_MOVE_CURSOR;
next_state = ILS_KEYBOARD;
}
break;
case ILS_LEFT: /* move cursor left */
if(cur_entry-column_height < 0)
break; /* can't move left */
else {
cur_entry-=column_height;
state = ILS_MOVE_CURSOR;
next_state = ILS_KEYBOARD;
}
break;
case ILS_REDRAW: /* redraw the screen */
case ILS_REDRAW_ALT: /* alternate character */
state = ILS_TOTAL_DRAW;
break;
case ILS_ENV: /* display symbol table */
display_symtab();
state = ILS_TOTAL_DRAW;
break;
case ILS_FORCE_KEYBOARD: /* force us into keyboard mode */
default:
if(keybd(c,ulx,orig_uly+(title==NULL? 0:1),lrx,lry,line)) {
strcpy(last_active,active_list[cur_entry]->name);
process_input(c,active_list,cur_entry,entries,line,ulx,orig_uly+(title==NULL? 0:1),lrx);
state = ILS_INITIAL;
if((new_entries=re_read_dir(pattern,dptr))!=entries)
next_state = ILS_FIND_CURSOR;
else
next_state = ILS_INITIAL2;
showpath(path,ulx,orig_uly+(title==NULL? 0:1),lrx,lry);
}
else
state = ILS_SHOW_PATH;
break;
}
break;
case ILS_ASCEND: /* up into a new directory */
if(path[1]=='\0') { /* at root (/) ? */
flash(); /* can't go up any higher! */
state = ILS_KEYBOARD; /* back to input mode */
break;
}
strcpy(newpath,path);
/* find the first '/' character from the right, then chop the
path from that point on. This is to make a path like:
/usr/local/bin
into
/usr/local
*/
for(i=strlen(path)-1;i && newpath[i]!='/';i--);
if(i==0) { /* i==0 if we are one level down from root */
strcpy(newpath,"/"); /* make root the new path */
strcpy(this_dir,&(path[1]));
}
else {
newpath[i]='\0'; /* up one level in the path */
strcpy(this_dir,&(newpath[i+1]));
}
if(this_dir[0]=='\0') /* make sure not a null string */
break; /* a little safeguard */
cur = (struct d_entry *) NULL; /* ready to read a new dir */
read_directory(pattern,newpath,&cur); /* read it */
t = cur; /* find the entry in the new directory that
corresponds to this directory's name. */
strcpy(last_active,this_dir); /* for finding cursor pos */
for(cur = (*dptr);cur!=(struct d_entry *)NULL;) {
if(strcmp(cur->name,this_dir)==0) {
/* found it. assign contents to this entry */
cur->contents = (*dptr);
cur = (struct d_entry *) NULL;
}
else /* try next one */
cur = cur->next;
}
(*dptr) = t; /* make this the new "top of tree" pointer */
strcpy(cur_path,newpath); /* let globals know */
strcpy(path,newpath);
cur_entry = first_visible = 0;
state = ILS_INITIAL; /* make this the active one */
next_state = ILS_FIND_CURSOR;
break;
case ILS_EXIT: /* QUIT! */
move(last_y,last_x);
addch(' '); /* erase cursor */
level--; /* back up one level */
if(level==0) {
noraw();
echo();
}
return(1);
break;
}
}
}
/* add an entry to a directory list.
** pattern is the array of search patterns as passed to ils()
** i is the inode number of this entry
** p is the name of this entry
** place the the pointer to the directory list (of d_entry's)
*/
add_entry(pattern,i,p,place)
long i;
char *pattern[],*p;
struct d_entry **place;
{
struct d_entry *t, *cur, *last;
int l, match;
struct stat st;
char *ps, *pd;
if(i==0) /* if inode is 0, file was removed */
return;
if(stat(p,&st)<0) /* can't stat file, don't add it */
return;
if(p[0]=='.' && (modes&ILS_ALL)==0) /* is this a "." file? */
return; /* starts with '.', not in list all mode */
if(pattern[0]!=(char *)NULL) { /* if patterns are used, see if match */
for(l=match=0;pattern[l]!=(char *)NULL && match==0;l++) {
if(wildmat(p,pattern[l]))
match++; /* matches a pattern */
}
if(!match)
return; /* doesn't match any patterns */
}
new_entry(&t,p,&st); /* get memory and assign values */
if(*place == (struct d_entry *)NULL) /* empty list */
*place=t;
else {
/* loop through and decide where to place the new entry.
the list is a sorted doubly-linked list. */
cur = last = *place;
while(cur != (struct d_entry *)NULL) {
if(strcmp(p,cur->name) < 0) { /* insert before */
if(cur == *place) { /* at top of list */
t->next = *place;
cur->prev = t;
*place = t;
return;
}
else { /* in middle */
cur->prev->next = t;
t->prev = cur->prev;
cur->prev = t;
t->next = cur;
return;
}
}
else { /* check next name */
last = cur;
cur = cur->next;
}
}
if( cur == (struct d_entry *)NULL) { /* insert at end of list */
last->next = t;
t->prev = last;
}
}
}
/* get a string from the keyboard, and process it based on defined keysequences.
** c is the first character (as entered in the mailine ils code above.
** if c is not a FORCE_KEYBOARD character, thenn it is inserted into
** the string passed to the string editing routine, as the first character
** of the user's string.
** leftx,upy,rightx,downy are screen coordinates of the window size,
** regarding the location of the upper-left and lower-right corners.
** line is a pointer to a string. This is where the keyboard input will
** be placed and thus passed back to the calling routine.
*/
keybd(c,leftx,upy,rightx,downy,line)
int leftx, upy, rightx, downy;
char c, line[];
{
int l;
if(c==ILS_FORCE_KEYBOARD) /* is this a FORCED KEY SEQUENCE? */
line[0]='\0';
else { /* if legal character, insert into line[] */
if(c<' ' || c >0x7f) /* out of range */
return;
line[0]=c;
line[1]='\0';
}
if(rightx-leftx-7 < 2) /* see if we can fit the prompt */
return(0); /* no space on screen for input */
move(upy,leftx);
printw("Input: "); /* print the prompt */
l=getst(rightx-leftx-8,leftx+7,upy,line,rightx-leftx-7,&l,ALL_ALPHA,NULL);
if(l==GET_RETURN || l==GET_DOWN)
return(1);
return(0); /* probably ESCAPED out */
}
/* free_contents() de-allocates the contents of the directory pointed at
** by p.
*/
free_contents(p)
struct d_entry *p;
{
if(p->next != (struct d_entry *)NULL) /* depth-first deallaocation */
free_contents(p->next);
if(p->contents != (struct d_entry *)NULL) /* get rid of contents */
free_contents(p->contents);
free(p); /* get rid of top node */
}
/* re_read_dir() takes another look at the contents of a directory for
** changes in the contents or mode bits of the directory members.
** This is used when a directory is re-entered into, and we need to see
** if files were remove, added, or changed in any way.
**
** pattern is the array of search patterns as passed to ils() initially.
**
** dptr is the pointer to the contents of the directory last time it was
** examined.
*/
re_read_dir(pattern,dptr)
char *pattern[];
struct d_entry **dptr;
{
char name[MAXPATH], *pd, *ps;
struct d_entry *tdptr,*t;
int i,inode,r,done,mxloop;
struct stat st;
long touch, time();
#ifdef BSD /* berkeley directories are different */
DIR *dp, *opendir();
struct direct *dirptr, *readdir();
if(chdir(cur_path)<0)
return;
if((dp=opendir("."))==NULL)
return;
tdptr = *dptr;
touch = time((long *)0);
while((dirptr=readdir(dp))!=NULL) {
strcpy(name,dirptr->d_name);
inode = dirptr->d_fileno;
#endif BSD
#ifdef SYSTEMV
struct direct d;
int fd;
if(chdir(cur_path)<0)
return;
if((fd=open(".",O_RDONLY))<0)
return;
tdptr = *dptr;
touch = time((long *)0);
while(read(fd,&d,sizeof(struct direct)) == sizeof(struct direct)) {
strncpy(name,d.d_name,DIRSIZ);
name[DIRSIZ]='\0';
inode = d.d_ino;
#endif SYSTEMV
/* common entry-handling code */
if(inode) /* if this file wasn't removed, stat it */
if(stat(name,&st)<0)
continue; /* can't stat? forget this one! */
if(name[0]=='.' && (modes&ILS_ALL)==0)
continue; /* skip this, not in 'list all' mode */
done=0;
mxloop=0;/* mxloop is a safeguard. It was used for
initial debugging, and can probably be removed */
while(!done && mxloop++ < 10000) {
if((r=strcmp(name,tdptr->name))==0) {
if(inode) { /* copy over new stat struct */
for(i=0, ps=(char *)&st,pd=(char *)&(tdptr->stat);i<sizeof(struct stat);i++)
*pd++ = *ps++;
/* flag this file as "touched" */
tdptr->touched = touch;
}
done=1; /* file found, move on to next */
}
else if(r<0 && inode) { /* name < tdptr->name insert before? */
if((tdptr->prev) == (struct d_entry *)NULL) {
/* insert at top of list */
new_entry(&t,name,&st);
t->touched = touch;
t->next = tdptr;
tdptr->prev = t;
*dptr = t;
done=1;
}
else if(strcmp(name,tdptr->prev->name)>0) {
/* insert above tdptr */
new_entry(&t,name,&st);
t->touched = touch;
tdptr->prev->next = t;
t->next = tdptr;
t->prev = tdptr->prev;
tdptr->prev = t;
done=1;
}
else
tdptr = tdptr->prev;
}
else if(inode) { /* name > tdptr->name insert after? */
if((tdptr->next) == (struct d_entry *)NULL) {
/* insert at end of list */
new_entry(&t,name,&st);
t->touched = touch;
tdptr->next = t;
t->prev = tdptr;
done=1;
}
else if(strcmp(name,tdptr->next->name)<0) {
/* insert just below tdptr */
new_entry(&t,name,&st);
t->touched = touch;
t->next = tdptr->next;
tdptr->next = t;
t->prev = tdptr;
t->next->prev = t;
done=1;
}
else
tdptr = tdptr->next;
}
else
done=1;
}
}
/* loop through and remove all entries that have a different touch
if the touch value doesn't match, then file was removed and the
entry in the directory was used by a new filename. */
tdptr = *dptr; /* start at top of directory */
while(tdptr != (struct d_entry *) NULL) {
if((tdptr->touched) != touch) {
/* need to remove this entry, see where it's at */
if(tdptr == (*dptr)) {
/* at the top */
*dptr = (*dptr)->next;
(*dptr)->prev = (struct d_entry *)NULL;
tdptr->next = (struct d_entry *)NULL;
free_contents(tdptr);
tdptr = *dptr;
}
else if(tdptr->next == (struct d_entry *)NULL) {
/* at the bottom */
tdptr->prev->next = (struct d_entry *)NULL;
free_contents(tdptr);
tdptr = (struct d_entry *) NULL; /* end */
}
else {
/* in the middle somewhere */
t = tdptr->next;
tdptr->prev->next = tdptr->next;
tdptr->next->prev = tdptr->prev;
tdptr->next = (struct d_entry *) NULL;
free_contents(tdptr);
tdptr = t;
}
}
else /* try next entry */
tdptr = tdptr->next;
}
#ifdef BSD
closedir(dp);
#endif BSD
#ifdef SYSTEMV
close(fd);
#endif SYSTEMV
}
/* new_entry allocates memory for a new addition to a directory, then
** copies in the name and stat structure into the newly allocated structure.
** It copies nulls into all of the structure's pointers.
**
** tex is to be assigned to the address of the new memory.
** name is the string to copy into the name field.
** st is a pointer to the stat structure to copy over.
*/
new_entry(tex,name,st)
struct d_entry **tex;
char *name;
struct stat *st;
{
struct d_entry *t;
register int i;
char *pd, *ps;
if((*tex=t= (struct d_entry *) malloc(sizeof(struct d_entry)))==NULL) {
clear();
printw("OUT OF MEMORY!\n");
refresh();
ils_exit(1);
}
t->name = (char *)malloc(strlen(name)+1); /* alloc space for name */
strcpy(t->name,name); /* copy name over */
for(i=0, ps=(char *)st,pd=(char *)&(t->stat);i<sizeof(struct stat);i++)
*pd++ = *ps++; /* copy stat over on byte at a time */
t->next = (struct d_entry *) NULL; /* null out all pointers */
t->prev = (struct d_entry *) NULL;
t->contents = (struct d_entry *) NULL;
}
/* exit ils gracefully with 'code' as the exit code */
ils_exit(code)
int code;
{
noraw(); /* out of raw mode */
echo(); /* echo back on */
endwin(); /* exit curses */
exit(code);
}