home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- *******************************************************************************
-
- Site: Western Michigan University Academic Computer Center
-
- System: Directory/File System Maintenance
-
- Program: maint
-
- Version=01 Level=00 01/24/92 Leonard J. Peirce
-
- Purpose: This program provides the user with a full-screen method for
- maintaining directories and file systems. The directory
- will be presented to the user in a series of screens, each
- of which will contain information about individual files.
- The user may move through a directory structure, marking files
- for deletion, changing protection modes, renaming files,
- creating text descriptors, copying files, editing files, and
- viewing files. Other options are available to allow the user
- to fork a subprocess to return to shell and search for a
- file.
-
- See the manual page maint.1 for more details.
-
- Arguments:
-
- -a auto-advance the cursor on
- Delete or Unmark
- -c ask for confirmation before executing
- -d include date field for files
- -f full info; implies -ogds
- -g include group name for files
- -o include owner field for files
- -p include protection field for files
- -s include size (in bytes) for files
- -t start up in text mode
- -S <sort-opt> sort files by <sort-opt>; legal
- values are: size, date, protection,
- filename; default is filename
-
- External variables: See individual routine(s)
-
- Maint external functions:
-
- Defined: None
-
- Called: cat, check_marks, clean_up, clear_mess, config_options,
- create_text, edit, erase_tag, file_locate,
- file_ptr_locate, file_select, follow_link, free_comm,
- free_pool, get_args, get_bnum, get_dir, get_dir_mem,
- get_filemarks, get_num_file, get_scr_num, give_help,
- highlite, info, init_pool, initialize, make_screen,
- make_slot, mark_cancel, mark_copy_ren, mark_delete,
- mark_group, mark_owner, mark_protect, mark_rename,
- mark_repeat, mark_text, prompt_getstr, put_pagnum,
- put_slot, put_spec, put_stat, put_text, read_text_des,
- screen_reset, set_args, set_nodes, set_screen,
- sort_files, strindex, strmcpy, strdel, tag_file, xecute
-
- Files accessed: only those in the directory and possibly .maint.tdf
- in other directories
-
- Return codes: 0 Successful completion
-
- Compiling instructions: See Makefile.
-
- Linking instructions: See Makefile.
-
- Other information: (C) Copyright 1992, Leonard J. Peirce
-
- Data structures:
-
- Several different data structures are used internally to Maint to store
- all kinds of information, ranging from the filenames and related information
- to text descriptors and new filenames.
-
- Directory information for the files in a directory is allocated dynamically
- upon entry to the proc_dir() function. An automatic pointer, dirptr, is
- used to point to the memory that holds the information about the files.
- This pointer MUST remain automatic because each directory needs it own
- copy. After the number of files in the directory is determined, the
- amount of memory needed to hold the information about each file in the
- directory can be calculated. It is calculated by taking the number of
- files in the directory, adding one, and multiplying it by the length of
- the structure definition ENT_DEF. This is the number of bytes needed.
- The memory is allocated by calling malloc() and the pointer to the
- memory is stored in dirptr.
-
- When a Finish command is issued or the commands in a directory are executed,
- the memory is deallocated, the number of files is computed, the size of
- the memory necessary is calculated, and the memory is allocated once again.
-
- A) Memory Pools
-
- MAINT uses its own memory pool allocation scheme. These memory pools are
- used to store only CHARACTER data and thus there is no need to worry about
- byte alignment for integer values and such. Items that are stored in the
- memory pools include: 1) the full filename of a file, and 2) the text
- descriptor of the file in case the user selects Text mode.
-
- The pools are allocated on a demand basis and are linked together into a
- linked list. The size of each memory pool in the list can vary, depending
- on the state of the information that will be included for each directory.
- The global variable ent_factor is initially set to FUDGE_FACTOR, which is
- a guess at the number of bytes that each file entry is going to need to
- store its information. Then the run-time arguments are taken into account,
- with ent_factor being updated for each that argument that will require
- something stored in the memory pools. See the routine set_factors() for
- the values that ent_factor is increased by.
-
- When it is time to redo the information for a directory, the memory in the
- memory pools is reclaimed rather than released and reallocated. The pointer
- to the next available byte in the structure is set to point to the beginning
- of the memory pool and the remaining length is reset to the original length
- of the pool. This may waste a little memory but it saves a few calls that
- would be needed to free and reallocate the memory.
-
- B) Command structures
-
- Command structures are used to hold the information necessary to carry out
- commands for a specific file. When the first command for a file is speci-
- fied by the user, a new command structure is allocated and linked to the
- file entry for the file, the pointer to the command structure being stored
- in the command field of the ENT_DEF structure.
-
- All of the information in the command structure that requires string values
- (such as ren_name, copy_name, and text) are stored in memory allocated by
- malloc() and NOT in a memory pool. This is to cut down on wasting of
- memory for file commands that are cancelled.
-
- When commands for a file are cancelled, all the memory for any of the char-
- acter strings are freed (via free()) and the command structure itself
- is freed.
-
- ********************************************************************************
- *******************************************************************************/
-
- /******************************************************************************/
- /* */
- /* # I N C L U D E F I L E S */
- /* */
- /******************************************************************************/
-
- #ifdef ultrix
- #include <cursesX.h>
- #include <unistd.h>
- #else
- #include <curses.h>
- #include <sys/file.h>
- #endif
- #include <sys/param.h>
- #include <sys/stat.h>
- #include <stdio.h> /* who knows? (NULL maybe?) */
- #include <time.h> /* for getting current year value */
- #include <string.h> /* string functions */
- #include <malloc.h> /* so free is declared right */
- #include "maint.h" /* our very own header file */
-
- /******************************************************************************/
- /* */
- /* # D E F I N E S */
- /* */
- /******************************************************************************/
-
- #define MAX_DIR 15 /* max. # of subdirectories to save */
-
- /******************************************************************************/
- /* */
- /* S T R U C T U R E S , U N I O N S , T Y P E D E F S */
- /* */
- /******************************************************************************/
-
- /******************************************************************************/
- /* */
- /* E X T E R N A L D E F I N I T I O N S & D E C L A R A T I O N S */
- /* */
- /******************************************************************************/
-
- extern char *getenv();
-
- extern u_int sleep();
-
- extern int strindex(),
- access();
-
- extern long get_bnum();
-
- extern int mark_text(),
- mark_delete(),
- mark_copy_ren(),
- mark_protect(),
- mark_rename(),
- mark_repeat(),
- mark_owner(),
- mark_group(),
- check_marks(),
- put_slot(),
- file_select(),
- edit(),
- make_slot(),
- read_text_des(),
- file_locate(),
- file_ptr_locate(),
- follow_link(),
- config_options(),
- create_text();
-
- extern short info(),
- get_num_file(),
- get_scr_num();
-
- extern void mark_cancel(),
- free_comm(),
- set_screen(),
- set_args(),
- set_nodes(),
- get_args(),
- get_dir_mem(),
- get_dir(),
- make_screen(),
- init_pool(),
- free_pool(),
- initialize(),
- put_stat(),
- put_spec(),
- put_pagnum(),
- prompt_getstr(),
- screen_reset(),
- clear_mess(),
- highlite(),
- tag_file(),
- erase_tag(),
- clean_up(),
- put_text(),
- xecute(),
- get_text(),
- get_filemarks(),
- give_help();
-
- #if defined(SYSV) && !defined(sun)
-
- extern char *getcwd();
- extern u_short geteuid();
-
- #else
-
- extern char *getwd();
-
- #endif
-
- ENT_DEF *baseptr; /* pointer to directory entries */
-
- WINDOW *spec_win, /* directory spec/page # window */
- *main_win, /* main display window */
- *stat_win; /* stats/options window */
-
- int *global_row, /* so others functions can use it */
- *global_col, /* ditto.... */
- curr_year, /* current year value */
- main_rows; /* rows in main window */
-
- u_short node_row_max, /* max. # of rows in nodes array */
- node_col_max, /* max. # of columns in nodes array */
- cont_flag; /* set if continuing after suspend */
-
- ARG_DEF args; /* run-time argument flags */
-
- NODE_DEF nodes[MAX_NODE_ROW+1][MAX_NODE_COL+1];
-
- ARG_STR arg_strings[] = {
- {"Include file size? (-s) ",&args.size},
- {"Include file protection? (-p) ",&args.prot},
- {"Include date? (-d) ",&args.date},
- {"Include group? (-g) ",&args.group},
- {"Include owner? (-o) ",&args.owner},
- {"Confirm before Xecuting marks? (-c) ",&args.confirm},
- {"Auto-feed on Delete/Unmark? (-A) ",&args.auto_feed},
- {"Include text descriptors? (-t) ",&args.text},
- {"Include dot-files? (-a) ",&args.dot_files},
- {"Include file marks? (-F) ",&args.filemarks},
- {"Sort field? (-S) ",&args.sort}
- };
-
- /******************************************************************************/
- /* */
- /* S T A T I C D E F I N I T I O N S & D E C L A R A T I O N S */
- /* */
- /******************************************************************************/
-
- static DIR_PTR dir_ent_head, /* head of directory node info list */
- dir_ent_tail, /* tail....... */
- *link_dir_ent(), /* link active directory node */
- *find_dir(); /* for searching the list */
-
- static size_t ent_factor; /* ent. size memory allocation factor */
-
- static int home_len, /* length of home_dir */
- get_year(), /* get current year value */
- proc_dir(); /* process current directory */
-
- static short def_slot_wid; /* default slot width */
-
- static char home_dir[MAXPATHLEN+3];
-
- static void unlink_dir_ent(); /* unlink active directory node */
-
- /******************************************************************************/
- /* */
- /* M A I N P R O C E S S I N G */
- /* */
- /******************************************************************************/
-
- main(argc,argv)
- /******* FORMAL PARAMETERS *******/
- int argc; /* number of run-time arguments */
- char **argv; /* run-time argument strings */
-
- { /*** main ***/
- /******** LOCAL VARIABLES ********/
- short retval; /* return value from proc_dir() */
-
-
- /* check the command-line arguments and set up 1) the screen width and 2)
- * the slot width
- */
-
- get_args(argc,argv,&args);
-
- curr_year = get_year(); /* get the current year */
-
- strcpy(home_dir,getenv("HOME"));
- home_len = strlen(home_dir);
-
- /* initialize/allocate all of the windows that will be needed and get
- * the necessary control strings from the termcap database
- */
-
- initialize(&spec_win,&main_win,&stat_win,&node_row_max,&node_col_max);
-
- /* initialize some global factors, such as the ent_factor and default
- * slot width
- */
-
- set_args(&args,&def_slot_wid,&ent_factor);
-
- /* set up the active directory linked list */
-
- dir_ent_head.next = &dir_ent_tail;
- dir_ent_head.prev = &dir_ent_tail;
- dir_ent_tail.next = &dir_ent_head;
- dir_ent_tail.prev = &dir_ent_head;
-
- /* go for it -- process the directories and any thing else that the
- * user might desire
- */
-
- do
- {
- retval = proc_dir();
- }
- while(retval == RECALL_PROC);
-
- clean_up(); /* reset things */
-
- } /*** main ***/
-
- /*******************************************************************************
- ********************************************************************************
-
- Function: proc_dir
-
- Purpose: Process the current directory. This includes allocating memory
- for storing the information about the files and handling all
- of the user responses. This routine is recursive and is called
- each time the user "selects" a new directory; the current dir-
- ectory is switched and this routine is called again. When the
- user exits a directory, this routine frees up the memory that
- was allocated for the directory and returns. The cursor is
- left pointing to the directory that was just exited.
-
- This is a *RECURSIVE* function.
-
- Global variables:
-
- Name Examine/Modify/Use/Read/Write
- ---- -----------------------------
- args X X
- user_dir X
- ent_factor X
- def_slot_wid X X
- main_rows X
- main_win X
- home_dir X
- home_len X
- node_row_max X
- dir_ent_head X
- dir_ent_tail X
-
- Return Codes:
-
- Code Reason
- ---- ------
- 0 return normally
- RECALL_PROC return and force this procedure to be recalled
- immediately
- EMPTY_DIR the directory entry selected to get us here is
- empty
-
- ********************************************************************************
- *******************************************************************************/
-
- static int proc_dir()
-
- { /*** proc_dir ***/
- /********* LOCAL VARIABLES ********/
- register int term_code; /* code for keystroke */
- DIR_PTR *dir_ent_ptr; /* pointer to directory info node */
- ENT_DEF *dirptr, /* pointer to directory information */
- *entptr, /* pointer to directory entry */
- *prev_ptr; /* ptr to file from previous command */
- POOL_DEF *first_pool, /* pointer to first memory pool */
- *curr_pool; /* pointer to current memory pool */
- char *dir_text= NULL, /* pointer to directory text descrip */
- *dir_name; /* current directory name */
- long num_block = 0L; /* number of blocks in directory */
- u_int dirsize; /* size of directory info memory */
- size_t pool_length; /* length for allocating new pools */
- time_t stat_time; /* last mod time for directory */
- int scr_col, /* current screen column */
- scr_row; /* current screen row */
- u_short prev_command; /* last command -- used for repeating */
- short num_col, /* number of columns for full screen */
- node_col, /* current node array column */
- node_row, /* current node array row */
- slot_width, /* slot width for current directory */
- num_row, /* number of rows for full screen */
- num_file = 0, /* number of files in directory */
- curr_screen = 1, /* current screen of directory */
- num_screen = 0, /* number of screens in directory */
- scr_file, /* number of files for current screen */
- num_slot, /* number of slots per screen */
- branched = FALSE, /* TRUE if we Branched to a directory */
- filemarks_flag = 0, /* TRUE if marks processed in dir */
- sort_flag = 0, /* TRUE if entries have been sorted */
- text_flag = 0; /* text descrip file processed flag */
- /** above vars MUST remain automatic **/
- static COM_DEF *comm_ptr; /* for saving pointer to commands */
- static char *tptr; /* temporary character pointer */
- static int curr_type, /* type of current file */
- status; /* return code status */
- static short temp, /* temporary value */
- temp2, /* temporary value #2 */
- save_width, /* temporary slot width holder */
- change_dir, /* set if we're changing directories */
- new_screen, /* new screen when locating files */
- level; /* what recursion level we are at */
- static DIR_SUMM dirmem[MAX_DIR]; /* summary info for all directories */
- static struct stat statbuf; /* for getting access time for dir */
- static u_char mess_flag, /* set if information mess on screen */
- cursor_flag, /* set if cursor needs to be set */
- exec_flag, /* set if we just executed commands */
- pass; /* for one-time execution of stuff */
- static char slot_buf[BUFSIZ]; /* for formatting screen slots */
-
-
- cursor_flag = 0;
- prev_ptr = NULL; /* no previous command yet */
- slot_width = def_slot_wid; /* initialize the slot width */
- num_row = node_row_max; /* set number of rows for now */
-
- /* this is kind of weird; we need to get the directory name soon after
- * entering proc_dir() and BEFORE calling get_num_file() in case we hit
- * hit an empty directory; the reason is that we might be coming backing
- * in to a directory that was previously non-empty and thus would need to
- * find the node in the active directory list for this directory and delete
- * it; and since we search the list by directory, we need the directory
- * name; grrr......
- */
-
- dir_name = (char *) malloc(MAXPATHLEN+3);
-
- #if defined(SYSV) && !defined(sun)
- getcwd(dir_name,MAXPATHLEN+2);
- #else
- getwd(dir_name);
- #endif
-
- /* find the active node for this directory, if it exists */
-
- dir_ent_ptr = find_dir(&dir_ent_head,&dir_ent_tail,dir_name);
-
- num_file = get_num_file(&args); /* get number of files in directory */
-
- if(num_file == 0 || stat(".",&statbuf) != 0)
- {
- /* have we been here before? if so, we need to free up the memory
- * pools
- */
-
- if(dir_ent_ptr != NULL)
- {
- free_pool(dir_ent_ptr->first_pool);
- dir_ent_ptr->num_file = 0; /* gone but not forgotten */
- unlink_dir_ent(dir_ent_ptr);
- }
-
- return(EMPTY_DIR);
- }
-
- stat_time = statbuf.st_ctime; /* save time directory last changed */
- sort_flag = args.sort;
-
- if(dir_ent_ptr != NULL)
- {
- /* this directory is currently active */
-
- free(dir_name); /* don't need this anymore */
- dirptr = dir_ent_ptr->dirptr;
- dir_name = dir_ent_ptr->dir_name;
- first_pool = dir_ent_ptr->first_pool;
- curr_pool = dir_ent_ptr->curr_pool;
- pool_length = dir_ent_ptr->pool_length;
- num_file = dir_ent_ptr->num_file;
- dir_ent_ptr->count += 1; /* update the active count */
- }
- else
- {
- /* this directory currently has no activity; this *doesn't* mean that
- * it hasn't seen before; it just means that the user hasn't visited
- * it, Branched out, and returned to it
- */
-
- /* get some memory to hold info about individual files */
-
- get_dir_mem(&dirptr,&dirsize,num_file);
-
- /* initialize the memory pools for holding the full filenames of the
- * files in the directory
- */
-
- pool_length = (num_file + 1) * ent_factor;
- init_pool(&first_pool,pool_length);
- curr_pool = first_pool; /* set current pool pointer */
-
- /* get all of the information about the files in the directory */
-
- get_dir(dirptr,&args,&num_block,&curr_pool,&num_file,pool_length);
-
- /* were there any files to get? there might not be, depending on the
- * volatility of the directory and file protections
- */
-
- if(!num_file)
- {
- free_pool(first_pool); /* free up the memory pools first */
-
- /* now free up the memory for the directory information */
-
- free((char *) dirptr);
- return(EMPTY_DIR);
- }
-
- get_text(&args,dirptr,&curr_pool,&dir_text,&mess_flag,&slot_width,
- &text_flag,pool_length,num_file);
-
- /* make a directory node entry and add it to the list */
-
- dir_ent_ptr = link_dir_ent(&dir_ent_head,&dir_ent_tail,dirptr,dir_name,
- first_pool,curr_pool,pool_length,stat_time,
- num_file);
- }
-
- global_row = &scr_row; /* mostly for handling signals */
- global_col = &scr_col;
-
- dirmem[level].ptr = dirptr; /* save a pointer to this memory */
- dirmem[level].num_file = num_file;
-
- /* count this recursion level; when it equals one, it means that we are in
- * the top-level directory for this session
- */
-
- level++;
-
- /* all of the information about the files in the directory has been
- * obtained; now initialize the screen parameters, including the screen
- * nodes and the number of screens for the directory
- */
-
- set_screen(&num_screen,&scr_file,num_file,slot_width,node_row_max,&num_col);
-
- num_slot = scr_file; /* save number of slots per screen */
-
- /* initialize the screen slot node pointers for the screen */
-
- set_nodes(nodes,node_row_max,&scr_file,num_screen,curr_screen,num_file,
- slot_width,num_col);
-
- /* write the directory statistics line at the bottom of the display
- * and the directory spec/page number line at the top of the display
- */
-
- put_spec(spec_win,dir_name,home_dir,home_len,num_screen);
- put_stat(stat_win,num_block,num_file);
-
- if(args.text) /* write text descrip for directory? */
- put_text(spec_win,dir_text);
-
- /* clear the main virtual display; we do this every time we enter a
- * directory to make things simple; some directories might have text
- * descriptors and some might not; this way, we make sure that we have
- * a clean display to work with, no matter what
- */
-
- werase(main_win);
-
- /* put the information about the files for the first screen on the screen */
-
- make_screen(main_win,nodes,dirptr,&args,curr_screen,node_row_max,
- node_col_max,scr_file,num_slot,slot_width,text_flag);
-
- /* position the cursor to the first file in the directory */
-
- node_row = 0; /* start in top left of nodes array */
- node_col = 0;
- scr_row = (int) nodes[0][0].row; /* start in top left of screen, too */
- scr_col = (int) nodes[0][0].column;
-
- /* write the options line only once */
-
- if(!pass)
- {
- put_options(stat_win);
- pass++;
- }
-
- /* set the cursor position to the first file */
-
- wmove(main_win,scr_row,scr_col);
- wrefresh(main_win);
-
- /* this is the main processing loop for the whole program; each keystroke
- * is read and appropriate action is taken for each; this is an infinite
- * loop and the only way out is to break out from the middle and return
- * to a previous invocation of this function
- */
-
- for(;;) /* loop forever......... */
- {
- /* get a keystroke from the keyboard (store in term_code) */
-
- term_code = wgetch(main_win);
-
- if(mess_flag) /* was a message on the screen? */
- {
- clear_mess(main_win); /* clear the message */
- mess_flag = 0; /* clear the message flag */
-
- /* reset the cursor to where it should be */
-
- wmove(main_win,scr_row,scr_col);
- }
-
- /* now look at the key that was pressed and take appropriate action */
-
- switch(term_code)
- {
- case(CONTROL_I): /**************************************/
- case(' '): /* right-arrow */
- case('>'): /**************************************/
- case('L'):
- case('l'):
- case(KEY_RIGHT):
-
- /* update the pointer to the screen and then update the position
- * of the physical cursor; we must use temp to get the up_row
- * position and then assign it to node_row because we can't have
- * node_row changing before we use it to get node_col
- */
-
- temp = (short) nodes[node_row][node_col].right_row;
- node_col = (short) nodes[node_row][node_col].right_col;
- node_row = temp;
- scr_row = (int) nodes[node_row][node_col].row;
- scr_col = (int) nodes[node_row][node_col].column;
-
- cursor_flag++; /* reset the cursor down below */
- break;
-
- case(BACKSPACE): /**************************************/
- case('<'): /* left-arrow */
- case('H'): /**************************************/
- case(KEY_BACKSPACE):
- case('h'):
- case(KEY_LEFT):
-
- /* update the pointer to the screen and then update the position
- * of the physical cursor; we must use temp to get the up_row
- * position and then assign it to node_row because we can't have
- * node_row changing before we use it to get node_col
- */
-
- temp = (short) nodes[node_row][node_col].left_row;
- node_col = (short) nodes[node_row][node_col].left_col;
- node_row = temp;
- scr_row = (int) nodes[node_row][node_col].row;
- scr_col = (int) nodes[node_row][node_col].column;
-
- cursor_flag++; /* reset the cursor down below */
- break;
-
- case(LINEFEED): /**************************************/
- case('J'): /* down-arrow */
- case('j'): /**************************************/
- case(KEY_DOWN):
-
- /* update the pointer to the screen and then update the position
- * of the physical cursor; we must use temp to get the up_row
- * position and then assign it to node_row because we can't have
- * node_row changing before we use it to get node_col
- */
-
- temp = (short) nodes[node_row][node_col].down_row;
- node_col = (short) nodes[node_row][node_col].down_col;
- node_row = temp;
- scr_row = (int) nodes[node_row][node_col].row;
- scr_col = (int) nodes[node_row][node_col].column;
-
- cursor_flag++; /* reset the cursor down below */
- break;
-
- case('^'): /**************************************/
- case('K'): /* up-arrow */
- case('k'): /**************************************/
- case(KEY_UP):
-
- /* update the pointer to the screen and then update the position
- * of the physical cursor; we must use temp to get the up_row
- * position and then assign it to node_row because we can't have
- * node_row changing before we use it to get node_col
- */
-
- temp = (short) nodes[node_row][node_col].up_row;
- node_col = (short) nodes[node_row][node_col].up_col;
- node_row = temp;
- scr_row = (int) nodes[node_row][node_col].row;
- scr_col = (int) nodes[node_row][node_col].column;
-
- cursor_flag++; /* reset the cursor down below */
- break;
-
- case(CARRIAGE_RETURN): /**************************************/
- /* carriage return */
- /**************************************/
-
- /* go to left of screen and down one row on the screen */
-
- node_row = nodes[node_row][0].down_row;
- node_col = 0;
- scr_row = (int) nodes[node_row][node_col].row;
- scr_col = (int) nodes[node_row][node_col].column;
-
- cursor_flag++; /* reset the cursor down below */
- break;
-
- case('='): /**************************************/
- case('+'): /* plus-screen */
- case(CONTROL_F): /**************************************/
- case(KEY_NPAGE):
-
- if(num_screen > 1) /* more than one screen? */
- {
- curr_screen++; /* go to next screen */
- if(curr_screen > num_screen)
- curr_screen = 1; /* oops, I meant the first screen */
-
- if((curr_screen == 1) || (curr_screen == num_screen))
- {
- set_nodes(nodes,node_row_max,&scr_file,num_screen,
- curr_screen,num_file,slot_width,num_col);
- }
-
- /* update the page number in the corner */
-
- put_pagnum(spec_win,curr_screen,num_screen);
-
- /* write the files to the screen */
-
- make_screen(main_win,nodes,dirptr,&args,curr_screen,
- node_row_max,node_col_max,scr_file,num_slot,
- slot_width,text_flag);
-
- /* reset screen and node pointers */
-
- node_row = 0;
- node_col = 0;
- scr_row = (int) nodes[0][0].row;
- scr_col = (int) nodes[0][0].column;
-
- /* home the cursor */
-
- cursor_flag++; /* reset the cursor down below */
- }
-
- break;
-
- case('-'): /**************************************/
- case('_'): /* minus-screen */
- case(CONTROL_B): /**************************************/
- case(KEY_PPAGE):
-
- /* reset the screen nodes if we have to */
-
- if(num_screen > 1)
- {
- curr_screen--; /* go to previous screen */
- if(curr_screen == 0) /* were we on the first screen? */
- curr_screen = num_screen; /* oops, go to last screen */
-
- if(curr_screen >= (num_screen-1))
- {
- set_nodes(nodes,node_row_max,&scr_file,num_screen,
- curr_screen,num_file,slot_width,num_col);
- }
-
- /* update the page number in the corner */
-
- put_pagnum(spec_win,curr_screen,num_screen);
-
- /* write the files to the screen */
-
- make_screen(main_win,nodes,dirptr,&args,curr_screen,
- node_row_max,node_col_max,scr_file,num_slot,
- slot_width,text_flag);
-
- /* reset screen and node pointers */
-
- node_row = 0;
- node_col = 0;
- scr_row = (int) nodes[0][0].row;
- scr_col = (int) nodes[0][0].column;
-
- /* home the cursor */
-
- cursor_flag++; /* reset the cursor down below */
- }
-
- break;
-
- case('/'): /**************************************/
- /* Locate-file */
- /**************************************/
-
- /* user wants to search for a filename; go for it */
-
- temp = (short) file_locate(main_win,dirptr,num_file);
-
- if(temp >= 0)
- {
- /* file was found; recompute the node indexes so that we
- * can change the cursor on the screen
- */
-
- new_screen = (temp / num_slot) + 1;
-
- /* get us to the current screen */
-
- temp2 = temp - ((new_screen - 1) * num_slot);
- node_col = temp2 / num_row;
- node_row = temp % num_row;
-
- /* do we need to go to a new screen? if so, make the new
- * one now
- */
-
- if(new_screen != curr_screen)
- {
- /* create the new screen by first putting the new page
- * number in the upper-right and then rebuilding the
- * main display
- */
-
- /* do we need to update the screen node pointers? */
-
- if((new_screen == num_screen) ||
- (curr_screen == num_screen))
- {
- /* set the nodes */
-
- set_nodes(nodes,node_row_max,&scr_file,num_screen,
- new_screen,num_file,slot_width,num_col);
- }
-
- curr_screen = new_screen;
-
- /* put the new page number on the screen */
-
- put_pagnum(spec_win,curr_screen,num_screen);
-
- /* build the display for the new screen */
-
- make_screen(main_win,nodes,dirptr,&args,curr_screen,
- node_row_max,node_col_max,scr_file,num_slot,
- slot_width,text_flag);
- }
-
- /* make the cursor point to the file that was found */
-
- scr_row = (int) nodes[node_row][node_col].row;
- scr_col = (int) nodes[node_row][node_col].column;
- }
- else if(temp == -1)
- {
- /* no file found; just put up a message and that's it */
-
- beep();
- info_mess("File not found");
- mess_flag++;
- }
-
- /* set the cursor where it is supposed to be, whether on the
- * file that was found or the file that it was on when the
- * failed search request was initiated
- */
-
- cursor_flag++; /* reset the cursor down below */
- break;
-
- case('U'): /**************************************/
- case('u'): /* Unmark */
- /**************************************/
-
- /* first get the entry pointer for the file selected */
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- /* now cancel all commands for the file entry and free up the
- * command structure that was allocated for it
- */
-
- mark_cancel(entptr);
-
- /* remake the slot so it can be written */
-
- temp = make_slot(slot_buf,entptr,&args,slot_width,text_flag);
-
- /* now write the file information to the screen in the
- * right spot
- */
-
- put_slot(main_win,scr_row,scr_col+1,slot_buf,A_NORMAL);
-
- if(args.auto_feed == TRUE)
- {
- /* move to the next logical file on the screen; basically, we are
- * just performing the same stuff we do for a down-arrow
- */
-
- temp = (short) nodes[node_row][node_col].down_row;
- node_col = (short) nodes[node_row][node_col].down_col;
- node_row = temp;
- scr_row = (int) nodes[node_row][node_col].row;
- scr_col = (int) nodes[node_row][node_col].column;
- }
-
- cursor_flag++;
- break;
-
- case('S'): /**************************************/
- case('s'): /* Select */
- /**************************************/
- case('B'): /* Branch */
- case('b'): /**************************************/
-
- change_dir = FALSE; /* just to be safe */
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- /* if the current file is a symbolic link, try to find out what
- * it is pointing to in case we need it later
- */
-
- if(entptr->type == LINK)
- curr_type = follow_link(entptr->filename);
- else
- curr_type = entptr->type; /* just use what we already have */
-
- if(term_code == 'S' || term_code == 's')
- {
- /* now see what was Selected */
-
- if(entptr->type == REGULAR || curr_type == REGULAR)
- {
- /* Selecting a file; just call the PAGER */
-
- if(access(entptr->filename,R_OK) != 0)
- status = CANT_OPEN;
- else if(entptr->size != 0)
- {
- /* the file is not empty; go ahead and try to look at it */
-
- status = file_select(entptr->filename);
- touchwin(main_win);
- touchwin(spec_win);
- touchwin(stat_win);
- wrefresh(main_win);
- wrefresh(spec_win);
- wrefresh(stat_win);
- }
- else
- status = EMPTY_FILE; /* file is empty */
-
- switch(status) /* what happened with the file? */
- {
- case(FAILURE):
-
- beep();
- info_mess("Cannot display selected file");
- mess_flag++;
- break;
-
- case(EMPTY_FILE):
-
- beep();
- info_mess("Selected file is empty");
- mess_flag++;
- break;
-
- case(CANT_OPEN):
-
- beep();
- info_mess("Cannot open file");
- mess_flag++;
- break;
-
- default:
- break;
- }
- }
- else if(entptr->type == DIRECTORY || curr_type == DIRECTORY)
- {
- /* Selected a directory; first see if we can even change
- * to it
- */
-
- if(chdir(entptr->filename) != 0)
- {
- beep();
- info_mess("Cannot change to selected directory");
- mess_flag++;
- cursor_flag++;
- }
- else
- {
- if(term_code == 'b') /* ask for confirmation first */
- {
- info_mess("There are commands in this directory. Execute them before branching? [y] ");
-
- term_code = wgetch(main_win);
-
- if(term_code == 'N' || term_code == 'n')
- break;
- }
-
- change_dir = TRUE;
- }
- }
- }
- else
- {
- /* must be a Branch command */
-
- prompt_getstr(main_win,"Directory: ",slot_buf,main_rows,
- sizeof(slot_buf));
-
- if(slot_buf[0] == '\0')
- {
- /* user just hit a return */
-
- cursor_flag++;
- }
- else if(chdir(slot_buf) != 0)
- {
- beep();
- info_mess("Cannot change to specified directory");
- mess_flag++;
- cursor_flag++;
- }
- else
- {
- /* it worked; save the directory name and set the
- * flag that says we are Jumping
- */
-
- branched = TRUE;
- change_dir = TRUE;
- }
- }
-
- if(change_dir == TRUE)
- {
- /* now call ourselves and start over with the new directory */
-
- /***********************************
- * R E C U R S I V E C A L L *
- ***********************************/
-
- do
- {
- temp = proc_dir();
- }
- while(temp == RECALL_PROC);
-
- baseptr = dirptr; /* point to current directory */
-
- /* change back to the directory that we should be in */
-
- if(chdir(dir_name) != 0)
- {
- /* problems changing to directory; scream at the user
- * and get out of here
- */
-
- beep();
- info_mess("Cannot reset directory....exiting...");
- sleep(2);
- exit(0);
- }
-
- /* see if the current directory has changed; if it has, we
- * need to rebuild it
- */
-
- if(stat(".",&statbuf) != 0)
- exit();
-
- if(stat_time < statbuf.st_ctime)
- {
- /* see if there are any commands to execute */
-
- if(check_marks(dirptr,num_file) == TRUE)
- {
- info_mess("Directory has been updated. Execute marks before rebuilding? [Y] ");
- term_code = wgetch(main_win);
- clear_mess(main_win);
-
- if(term_code != 'N' && term_code != 'n')
- xecute(dirptr,dir_text,num_file);
- else
- {
- /* free up the memory for any command structures that
- * might have been allocated
- */
-
- free_comm(dirptr,num_file);
- }
- }
-
- info_mess("Rebuilding directory.....");
- level--; /* decrement recursion level counter */
-
- /* free up the memory pools first */
-
- free_pool(first_pool);
- unlink_dir_ent(dir_ent_ptr);
-
- /* now free up the memory for the directory information */
-
- free((char *) dirptr);
-
- werase(main_win); /* erase display to be sure... */
- return(RECALL_PROC); /* go back to where we were called */
- }
-
- if(temp == EMPTY_DIR) /* did the user make a good choice? */
- {
- /* the directory that was selected was empty */
-
- beep();
- info_mess("Directory is empty...........");
-
- if(exec_flag)
- {
- sleep(2); /* only pause if we just executed */
- clear_mess(main_win);
- }
- else
- mess_flag++; /* clear it on next keystroke */
- }
-
- /* reset some things on the screen since we are actually
- * returning from a directory
- */
-
- if((args.text) && (!text_flag) && temp != EMPTY_DIR)
- {
- /* when we left this directory to go down, the
- * text descriptors were not included (at least not
- * not on the screen, anyway); when we were in
- * one of the descendant directories, the text
- * descriptors were selected; we must read them
- * in here; first, update the slot width on the
- * assumption that we can get the text descriptors
- * for the current directory without any trouble and
- * set the flag that signifies that we have text
- * descriptors read in for the current directory
- */
-
- if(args.text == DISPLAY_TEXT) /* room to display descrips? */
- slot_width += TEXT_MAX + 1; /* yes, assume we get them */
-
- text_flag = args.text;
-
- /* erase the display to make sure we don't have any
- * garbage left over if we need to reformat the screen
- */
-
- werase(main_win);
-
- temp = read_text_des(dirptr,&curr_pool,&dir_text,
- pool_length,num_file);
-
- if(temp == BAD_FILE)
- {
- beep();
- info_mess("Invalid format for text descriptor file");
- mess_flag++;
- text_flag = 0;
-
- if(args.text == DISPLAY_TEXT)
- slot_width = slot_width - (TEXT_MAX + 1);
-
- sleep(1);
- }
- else if(temp == CANT_OPEN)
- {
- beep();
- info_mess("Cannot open text descriptor file");
- mess_flag++;
- text_flag = 0;
-
- if(args.text == DISPLAY_TEXT)
- slot_width = slot_width - (TEXT_MAX + 1);
-
- sleep(1);
- }
- else if(temp == NO_FILE)
- {
- text_flag = 0;
-
- if(args.text == DISPLAY_TEXT)
- slot_width = slot_width - (TEXT_MAX + 1);
- }
- else if(temp == 0)
- {
- /* reset the screen parameters, just in case they need
- * to be changed to reflect text descriptors
- */
-
- set_screen(&num_screen,&scr_file,num_file,slot_width,
- node_row_max,&num_col);
- num_slot = scr_file;
- }
- }
-
- if(args.filemarks && !filemarks_flag)
- {
- /* the user has filemarks selected from a descendent
- * directory but we don't have them included in the
- * current directory; add them here
- */
-
- get_filemarks(dirptr,num_file);
- filemarks_flag = 1;
- }
-
- if(args.sort && !sort_flag)
- {
- /* the user turned on sorting in a descendent directory
- * but the directory isn't sorted; go ahead and sort now
- */
-
- sort_files(num_file - 1,args.sort);
- sort_flag = 1;
- }
- /*
- if((temp == EMPTY_DIR && exec_flag) || temp != EMPTY_DIR)
- {
- */
- /* we just executed commands in a directory so we must
- * rebuild stuff
- */
-
- set_nodes(nodes,node_row_max,&scr_file,num_screen,
- curr_screen,num_file,slot_width,num_col);
-
- /* rewrite all of the stuff local to this directory */
-
- put_spec(spec_win,dir_name,home_dir,home_len,num_screen);
- put_stat(stat_win,num_block,num_file);
-
- if(args.text) /* text descriptor to write? */
- put_text(spec_win,dir_text);
-
- /* this is important; we have to look for the directory
- * that we were on when the last Select was done and de-
- * termine what page it is on; we might have to change the
- * current page and everything just to put the cursor back
- * in the right spot
- */
-
- screen_reset(nodes,dirptr,entptr->filename,&node_row,
- &node_col,&scr_file,&curr_screen,node_row_max,
- num_file,num_slot,num_screen,slot_width,
- num_row,num_col);
-
- /* put the new page number on the screen */
-
- put_pagnum(spec_win,curr_screen,num_screen);
-
- /* create and write the screen again for the current
- * directory
- */
-
- make_screen(main_win,nodes,dirptr,&args,curr_screen,
- node_row_max,node_col_max,scr_file,
- num_slot,slot_width,text_flag);
-
- exec_flag = 0; /* make sure to reset this */
-
- /* reset the screen row and column */
-
- scr_row = (int) nodes[node_row][node_col].row;
- scr_col = (int) nodes[node_row][node_col].column;
- /*
- }
- */
- }
-
- exec_flag = 0;
- cursor_flag++; /* reset the cursor down below */
- break;
-
- case('X'): /**************************************/
- case('x'): /* eXecute */
- /**************************************/
-
- if(args.confirm) /* should we ask to make sure? */
- {
- /* the user wants to be asked if they REALLY want to execute
- * the commands for the directory
- */
-
- info_mess("REALLY eXecute commands? [N] ");
- term_code = wgetch(main_win);
-
- /* now look at what the keystroke is; if it is not Y or y,
- * then we DO NOT execute the commands for the directory
- */
-
- if((term_code != 'Y') && (term_code != 'y'))
- {
- /* clear out the prompt message first and then set the
- * flag to reset the cursor
- */
-
- clear_mess(main_win);
- cursor_flag++; /* reset the cursor */
- break; /* nope, don't do anything yet..... */
- }
- }
-
- /* execute the file commands for all of the files in the current
- * directory; informational messages will appear for each action
- * for each file
- */
-
- xecute(dirptr,dir_text,num_file);
- exec_flag++; /* set flag saying we just executed */
-
- /* just fall through here and do what we would normally do for
- * a REBUILD command; no sense in putting the code in two places,
- * now is there?
- */
-
- case(CONTROL_R): /**************************************/
- /* rebuild the directory */
- /**************************************/
-
- /* if we are really just rebuilding, free up any command
- * structures for the directory
- */
-
- if(!exec_flag)
- free_comm(dirptr,num_file);
-
- /* tell the user we are doing something so they don't worry */
-
- xmess("Rebuilding directory information......",0);
-
- /* decrement the recursion level before returning */
-
- --level;
-
- /* free the memory pools first */
-
- free_pool(first_pool);
- unlink_dir_ent(dir_ent_ptr);
-
- /* now free up the memory for the directory information */
-
- free((char *) dirptr);
-
- return(RECALL_PROC); /* force proc_dir() to be recalled */
-
- case('?'): /**************************************/
- /* Help */
- /**************************************/
-
- give_help(main_win);
- mess_flag++;
- cursor_flag++;
- break;
-
- case('D'): /**************************************/
- case('d'): /* Delete */
- /**************************************/
-
- /* first get the entry pointer for the file indicated */
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- mark_delete(entptr); /* mark file for deletion */
-
- temp = make_slot(slot_buf,entptr,&args,slot_width,text_flag);
-
- /* now write the file information to the screen in the right spot */
-
- put_slot(main_win,scr_row,scr_col+1,slot_buf,A_BOLD);
-
- if(args.auto_feed == TRUE)
- {
- /* move to the next logical file on the screen; basically, we are
- * just performing the same stuff we do for a down-arrow
- */
-
- temp = (short) nodes[node_row][node_col].down_row;
- node_col = (short) nodes[node_row][node_col].down_col;
- node_row = temp;
- scr_row = (int) nodes[node_row][node_col].row;
- scr_col = (int) nodes[node_row][node_col].column;
- }
-
- cursor_flag++;
- prev_ptr = entptr; /* save in case user wants to repeat */
- prev_command = DELETE;
- break;
-
- case('P'): /**************************************/
- case('p'): /* Protect */
- /**************************************/
-
- /* first get the entry pointer for the file indicated */
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- tag_file(main_win,scr_row,scr_col);
-
- /* get the new filename and mark the file to be renamed */
-
- temp = mark_protect(main_win,entptr,0,FALSE);
-
- if(temp != SUCCESS) /* wot happen? */
- {
- beep();
- info_mess("Invalid protection string");
- mess_flag++;
- }
- else
- {
- /* highlite the file slot */
-
- highlite(main_win,slot_buf,entptr,&args,scr_row,scr_col+1,
- slot_width,text_flag);
- prev_ptr = entptr; /* save in case user wants to repeat */
- prev_command = PROTECT;
- }
-
- erase_tag(main_win,scr_row,scr_col);
- cursor_flag++; /* reset the cursor down below */
- break;
-
- case('F'): /**************************************/
- case('f'): /* Finish */
- /**************************************/
-
-
- if(level == 1) /* are we at the top? */
- {
- /* beep and continue, ignoring the Finish command */
-
- beep();
- break; /* yes, we can't go up any more */
- }
-
- /* check for marked files first; if some are marked, ask the user
- * if Finishing is the right thing to do
- */
-
- if(check_marks(dirptr,num_file) == TRUE && term_code == 'f')
- {
- info_mess("There are commands in this directory. Execute them before finishing? [y] ");
-
- term_code = wgetch(main_win);
- clear_mess(main_win);
- cursor_flag++;
-
- if(term_code != 'N' && term_code != 'n')
- xecute(dirptr,dir_text,num_file);
- else
- free_comm(dirptr,num_file);
- }
-
- /* the user is finished with the current directory; free up the
- * memory that was allocated for the directory and just return;
- * whether we return to the mainline or to a previous call to
- * proc_dir() is no matter to us at this point
- */
-
- level--; /* decrement recursion level counter */
-
- /* free up the memory pools first */
-
- free_pool(first_pool);
-
- /* now free up the memory for the directory information */
-
- free((char *) dirptr);
-
- /* unlink the active directory node from the list */
-
- unlink_dir_ent(dir_ent_ptr);
-
- return(0); /* go back to where we were called */
-
- case('E'): /**************************************/
- case('e'): /* Edit */
- /**************************************/
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- if(entptr->type != DIRECTORY)
- {
- /* Editing a file; fine... */
-
- if(access(entptr->filename,R_OK) != 0)
- {
- beep();
- info_mess("Cannot open file");
- mess_flag++;
- }
- else
- {
- /* the file is not empty; go ahead and try to edit it */
-
- /* subtract the number of blocks for the file from the total
- * for the directory because the size of the file might be
- * different
- */
-
- num_block -= get_bnum(entptr->filename);
-
- status = edit(entptr->filename);
- touchwin(main_win);
- touchwin(spec_win);
- touchwin(stat_win);
- wrefresh(main_win);
- wrefresh(spec_win);
- wrefresh(stat_win);
- }
-
- if(status == FAILURE)
- {
- beep();
- info_mess("Cannot edit selected file");
- mess_flag++;
- }
-
- /* rebuild the file entry for the file to reflect the new info;
- * save the command pointer and re-attach it to the entry because
- * make_ent() will wipe it out
- */
-
- comm_ptr = entptr->command;
- make_ent(entptr,entptr->filename,&num_block);
- entptr->command = comm_ptr;
- status = make_slot(slot_buf,entptr,&args,slot_width,text_flag);
- put_slot(main_win,scr_row,scr_col+1,slot_buf,status);
-
- /* update the stat line */
-
- put_stat(stat_win,num_block,num_file);
- cursor_flag++;
- }
- else
- {
- beep();
- info_mess("Cannot edit a directory");
- mess_flag++;
- cursor_flag++;
- }
-
- break;
-
- case('I'): /**************************************/
- case('i'): /* Info */
- /**************************************/
-
- /* first get the entry pointer for the file indicated */
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- /* display all of the information about the file on the screen */
-
- if(info(entptr,&args) != SUCCESS)
- {
- beep();
- info_mess("Cannot obtain information for file");
- mess_flag++;
- }
-
- touchwin(main_win); /* to force it to be refreshed */
- wnoutrefresh(main_win);
- touchwin(stat_win);
- wnoutrefresh(stat_win);
- doupdate();
- cursor_flag++; /* reset the cursor */
-
- break;
-
- case('R'): /**************************************/
- case('r'): /* Rename */
- /**************************************/
-
- /* first get the entry pointer for the file indicated */
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- tag_file(main_win,scr_row,scr_col);
-
- /* get the new filename and mark the file to be renamed */
-
- temp = mark_copy_ren(main_win,entptr,RENAME,NULL,FALSE);
-
- if(temp != SUCCESS) /* wot happen? */
- {
- beep();
- info_mess("Error in trying to rename file");
- mess_flag++;
- }
- else
- {
- /* highlite the file slot */
-
- highlite(main_win,slot_buf,entptr,&args,scr_row,scr_col+1,
- slot_width,text_flag);
- prev_ptr = entptr; /* save in case user wants to repeat */
- prev_command = RENAME;
- }
-
- erase_tag(main_win,scr_row,scr_col);
- cursor_flag++; /* reset the cursor down below */
-
- break;
-
- case('C'): /**************************************/
- case('c'): /* Copy */
- /**************************************/
-
- /* first get the entry pointer for the file indicated */
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- if(entptr->type != DIRECTORY)
- {
- tag_file(main_win,scr_row,scr_col);
-
- /* get the new filename and mark the file to be copied */
-
- temp = mark_copy_ren(main_win,entptr,COPY,NULL,FALSE);
-
- if(temp != SUCCESS) /* wot happen? */
- {
- beep();
- info_mess("Error in trying to copy file");
- mess_flag++;
- }
- else
- {
- /* highlite the file slot */
-
- highlite(main_win,slot_buf,entptr,&args,scr_row,scr_col+1,
- slot_width,text_flag);
- prev_ptr = entptr; /* save in case user wants to repeat */
- prev_command = COPY;
- }
-
- erase_tag(main_win,scr_row,scr_col);
- }
- else
- {
- beep();
- info_mess("Copy is invalid for that file");
- mess_flag++;
- }
-
- cursor_flag++;
- wrefresh(main_win); /* make sure screen is up to date */
- break;
-
- case('T'): /**************************************/
- case('t'): /* Text */
- /**************************************/
-
- /* first save what file the cursor was pointing to */
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- if(!text_flag)
- {
- /* were text descriptors already turned on? */
-
- if(!args.text)
- {
- /* now see what we need to set the text global run-time
- * flag to (whether we should display text descriptors
- * or not
- */
-
- save_width = slot_width;
-
- if((slot_width + TEXT_MAX + 1) <= COLS)
- {
- /* Good news! The text descriptors will fit on the
- * screen; update the current slot width but leave the
- * global slot width alone
- */
-
- slot_width = slot_width + TEXT_MAX + 1;
- args.text = DISPLAY_TEXT;
- }
- else
- {
- /* no, the text descriptors will not fit on the screen;
- * but we want them read in from now on anyway
- */
-
- args.text = SLOT_OVF;
- }
- }
-
- /* text descriptors have NOT been read in for the current dir-
- * ectory; first we must see if the text descriptor file exists;
- * if it is there, we will use it; if not, we will ask if they
- * want to create one
- */
-
- text_flag = args.text;
-
- temp = read_text_des(dirptr,&curr_pool,&dir_text,pool_length,
- num_file);
-
- if(temp == NO_FILE)
- {
- /* the text descriptor file does not exist; ask the user if
- * it should be created
- */
-
- temp = create_text(main_win);
- }
-
- switch(temp) /* what happened with the file? */
- {
- case(NEW_FILE): /* new text descriptor file? */
-
- /* ask the user if the commands should be executed
- * before rebuilding things
- */
-
- if(check_marks(dirptr,num_file) == TRUE)
- {
- info_mess("Commands will be wiped out. eXecute them?\
- [y] ");
-
- term_code = wgetch(main_win);
- clear_mess(main_win);
-
- if(term_code != 'N' && term_code != 'n')
- {
- /* execute the stuff first */
-
- /* make sure we don't try to create a text descriptor
- * file before eXecuting the commands
- */
-
- xecute(dirptr,dir_text,num_file);
- }
- else
- free_comm(dirptr,num_file);
- }
-
- /* free up the memory pools first */
-
- free_pool(first_pool);
- unlink_dir_ent(dir_ent_ptr);
-
- /* now free up the memory for the directory info */
-
- free((char *) dirptr);
-
- --level; /* don't count this level anymore */
-
- /* return here and force the routine to be called
- * again; this makes the function epilogue (don't
- * you just love those programming language terms?)
- * do all of the work by allocating and initializing
- * all of the automatic variables; this is a neat
- * way to take advantage of the recursive structure
- * we have set up for ourselves because all of the
- * code to reinitialize a directory does not have
- * to be duplicated
- */
-
- return(RECALL_PROC);
-
- case(SUCCESS): /* text descriptors read in ok? */
-
- /* the text descriptors were read in ok; now rebuild the
- * nodes for the directory and remake the screen
- */
-
- text_flag = args.text;
- set_screen(&num_screen,&scr_file,num_file,slot_width,
- node_row_max,&num_col);
- num_slot = scr_file;
- set_nodes(nodes,node_row_max,&scr_file,num_screen,
- curr_screen,num_file,slot_width,num_col);
- put_spec(spec_win,dir_name,home_dir,home_len,num_screen);
- put_text(spec_win,dir_text);
-
- /* we have to look for the file that was being point to
- * when the Text command was done and determine what page
- * it is on; we might have to change the current page and
- * everything just to put the cursor back in the right spot
- */
-
- screen_reset(nodes,dirptr,entptr->filename,&node_row,
- &node_col,&scr_file,&curr_screen,
- node_row_max,num_file,num_slot,num_screen,
- slot_width,num_row,num_col);
-
- /* put the page number on the screen again, just in case
- * it might have changed
- */
-
- put_pagnum(spec_win,curr_screen,num_screen);
-
- /* clear the screen to make sure we don't have any
- * any garbage left over when we put the text des-
- * criptors on the screen
- */
-
- werase(main_win);
-
- /* remake the virtual display now that it is clear */
-
- make_screen(main_win,nodes,dirptr,&args,curr_screen,
- node_row_max,node_col_max,scr_file,
- num_slot,slot_width,text_flag);
-
- /* reset the screen cursor values */
-
- scr_row = (int) nodes[node_row][node_col].row;
- scr_col = (int) nodes[node_row][node_col].column;
-
- /* make the sure pool length is set properly */
-
- pool_length = (num_file + 1) * ent_factor;
- cursor_flag++; /* reset the cursor */
- break;
-
- case(BAD_FILE):
-
- /* bad format for text descriptor file */
-
- info_mess("Invalid format for text descriptor file");
- beep();
-
- /* reset the slot width */
-
- slot_width = save_width;
- text_flag = 0;
- mess_flag++;
- break;
-
- case(CANT_OPEN):
-
- beep();
- info_mess("Cannot open text descriptor file");
-
- /* reset the slot width */
-
- slot_width = save_width;
- text_flag = 0;
- mess_flag++;
- break;
-
- case(DONT_CREATE):
- default:
-
- /* reset the slot width */
-
- slot_width = save_width;
- text_flag = 0;
- break;
- }
- }
- else
- {
- /* the text descriptors have already been read in; get the
- * text descriptor for the selected file and store it in a
- * memory pool
- */
-
- /* first get the entry pointer for the file indicated */
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- tag_file(main_win,scr_row,scr_col);
-
- /* get the text descriptor and mark the file */
-
- temp = mark_text(main_win,entptr,NULL,FALSE);
-
- if(temp != SUCCESS) /* did everything go ok? */
- {
- beep();
- info_mess("Invalid text descriptor");
- mess_flag++;
- }
- else
- {
- /* highlite the file slot */
-
- highlite(main_win,slot_buf,entptr,&args,scr_row,scr_col+1,
- slot_width,text_flag);
- prev_ptr = entptr; /* save in case user wants to repeat */
- prev_command = TEXT;
- }
-
- erase_tag(main_win,scr_row,scr_col);
- }
-
- cursor_flag++; /* reset the cursor down below */
- break;
-
- case('.'): /**************************************/
- /* Repeat */
- /**************************************/
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- if(prev_ptr != NULL)
- {
- mark_repeat(main_win,entptr,prev_ptr,prev_command);
- highlite(main_win,slot_buf,entptr,&args,scr_row,scr_col+1,
- slot_width,text_flag);
- }
- else
- {
- beep();
- info_mess("No previous command");
- mess_flag++;
- }
-
- cursor_flag++;
- break;
-
- case('Q'): /**************************************/
- case('q'): /* Quit */
- /**************************************/
-
- /* check for marked files first; if some are marked, ask the user
- * if Quitting is the right thing to do
- */
-
- for(temp = 0,status = FALSE; temp < level && status == FALSE;
- temp++)
- status = check_marks(dirmem[temp].ptr,dirmem[temp].num_file);
-
- if(status == TRUE && term_code == 'q')
- {
- info_mess("There are commands in this directory. Execute them before quitting? [y] ");
-
- term_code = wgetch(main_win);
- clear_mess(main_win);
- cursor_flag++;
-
- if(term_code != 'N' && term_code != 'n')
- xecute(dirptr,dir_text,num_file);
- }
-
- clean_up();
- exit(0); /* now we can exit */
-
- break;
-
- case('!'): /**************************************/
- /* Shell escape */
- /**************************************/
-
- /* clear out the options line so we can jump to the shell
- * a little cleaner
- */
-
- wmove(stat_win,STAT_WINDOW_ROWS - 1,0);
- wclrtoeol(stat_win);
- wrefresh(stat_win);
-
- if(spawn() == FAILURE) /* fork the shell */
- info_mess("Cannot fork");
-
- /* refresh the screen */
-
- put_options(stat_win);
- touchwin(main_win);
- touchwin(spec_win);
- wrefresh(main_win);
- wrefresh(spec_win);
- wrefresh(stat_win);
- cursor_flag++;
- break;
-
- case(CONTROL_W): /**************************************/
- case(CONTROL_L): /* repaint screen */
- /**************************************/
-
- touchwin(spec_win);
- touchwin(main_win);
- touchwin(stat_win);
- wnoutrefresh(spec_win);
- wnoutrefresh(main_win);
- wnoutrefresh(stat_win);
- doupdate();
- cursor_flag++;
- break;
-
- case(CONTROL_G): /**************************************/
- /* Goto */
- /**************************************/
-
- /* ask for a new screen number */
-
- temp = get_scr_num(main_win,curr_screen,num_screen);
-
- if(temp == BAD_SCREEN_NO) /* was it a bad screen number? */
- {
- beep();
- info_mess("Invalid page number");
- mess_flag++;
- }
- else
- {
- /* was the page number specified different from the
- * current one? If not, don't do anything
- */
-
- if(curr_screen != temp)
- {
- /* the page number specified was valid; set up the new page */
-
- curr_screen = temp; /* store the new current screen */
-
- /* update the screen nodes array */
-
- set_nodes(nodes,node_row_max,&scr_file,num_screen,
- curr_screen,num_file,slot_width,num_col);
-
- /* update the page number in the corner */
-
- put_pagnum(spec_win,curr_screen,num_screen);
-
- /* remake the screen to reflect the new screen specified */
-
- make_screen(main_win,nodes,dirptr,&args,curr_screen,
- node_row_max,node_col_max,scr_file,num_slot,
- slot_width,text_flag);
-
- /* reset the screen and node pointers */
-
- node_row = 0;
- node_col = 0;
- scr_row = (int) nodes[0][0].row;
- scr_col = (int) nodes[0][0].column;
- }
- }
-
- cursor_flag++; /* set the cursor */
- break;
-
- case('o'): /**************************************/
- /* Owner */
- /**************************************/
-
- #if !defined(SYSV) || defined(sun)
- if(geteuid() != 0)
- {
- beep();
- info_mess("Only the superuser can use the Owner command");
- mess_flag++;
- cursor_flag++;
- break;
- }
- #endif
-
- /* change the owner of a file */
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- tag_file(main_win,scr_row,scr_col);
-
- temp = mark_owner(main_win,entptr,0,FALSE);
-
- if(temp == SUCCESS)
- {
- /* highlite the file slot */
-
- highlite(main_win,slot_buf,entptr,&args,scr_row,scr_col+1,
- slot_width,text_flag);
- prev_ptr = entptr; /* save in case user wants to repeat */
- prev_command = OWNER;
- }
- else if(temp == BAD_OWNER)
- {
- info_mess("Invalid owner specified");
- beep();
- mess_flag++;
- }
-
- erase_tag(main_win,scr_row,scr_col);
- cursor_flag++; /* reset the cursor down below */
- break;
-
-
- case('G'): /**************************************/
- case('g'): /* Group */
- /**************************************/
-
- /* change the group of a file */
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- tag_file(main_win,scr_row,scr_col);
-
- temp = mark_group(main_win,entptr,0,FALSE);
-
- if(temp == SUCCESS)
- {
- /* highlite the file slot */
-
- highlite(main_win,slot_buf,entptr,&args,scr_row,scr_col+1,
- slot_width,text_flag);
- prev_ptr = entptr; /* save in case user wants to repeat */
- prev_command = GROUP;
- }
- else if(temp == BAD_GROUP)
- {
- info_mess("Invalid group specified");
- beep();
- mess_flag++;
- }
-
- erase_tag(main_win,scr_row,scr_col);
- cursor_flag++; /* reset the cursor down below */
- break;
-
- case('O'): /**************************************/
- /* Options */
- /**************************************/
-
- /* first get the entry pointer for the current file */
-
- entptr = dirptr + ((curr_screen - 1) * (num_row * num_col)) +
- (node_col * num_row) + node_row;
-
- temp = config_options(&args);
-
- /* reinitialize the global factors */
-
- set_args(&args,&def_slot_wid,&ent_factor);
-
- /* slot width has probably changed */
-
- slot_width = def_slot_wid;
-
- if(temp & REBUILD_DIRECTORY)
- {
- /* ask the user if the commands should be executed
- * before rebuilding things
- */
-
- if(check_marks(dirptr,num_file) == TRUE)
- {
- touchwin(main_win);
- wnoutrefresh(main_win);
- doupdate();
- info_mess("Commands will be wiped out. eXecute them? [y] ");
- term_code = wgetch(main_win);
- clear_mess(main_win);
-
- if(term_code != 'N' && term_code != 'n')
- {
- /* execute the stuff first */
-
- xecute(dirptr,dir_text,num_file);
- }
- else
- free_comm(dirptr,num_file);
- }
-
- /* refresh the stat window because we overwrote it */
-
- touchwin(stat_win);
- wrefresh(stat_win);
-
- /* free up the memory pools first */
-
- free_pool(first_pool);
- unlink_dir_ent(dir_ent_ptr);
-
- /* now free up the memory for the directory info */
-
- free((char *) dirptr);
-
- --level; /* don't count this level anymore */
-
- return(RECALL_PROC); /* recall proc_dir() to rebuild */
- }
-
- if(temp & REBUILD_SCREEN)
- {
- if(temp & REBUILD_WITH_FILEMARKS)
- {
- get_filemarks(dirptr,num_file);
- filemarks_flag = args.filemarks;
- }
-
- if(temp & REBUILD_WITH_SORT)
- {
- tptr = entptr->filename;
- sort_files(num_file - 1,args.sort);
- sort_flag = args.sort;
- }
-
- if(text_flag && !args.text)
- {
- /* text descriptors were turned off; make sure that we
- * wipe out any directory text descriptor
- */
-
- put_text(spec_win,NULL);
- text_flag = 0;
- }
-
- get_text(&args,dirptr,&curr_pool,&dir_text,&mess_flag,
- &slot_width,&text_flag,pool_length,num_file);
-
- /* reinitialize the screen parameters */
-
- set_screen(&num_screen,&scr_file,num_file,slot_width,
- node_row_max,&num_col);
-
- num_slot = scr_file; /* save number of slots per screen */
-
- /* search for the filename of the file we were on so we can
- * go back to it; we might as well do this every time, es-
- * pecially since the search for it is fast (we're only
- * comparing pointer values instead of strings
- */
-
- temp = (short) file_ptr_search(dirptr,tptr,num_file);
-
- if(temp >= 0)
- {
- /* file was found; recompute the node indexes so that we
- * can change the cursor on the screen
- */
-
- new_screen = (temp / num_slot) + 1;
-
- /* get us to the current screen */
-
- temp2 = temp - ((new_screen - 1) * num_slot);
- node_col = temp2 / num_row;
- node_row = temp % num_row;
- curr_screen = new_screen;
- }
-
- /* create the new screen by first putting the new page
- * number in the upper-right and then rebuilding the
- * main display
- */
-
- put_pagnum(spec_win,curr_screen,num_screen);
-
- set_nodes(nodes,node_row_max,&scr_file,num_screen,new_screen,
- num_file,slot_width,num_col);
-
- if(args.text) /* write text descrip for directory? */
- put_text(spec_win,dir_text);
-
- werase(main_win); /* make sure we start clean */
-
- /* display the current screen */
-
- make_screen(main_win,nodes,dirptr,&args,curr_screen,
- node_row_max,node_col_max,scr_file,num_slot,
- slot_width,text_flag);
-
- /* get the cursor coordinates so we can reset it */
-
- scr_row = (int) nodes[node_row][node_col].row;
- scr_col = (int) nodes[node_row][node_col].column;
- }
-
- put_stat(stat_win,num_block,num_file);
- put_options(stat_win);
- touchwin(stat_win);
- touchwin(main_win);
- wnoutrefresh(main_win);
- wnoutrefresh(stat_win);
- doupdate();
- cursor_flag++;
- break;
-
- case(0): /**************************************/
- /* something weird :-C */
- /**************************************/
- break;
-
- default: /**************************************/
- /* all others */
- /**************************************/
-
- /* scream at the user (ring the bell) */
-
- beep();
- break;
-
- } /* switch(term_code) */
-
- /* do we need reposition the cursor? */
-
- if(cursor_flag)
- {
- /* set the cursor where it should be */
-
- wmove(main_win,scr_row,scr_col);
- wrefresh(main_win); /* make sure screen is up to date */
- cursor_flag = 0; /* clear the cursor set flag */
- }
-
- } /* for(;;) */ /* end of main processing loop */
-
- } /*** proc_dir ***/
-
- /*******************************************************************************
- ********************************************************************************
-
- Function: find_dir
-
- Purpose: Search for a directory info node in the link list. If one
- is found, it means that the directory is currently active.
-
- Global variables:
-
- Name Examine/Modify/Use/Read/Write
- ---- -----------------------------
- none
-
- Return Codes:
-
- Code Reason
- ---- ------
- none
-
- ********************************************************************************
- *******************************************************************************/
-
- static DIR_PTR *find_dir(head,tail,dir_name)
- /******* FORMAL PARAMETERS *******/
- DIR_PTR *head, /* pointer to head of dir info nodes */
- *tail; /* pointer to end of dir info nodes */
- char *dir_name; /* directory name to search for */
-
- { /*** find_dir ***/
-
- head = head->next;
-
- while(head != tail && strcmp(head->dir_name,dir_name) != 0)
- head = head->next;
-
- if(head == tail)
- return(NULL);
-
- return(head);
-
- } /*** find_dir ***/
-
- /*******************************************************************************
- ********************************************************************************
-
- Function: link_dir_ent
-
- Purpose: Link the info for the current directory into the active
- directory linked list.
-
- Global variables:
-
- Name Examine/Modify/Use/Read/Write
- ---- -----------------------------
- none
-
- Return Codes:
-
- Code Reason
- ---- ------
- temp_ptr pointer to new node
- NULL couldn't get memory for node
-
- ********************************************************************************
- *******************************************************************************/
-
- static DIR_PTR *link_dir_ent(dir_ent_head,dir_ent_tail,dirptr,dir_name,
- first_pool,curr_pool,pool_length,stat_time,
- num_file)
- /******* FORMAL PARAMETERS *******/
- DIR_PTR *dir_ent_head, /* head of directory chain list */
- *dir_ent_tail; /* tail of directory chain list */
- ENT_DEF *dirptr; /* pointer to directory information */
- char *dir_name; /* name of current directory */
- POOL_DEF *first_pool, /* first memory pool for directory */
- *curr_pool; /* current memory pool */
- size_t pool_length; /* length to allocate for new pool */
- time_t stat_time; /* time directory was last modified */
- short num_file; /* number of files in directory */
-
- { /*** link_dir_ent ***/
- /******** LOCAL VARIABLES ********/
- DIR_PTR *new_ptr, /* new node pointer */ *temp_ptr; /* previous node in list */
-
-
- /* allocate the node first */
-
- new_ptr = (DIR_PTR *) malloc(sizeof(DIR_PTR));
-
- if(new_ptr == NULL)
- return(NULL); /* couldn't get the memory */
-
- /* got the memory for the node; link it in */
-
- temp_ptr = dir_ent_tail->prev; /* save where we were */
- dir_ent_tail->prev = new_ptr;
- new_ptr->next = dir_ent_tail;
- temp_ptr->next = new_ptr;
- new_ptr->prev = temp_ptr;
-
- new_ptr->dirptr = dirptr;
- new_ptr->dir_name = dir_name;
- new_ptr->first_pool = first_pool;
- new_ptr->curr_pool = curr_pool;
- new_ptr->pool_length = pool_length;
- new_ptr->num_file = num_file;
- new_ptr->stat_time = stat_time;
- new_ptr->count = 1; /* first time here */
-
- return(new_ptr); /* return pointer to new node */
-
- } /*** link_dir_ent ***/
-
- /*******************************************************************************
- ********************************************************************************
-
- Function: unlink_dir_ent
-
- Purpose: Unlink the info for the current directory from the active
- directory linked list.
-
- Global variables:
-
- Name Examine/Modify/Use/Read/Write
- ---- -----------------------------
- none
-
- Return Codes:
-
- Code Reason
- ---- ------
- none
-
- ********************************************************************************
- *******************************************************************************/
-
- static void unlink_dir_ent(current)
- /******* FORMAL PARAMETERS *******/
- DIR_PTR *current; /* active directory list node */
-
- { /*** unlink_dir_ent ***/
- /******** LOCAL VARIABLES ********/
- DIR_PTR *temp; /* temporary node pointer */
-
-
- if(current->count > 1) /* can we unlink it? */
- {
- current->count -= 1;
- return; /* nope, still active */
- }
-
- temp = current->prev;
- temp->next = current->next;
- temp = current->next;
- temp->prev = current->prev;
- free(current->dir_name); /* free up directory name string */
- free(current); /* free up the node itself */
-
- return;
-
- } /*** unlink_dir_ent ***/
-
- /*******************************************************************************
- ********************************************************************************
-
- Function: get_year
-
- Purpose: Obtain and return the value for the current year.
-
- Global variables:
-
- Name Examine/Modify/Use/Read/Write
- ---- -----------------------------
- none
-
- Return Codes:
-
- Code Reason
- ---- ------
- tstr->tm_year current year value
-
- ********************************************************************************
- *******************************************************************************/
-
- static int get_year()
-
- { /*** get_year ***/
- /******** LOCAL VARIABLES ********/
- long clock; /* binary time value */
- struct tm *tstr; /* time structure pointer */
-
-
- clock = (long) time((long *) 0); /* get current time */
- tstr = localtime(&clock); /* fill in the time structure */
- return(tstr->tm_year); /* return the current year value */
-
- } /*** get_year ***/
-