home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- * 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);
- }
-