home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-05-13 | 72.1 KB | 2,560 lines |
- Newsgroups: comp.sources.unix
- From: peirce@gw.wmich.edu (Leonard J. Peirce)
- Subject: v26i051: maint - full-screen file and directory maintenance tool, Part03/07
- Sender: unix-sources-moderator@pa.dec.com
- Approved: vixie@pa.dec.com
-
- Submitted-By: peirce@gw.wmich.edu (Leonard J. Peirce)
- Posting-Number: Volume 26, Issue 51
- Archive-Name: maint/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 7)."
- # Contents: mark.c text.c xecute.c
- # Wrapped by vixie@cognition.pa.dec.com on Thu May 14 23:05:42 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'mark.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mark.c'\"
- else
- echo shar: Extracting \"'mark.c'\" \(26500 characters\)
- sed "s/^X//" >'mark.c' <<'END_OF_FILE'
- X/******************************************************************************
- X*******************************************************************************
- X
- X Site: Western Michigan University Academic Computer Center
- X
- X System: Directory/File System Maintenance
- X
- X Program: maint
- X
- X Version=01 Level=00 01/24/92 Leonard J. Peirce
- X
- X Purpose: Associate commands with individual file entries or cancel
- X all commands for a file.
- X
- X Arguments: See individual routines
- X
- X External variables: See individual routines
- X
- X External functions:
- X
- X Defined: mark_text, mark_delete, mark_copy_ren, mark_protect,
- X mark_group, mark_owner, mark_rename, mark_cancel,
- X mark_repeat
- X
- X Called: new_comm, add_filetype, prot_str_to_val, prompt_getstr,
- X free_comstr, squeeze_str
- X
- X Files accessed: See individual routines
- X
- X Return codes: See individual routines
- X
- X Compiling instructions: See Makefile
- X
- X Linking instructions: See Makefile
- X
- X Other information: (C) Copyright 1992, Leonard J. Peirce
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- X/******************************************************************************/
- X/* */
- X/* # I N C L U D E F I L E S */
- X/* */
- X/******************************************************************************/
- X
- X#include <ctype.h>
- X#include <math.h>
- X#include <malloc.h>
- X#ifdef ultrix
- X#include <cursesX.h>
- X#else
- X#include <curses.h>
- X#endif
- X#include <string.h>
- X#include <grp.h>
- X#include <pwd.h>
- X#include "maint.h"
- X
- X/******************************************************************************/
- X/* */
- X/* # D E F I N E S */
- X/* */
- X/******************************************************************************/
- X
- X/******************************************************************************/
- X/* */
- X/* S T R U C T U R E S , U N I O N S , T Y P E D E F S */
- X/* */
- X/******************************************************************************/
- X
- X/******************************************************************************/
- X/* */
- X/* 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 */
- X/* */
- X/******************************************************************************/
- X
- extern int main_rows;
- X
- X#ifndef ultrix
- extern void free();
- X#endif
- X
- extern COM_DEF *new_comm();
- X
- extern u_short add_filetype();
- X
- extern short prot_str_to_val();
- X
- extern void prompt_getstr(),
- X squeeze_str(),
- X free_comstr();
- X
- X int mark_text(),
- X mark_delete(),
- X mark_copy_ren(),
- X mark_protect(),
- X mark_group(),
- X mark_owner(),
- X mark_rename(),
- X mark_repeat();
- X
- X void mark_cancel();
- X
- X/******************************************************************************/
- X/* */
- X/* 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 */
- X/* */
- X/******************************************************************************/
- X
- static short prot_abs_to_val();
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: mark_delete
- X
- X Purpose: The selected file is to be deleted; allocate memory for the
- X command structure (if necessary), link it to the entry, and
- X set up the command structure so that the file can be deleted.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X 0 completed successfully
- X -1 problems allocating memory
- X
- X Termination Codes:
- X
- X Code Reason
- X ---- ------
- X SUCCESS
- X FAILURE
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- int mark_delete(ent)
- X /******* FORMAL PARAMETERS *******/
- register ENT_DEF *ent; /* entry for file to be deleted */
- X
- X{ /*** mark_delete ***/
- X /******** LOCAL VARIABLES ********/
- register COM_DEF *tptr; /* temporary command structure ptr */
- X
- X
- X /* do we need a command structure or does the file already have one? */
- X
- X if(ent->command == NULL)
- X {
- X /* we need command structure; allocate it and link it to the file entry */
- X
- X tptr = new_comm();
- X
- X if(tptr == NULL)
- X return(FAILURE); /* problems allocating memory */
- X
- X ent->command = tptr; /* link it to the file entry */
- X }
- X else
- X tptr = ent->command; /* else use the one already there */
- X
- X tptr->comm_del = 1;
- X
- X /* deallocate all of the memory that might have been used for things
- X * like renaming the file and for a text descriptor
- X */
- X
- X if(tptr->ren_name != NULL) /* need to deallocate rename name? */
- X {
- X
- X free(tptr->ren_name);
- X tptr->comm_ren = 0; /* make sure to shut of renaming */
- X tptr->ren_name = NULL; /* reset the rename name stuff */
- X tptr->ren_len = 0;
- X }
- X
- X if(tptr->text != NULL) /* need to deallocate text descrip? */
- X {
- X free(tptr->text);
- X tptr->comm_text = 0; /* make sure to shut off text descrip */
- X tptr->text = NULL; /* reset the text descriptor stuff */
- X tptr->text_len = 0;
- X }
- X
- X return(SUCCESS); /* no problem..... */
- X
- X} /*** mark_delete ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: mark_copy_ren
- X
- X Purpose: The selected file is to be copied or renamed; allocate the
- X memory for the command structure (if necessary), link it to
- X the file entry, and set the command in the command structure.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X 0 completed successfully
- X -1 problems allocating memory
- X
- X Termination Codes:
- X
- X Code Reason
- X ---- ------
- X SUCCESS
- X CANT_ALLOCATE cannot allocate necessary memory
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- int mark_copy_ren(window,ent,command,prev_str,repeat)
- X /******* FORMAL PARAMETERS *******/
- X WINDOW *window; /* where to read/write */
- register ENT_DEF *ent; /* entry for file to be deleted */
- X u_short command; /* either RENAME or COPY */
- X char *prev_str; /* string to use from mark_repeat() */
- X u_short repeat; /* set if called from mark_repeat() */
- X
- X{ /*** mark_copy_ren ***/
- X /******** LOCAL VARIABLES ********/
- register COM_DEF *tptr; /* temporary command structure ptr */
- X char *dest_ptr; /* temporary character pointer */
- X int length; /* length of string read in */
- X char buf[FULL_SPEC_MAX+1], /* array for new filename */
- X prompt[PROMPT_MAX+1]; /* prompt array */
- X
- X
- X if(!repeat)
- X {
- X buf[0] = '\0'; /* reset the buffer */
- X
- X /* set up the prompt for the filename */
- X
- X if(command == COPY)
- X strcpy(prompt,"Copy to: ");
- X else
- X strcpy(prompt,"Rename to: ");
- X
- X /* read in the file spec */
- X
- X prompt_getstr(window,prompt,buf,main_rows,FULL_SPEC_MAX);
- X
- X /* was anything specified for the filename? */
- X
- X if(*buf == '\0')
- X return(SUCCESS);
- X }
- X else
- X strcpy(buf,prev_str); /* use string from mark_repeat() */
- X
- X length = strlen(buf);
- X
- X /* ok, we have a filename; now determine if we need to allocate a command
- X * structure for this file or if one already exists from a previous command
- X */
- X
- X if(ent->command == NULL)
- X {
- X /* we need command structure; allocate it and link it to the file entry */
- X
- X tptr = new_comm();
- X
- X if(tptr == NULL)
- X exit(CANT_ALLOCATE); /* problems allocating memory */
- X
- X ent->command = tptr; /* link it to the file entry */
- X }
- X else
- X {
- X tptr = ent->command; /* else use the one already there */
- X }
- X
- X /* is there already enough room to put the new name in a memory pool? if
- X * there is, just reuse the memory we already have; otherwise, free up
- X * the memory (if there is any) and allocate some to hold the new name
- X */
- X
- X if(command == COPY)
- X {
- X if(length > tptr->copy_len)
- X {
- X /* nope, we need more memory; first free the old memory if there
- X * was any
- X */
- X
- X if(tptr->copy_len != 0)
- X free(tptr->copy_name);
- X
- X /* now allocate some new memory to hold the longer filename
- X * AND the nul character
- X */
- X
- X tptr->copy_name = (char *) malloc((u_int) (length + 1));
- X
- X if(tptr->copy_name == NULL)
- X {
- X exit(CANT_ALLOCATE);
- X }
- X
- X tptr->copy_len = length; /* save the length of the memory */
- X }
- X
- X dest_ptr = tptr->copy_name; /* get where to copy the filename to */
- X tptr->comm_copy = 1; /* set the command in the structure */
- X }
- X else
- X {
- X if(length > tptr->ren_len)
- X {
- X /* nope, we need more memory; first free the old memory if there
- X * was any
- X */
- X
- X if(tptr->ren_len != 0)
- X free(tptr->ren_name);
- X
- X /* now allocate some new memory to hold the longer filename
- X * AND the nul character
- X */
- X
- X tptr->ren_name = (char *) malloc((u_int) (length + 1));
- X
- X if(tptr->ren_name == NULL)
- X exit(CANT_ALLOCATE);
- X
- X tptr->ren_len = length; /* save the length of the memory */
- X }
- X
- X dest_ptr = tptr->ren_name; /* get where to copy the filename to */
- X tptr->comm_ren = TRUE; /* set the command in the structure */
- X tptr->comm_del = FALSE; /* rename implies no delete */
- X }
- X
- X strcpy(dest_ptr,buf); /* copy it to the right place */
- X
- X return(SUCCESS);
- X
- X} /*** mark_copy_ren ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: mark_text
- X
- X Purpose: The selected file is to get a text descriptor; allocate the
- X memory for the command structure (if necessary), link it to
- X the file entry, and set the command in the command structure.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X SUCCESS
- X FAILURE
- X
- X Termination Codes:
- X
- X Code Reason
- X ---- ------
- X SUCCESS
- X FAILURE
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- int mark_text(window,ent,text,repeat)
- X /******* FORMAL PARAMETERS *******/
- X WINDOW *window; /* where to read/write */
- register ENT_DEF *ent; /* entry for file to be deleted */
- X char *text; /* from mark_repeat */
- X u_short repeat; /* set if called by mark_repeat() */
- X
- X{ /*** mark_text ***/
- X /******** LOCAL VARIABLES ********/
- register COM_DEF *tptr; /* temporary command structure ptr */
- X int length; /* length of string read in */
- X char buf[TEXT_MAX+1]; /* array for text descriptor */
- X
- X
- X buf[0] = '\0'; /* reset the buffer */
- X
- X /* first put the character that marks the maximum number of characters
- X * that can be specified for the text descriptor
- X */
- X
- X if(!repeat)
- X prompt_getstr(window,"Text descriptor: ",buf,main_rows,TEXT_MAX);
- X else
- X strcpy(buf,text); /* use text descrip from mark_repeat */
- X
- X length = strlen(buf); /* make sure it's not too long */
- X
- X /* ok, we have the text descriptor; determine if we need to allocate a
- X * command structure for this file or if one already exists from a
- X * previous command
- X */
- X
- X if(ent->command == NULL)
- X {
- X /* we need command structure; allocate it and link it to the file entry */
- X
- X tptr = new_comm();
- X
- X if(tptr == NULL)
- X return(FAILURE); /* problems allocating memory */
- X
- X ent->command = tptr; /* link it to the file entry */
- X }
- X else
- X tptr = ent->command; /* else use the one already there */
- X
- X /* is there already enough room to store the text descriptor?
- X * if there is, just reuse the memory we already have; otherwise,
- X * allocate some new memory
- X */
- X
- X if(length > tptr->text_len)
- X {
- X /* we need more memory; first free up any old memory if there was any */
- X
- X if(tptr->text_len != 0)
- X free(tptr->text);
- X
- X /* allocate some memory to hold the text descriptor AND the null char */
- X
- X tptr->text = (char *) malloc((u_int) (length + 1));
- X
- X if(tptr->text == NULL)
- X exit(CANT_ALLOCATE);
- X
- X tptr->text_len = length; /* we have a new length */
- X }
- X
- X if(length)
- X strcpy(tptr->text,buf); /* copy it to its resting place */
- X else
- X tptr->text = NULL;
- X
- X /* set the command in the command structure */
- X
- X tptr->comm_text = TRUE;
- X tptr->comm_del = FALSE; /* text descriptor implies no delete */
- X
- X return(SUCCESS);
- X
- X} /*** mark_text ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: mark_protect
- X
- X Purpose: The selected file is to be reprotected; allocate the memory
- X for the command structure (if necessary), link it to the file
- X entry, and set the command in the command structure.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X main_rows X
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X SUCCESS
- X FAILURE
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- int mark_protect(window,ent,prot,repeat)
- X /******* FORMAL PARAMETERS *******/
- X WINDOW *window; /* where to read/write */
- register ENT_DEF *ent; /* entry for file to be deleted */
- X u_short prot, /* from mark_repeat() */
- X repeat; /* set if called from mark_repeat() */
- X
- X{ /*** mark_protect ***/
- X /******** LOCAL VARIABLES ********/
- register COM_DEF *tptr; /* temporary command structure ptr */
- X u_short prot_val; /* temporary protection value */
- X char buf[PROT_INP_MAX+1]; /* array for protection string */
- X
- X
- X if(!repeat)
- X {
- X buf[0] = '\0'; /* initialize input buffer */
- X
- X /* prompt for and read in the protection string */
- X
- X prompt_getstr(window,"Protection: ",buf,main_rows,PROT_INP_MAX);
- X
- X /* if nothing was specified for the protection string, just return from
- X * right here
- X */
- X
- X if(*buf == '\0')
- X return(SUCCESS);
- X
- X squeeze_str(buf); /* squeeze the blanks out */
- X
- X /* now determine if the protection string specified is valid */
- X
- X if(prot_str_to_val(buf,&prot_val) == FAILURE)
- X {
- X /* maybe it's an absolute number; try to convert it */
- X
- X if(prot_abs_to_val(buf,&prot_val) == FAILURE)
- X return(FAILURE); /* invalid protection string */
- X }
- X }
- X else
- X prot_val = prot; /* use value from mark_repeat() */
- X
- X /* at this point, the protection string has been edited and is considered
- X * valid; get the integer value for the protection string and store it in
- X * in the command structure; first, do we need a command structure or does
- X * the file have one from a previous command?
- X */
- X
- X if(ent->command == NULL)
- X {
- X /* we need command structure; allocate it and link it to the file entry */
- X
- X tptr = new_comm();
- X
- X if(tptr == NULL)
- X return(-1); /* problems allocating memory */
- X
- X ent->command = tptr; /* link it to the file entry */
- X }
- X else
- X tptr = ent->command; /* else use the one already there */
- X
- X tptr->comm_prot = 1; /* set the command in the structure */
- X tptr->prot = add_filetype(ent->type,prot_val);
- X tptr->comm_del = 0; /* protection implies no delete */
- X
- X return(SUCCESS); /* fine......... */
- X
- X} /*** mark_protect ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: mark_cancel
- X
- X Purpose: Cancel all commands for the specified file entry and deallocate
- X the command structure for the file.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X 0 completed successfully
- X -1 problems allocating memory
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- void mark_cancel(ent)
- X /******* FORMAL PARAMETERS *******/
- X ENT_DEF *ent; /* file entry pointer */
- X
- X{ /*** mark_cancel ***/
- X
- X
- X if(ent->command != NULL)
- X {
- X /* first free up any memory that might be holding character strings */
- X
- X free_comstr(ent->command);
- X
- X ent->command = NULL; /* no more structure for file entry */
- X }
- X
- X return;
- X
- X} /*** mark_cancel ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: mark_repeat
- X
- X Purpose: Repeat the last command on the current file.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X SUCCESS
- X FAILURE
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- int mark_repeat(window,ent,prev_ptr,command)
- X /******* FORMAL PARAMETERS *******/
- X WINDOW *window; /* needed to pass along */
- X ENT_DEF *ent, /* what is to be marked */
- X *prev_ptr; /* where to find previous mark */
- X u_short command; /* command to be used */
- X
- X{ /*** mark_repeat ***/
- X /******** LOCAL VARIABLES ********/
- X COM_DEF *comm_ptr; /* previous entry's commands */
- X int retval; /* return value */
- X
- X
- X comm_ptr = prev_ptr->command;
- X
- X switch(command)
- X {
- X case(DELETE):
- X
- X retval = mark_delete(ent);
- X break;
- X
- X case(PROTECT):
- X
- X retval = mark_protect(window,ent,comm_ptr->prot,TRUE);
- X break;
- X
- X case(RENAME):
- X
- X retval = mark_copy_ren(window,ent,RENAME,comm_ptr->ren_name,TRUE);
- X break;
- X
- X case(COPY):
- X
- X retval = mark_copy_ren(window,ent,COPY,comm_ptr->copy_name,TRUE);
- X break;
- X
- X case(OWNER):
- X
- X retval = mark_owner(window,ent,comm_ptr->owner,TRUE);
- X break;
- X
- X case(GROUP):
- X
- X retval = mark_group(window,ent,comm_ptr->group,TRUE);
- X break;
- X
- X case(TEXT):
- X
- X retval = mark_text(window,ent,comm_ptr->text,TRUE);
- X break;
- X
- X default:
- X break;
- X }
- X
- X return(retval);
- X
- X} /*** mark_repeat ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: mark_group
- X
- X Purpose: Prompt for the new group of the file and look it up in the
- X group file. If it doesn't exist, just use the numeric version.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X main_rows X
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X SUCCESS
- X FAILURE
- X BAD_GROUP invalid group specified
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- int mark_group(window,ent,group,repeat)
- X /******* FORMAL PARAMETERS *******/
- X WINDOW *window; /* where to read/write */
- X ENT_DEF *ent; /* file entry pointer */
- X gid_t group; /* from mark_repeat() */
- X u_short repeat; /* set if called by mark_repeat() */
- X
- X{ /*** mark_group ***/
- X /******** LOCAL VARIABLES ********/
- struct group *gid_ptr; /* from getgrnam() */
- X COM_DEF *tptr; /* temporary pointer */
- X char *tptr2; /* for checking for digit string */
- X gid_t gid; /* temporary group id holder */
- X char buf[ID_STR_MAX+1]; /* for getting group string */
- X
- X
- X if(!repeat)
- X {
- X prompt_getstr(window,"Change group to: ",buf,main_rows,ID_STR_MAX);
- X
- X if(*buf == '\0')
- X return(SUCCESS);
- X
- X /* see if the group is valid */
- X
- X gid_ptr = getgrnam(buf);
- X
- X if(gid_ptr == NULL)
- X {
- X /* not found, try to use numeric value */
- X
- X tptr2 = buf;
- X
- X /* skip leading blanks first */
- X
- X while(isspace(*tptr2))
- X ++tptr2;
- X
- X while(*tptr2 && isdigit(*tptr2))
- X ++tptr2;
- X
- X if(*tptr2 != '\0')
- X return(BAD_GROUP);
- X
- X /* it's ok; change it to a integer and store it */
- X
- X gid = (gid_t) atoi(buf);
- X }
- X else
- X gid = gid_ptr->gr_gid; /* found; use it */
- X }
- X else
- X gid = group; /* use group from mark_repeat() */
- X
- X if(ent->command == NULL)
- X {
- X /* we need command structure; allocate it and link it to the file entry */
- X
- X tptr = new_comm();
- X
- X if(tptr == NULL)
- X return(FAILURE); /* problems allocating memory */
- X
- X ent->command = tptr; /* link it to the file entry */
- X }
- X else
- X tptr = ent->command; /* else use the one already there */
- X
- X tptr->comm_grp = 1;
- X tptr->group = gid;
- X tptr->comm_del = 0; /* Group implies !Delete */
- X
- X return(SUCCESS);
- X
- X} /*** mark_group ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: mark_owner
- X
- X Purpose: Prompt for the new owner of the file and look it up in the
- X passwd file. If it doesn't exist, just use the numeric version.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X main_rows X
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X SUCCESS
- X FAILURE
- X BAD_OWNER invalid owner specified
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- int mark_owner(window,ent,owner,repeat)
- X /******* FORMAL PARAMETERS *******/
- X WINDOW *window; /* where to read/write */
- X ENT_DEF *ent; /* file entry pointer */
- X uid_t owner; /* from mark_repeat() */
- X u_short repeat; /* set if called by mark_repeat() */
- X
- X{ /*** mark_owner ***/
- X /******** LOCAL VARIABLES ********/
- struct passwd *uid_ptr; /* from getpwnam() */
- X COM_DEF *tptr; /* temporary pointer */
- X char *tptr2; /* for checking for digit string */
- X uid_t uid; /* temporary group id holder */
- X char buf[ID_STR_MAX+1]; /* for getting group string */
- X
- X
- X if(!repeat)
- X {
- X prompt_getstr(window,"Change owner to: ",buf,main_rows,ID_STR_MAX);
- X
- X if(*buf == '\0')
- X return(SUCCESS);
- X
- X /* see if the owner is valid */
- X
- X uid_ptr = getpwnam(buf);
- X
- X if(uid_ptr == NULL)
- X {
- X /* not found, try to use numeric value */
- X
- X tptr2 = buf;
- X
- X /* skip leading blanks first */
- X
- X while(isspace(*tptr2))
- X ++tptr2;
- X
- X while(*tptr2 && isdigit(*tptr2))
- X ++tptr2;
- X
- X if(*tptr2 != '\0')
- X return(BAD_OWNER);
- X
- X /* it's ok; change it to a integer and store it */
- X
- X uid = (uid_t) atoi(buf);
- X }
- X else
- X uid = uid_ptr->pw_uid; /* found; use it */
- X }
- X else
- X uid = owner; /* use owner from mark_repeat() */
- X
- X if(ent->command == NULL)
- X {
- X /* we need command structure; allocate it and link it to the file entry */
- X
- X tptr = new_comm();
- X
- X if(tptr == NULL)
- X return(FAILURE); /* problems allocating memory */
- X
- X ent->command = tptr; /* link it to the file entry */
- X }
- X else
- X tptr = ent->command; /* else use the one already there */
- X
- X tptr->comm_own = 1;
- X tptr->owner = uid;
- X tptr->comm_del = 0;
- X
- X return(SUCCESS);
- X
- X} /*** mark_owner ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: prot_abs_to_val
- X
- X Purpose: See if a string is an absolute protection mode and calculate
- X the integer value if possible.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X SUCCESS
- X FAILURE
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- static short prot_abs_to_val(buffer,mode)
- X /******* FORMAL PARAMETERS *******/
- register char *buffer; /* mode string */
- X u_short *mode; /* where to put the mode value */
- X
- X{ /*** prot_abs_to_val ***/
- X /******** LOCAL VARIABLES ********/
- register int temp; /* temporary mode holder */
- X
- X
- X temp = 0;
- X
- X while(*buffer >= '0' && *buffer <= '7')
- X {
- X temp = (temp << 3) + (*buffer - '0');
- X ++buffer;
- X }
- X
- X while(isspace(*buffer)) /* skip any trailing whitespace */
- X ++buffer;
- X
- X if(*buffer != '\0')
- X return(FAILURE);
- X
- X *mode = temp;
- X return(SUCCESS);
- X
- X} /*** prot_abs_to_val ***/
- END_OF_FILE
- if test 26500 -ne `wc -c <'mark.c'`; then
- echo shar: \"'mark.c'\" unpacked with wrong size!
- fi
- # end of 'mark.c'
- fi
- if test -f 'text.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'text.c'\"
- else
- echo shar: Extracting \"'text.c'\" \(20210 characters\)
- sed "s/^X//" >'text.c' <<'END_OF_FILE'
- X/******************************************************************************
- X*******************************************************************************
- X
- X Site: Western Michigan University Academic Computer Center
- X
- X System: Directory/File System Maintenance
- X
- X Program: maint
- X
- X Version=01 Level=00 01/24/92 Leonard J. Peirce
- X
- X Purpose: Routines for dealing with text descriptors.
- X
- X Arguments: See individual routines
- X
- X External variables: See individual routines
- X
- X External functions:
- X
- X Defined: create_text, put_text, read_text_des, text_match,
- X text_search
- X
- X Called: clear_mess, get_name, get_pool_mem, prompt_getstr,
- X put_pool, strindex
- X
- X Files accessed:
- X
- X Return codes: See individual routines
- X
- X Compiling instructions: See Makefile
- X
- X Linking instructions: See Makefile
- X
- X Other information: (C) Copyright 1992, Leonard J. Peirce
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- X/******************************************************************************/
- X/* */
- X/* # I N C L U D E F I L E S */
- X/* */
- X/******************************************************************************/
- X
- X#include <stdio.h>
- X#ifdef ultrix
- X#include <cursesX.h>
- X#else
- X#include <curses.h>
- X#endif
- X#include <string.h>
- X#include "maint.h"
- X
- X/******************************************************************************/
- X/* */
- X/* # D E F I N E S */
- X/* */
- X/******************************************************************************/
- X
- X/******************************************************************************/
- X/* */
- X/* S T R U C T U R E S , U N I O N S , T Y P E D E F S */
- X/* */
- X/******************************************************************************/
- X
- X/******************************************************************************/
- X/* */
- X/* 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 */
- X/* */
- X/******************************************************************************/
- X
- extern int main_rows;
- X
- extern char *get_pool_mem();
- X
- extern int strindex();
- X
- extern void put_pool(),
- X prompt_getstr(),
- X clear_mess(),
- X *get_name();
- X
- X char *text_search(),
- X *text_match();
- X
- X int read_text_des(),
- X create_text();
- X
- X void put_text();
- X
- X/******************************************************************************/
- X/* */
- X/* 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 */
- X/* */
- X/******************************************************************************/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: read_text_des
- X
- X Purpose: Attempt to read in the text descriptors from the text des-
- X criptor file for the current directory.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X NO_FILE file does not exist
- X CANT_OPEN cannot open MAINT.TDF file
- X BAD_FILE bad text descriptor file
- X 0 text descriptor file successfully read
- X
- X Termination Codes:
- X
- X Code Reason
- X ---- ------
- X none
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- int read_text_des(dirptr,curr_pool,dir_text,pool_length,num_file)
- X /******* FORMAL PARAMETERS *******/
- register ENT_DEF *dirptr; /* pointer to directory entries */
- X POOL_DEF **curr_pool; /* pointer to pointer to current pool */
- X char **dir_text; /* directory text descriptor array */
- X size_t pool_length; /* length of pool to allocate */
- X short num_file; /* number of files in directory */
- X
- X{ /*** read_text_des ***/
- X /******** LOCAL VARIABLES ********/
- X FILE *fptr; /* text file pointer */
- X ENT_DEF *currptr; /* current entry for searching */
- X int length; /* length of string */
- X char *tptr, /* temporary character pointer */
- X *status, /* return code status holder */
- X *temp,
- X text_buf[TEXT_REC_MAX+10];
- X
- X
- X /* open the text descriptor file */
- X
- X fptr = fopen(TEXT_FILE,"r");
- X
- X if(fptr == NULL)
- X return(NO_FILE); /* no problem; just no file */
- X
- X /* get the first record; this is the text descriptor for the directory;
- X * the format for this record is
- X * >>><text descriptor for directory>
- X */
- X
- X status = fgets(text_buf,TEXT_REC_MAX+1,fptr);
- X
- X if(status == NULL)
- X {
- X *dir_text = NULL;
- X fclose(fptr);
- X return(CANT_OPEN);
- X }
- X
- X /* make sure this record is in the right form */
- X
- X if(strindex(text_buf,">>>") != 0)
- X {
- X /* close the text descriptor file */
- X
- X fclose(fptr);
- X return(BAD_FILE);
- X }
- X
- X /* store this in the memory pools and set the dir_text pointer to point
- X * to it
- X */
- X
- X length = strlen(text_buf);
- X text_buf[length - 1] = '\0'; /* lop off the \n */
- X
- X put_pool(dir_text,curr_pool,&text_buf[3],strlen(&text_buf[3]),pool_length);
- X
- X /* skip the comment lines in the text descriptor file */
- X
- X status = fgets(text_buf,TEXT_REC_MAX+1,fptr);
- X
- X while(status != NULL && text_buf[0] == '>')
- X status = fgets(text_buf,TEXT_REC_MAX+1,fptr);
- X
- X if(status == NULL)
- X {
- X fclose(fptr);
- X return(SUCCESS); /* end-of-file here.... */
- X }
- X
- X /* now get each text descriptor record and match it up with a filename */
- X
- X /* set the current file entry pointer to actually pointer to one entry
- X * BEFORE the current entry; it will be updated inside text_search to
- X * point to the correct entry; this is done so that text_search can be
- X * more general
- X */
- X
- X currptr = dirptr - 1; /* set where we start to look */
- X
- X while(status != NULL)
- X {
- X /* search for a match with the filename in the text descriptor record */
- X
- X length = strlen(text_buf);
- X text_buf[length - 1] = '\0';
- X
- X if((tptr = text_search(dirptr,&currptr,text_buf,num_file)) != NULL)
- X {
- X /* match; store the text descriptor in a memory pool */
- X
- X/* put_pool(&(currptr->text),curr_pool,tptr,(size_t) strlen(tptr),
- X pool_length);*/
- X put_pool(&temp,curr_pool,tptr,(size_t) strlen(tptr),
- X pool_length);
- X currptr->text = temp;
- X }
- X
- X status = fgets(text_buf,TEXT_REC_MAX+1,fptr);
- X }
- X
- X fclose(fptr);
- X return(SUCCESS); /* everything done */
- X
- X} /*** read_text_des ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: text_search
- X
- X Purpose: Search the directory entries for a match with the current
- X text descriptor record. If one is found, return a pointer
- X to the actual text of the text descriptor and update the
- X current directory entry pointer to point to the NEXT entry
- X to check for a text descriptor match.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X retval pointer to actual text of text descriptor
- X NULL no match for text descriptor
- X
- X Termination Codes:
- X
- X Code Reason
- X ---- ------
- X none
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- char *text_search(dirptr,currptr,text_rec,num_file)
- X /******* FORMAL PARAMETERS *******/
- X ENT_DEF *dirptr, /* pointer to all directory entries */
- X **currptr; /* pointer to current directory entry */
- X char *text_rec; /* current text descriptor record */
- X short num_file; /* number of files in directory */
- X
- X{ /*** text_search ***/
- X /******** LOCAL VARIABLES ********/
- register ENT_DEF *ptr; /* current file entry pointer */
- X ENT_DEF *origptr; /* original directory pointer */
- X char *retval; /* return value */
- X u_long curr_index; /* index value for setting pointer */
- X
- X
- X /* get pointer to directory that we need; this is the one following
- X * (modulo the number of files in the directory) the entry that we
- X * were on the last time through
- X */
- X
- X curr_index = *currptr - dirptr; /* get current entry index */
- X curr_index = (curr_index + 1L) % (u_long) num_file;
- X
- X ptr = dirptr + curr_index; /* get pointer to the NEW entry */
- X
- X /* first check to see if we have a match with the current entry */
- X
- X if((retval = text_match(ptr->filename,text_rec)) != NULL)
- X {
- X /* we have a match; return the pointer to the beginning of the
- X * actual text of the text descriptor AND update the currptr
- X * return value to point to the next entry so that the next time
- X * this routine is called, we can start up one after where we
- X * left off here
- X */
- X
- X *currptr = ptr; /* return pointer to current entry */
- X return(retval); /* match.... */
- X }
- X
- X /* no match with the current entry; search the entries until 1) we find a
- X * a match, or until we have examined all of the entries
- X */
- X
- X origptr = ptr; /* save where we are right now */
- X curr_index = (curr_index + 1L) % (u_long) num_file;
- X ptr = dirptr + curr_index;
- X
- X while(ptr != origptr) /* until we are back where we started */
- X {
- X /* check for a match */
- X
- X if((retval = text_match(ptr->filename,text_rec)) != NULL)
- X {
- X /* we have a match; return the pointer to the beginning of the
- X * actual text of the text descriptor AND update the currptr
- X * return value to point to the current directory entry so that
- X * we know where we left off last time through
- X */
- X
- X *currptr = ptr;
- X return(retval);
- X }
- X
- X /* update the current entry pointer to point to the next entry */
- X
- X curr_index = (curr_index + 1L) % (u_long) num_file;
- X ptr = dirptr + curr_index;
- X }
- X
- X return(NULL); /* no match for this text descriptor */
- X
- X} /*** text_search ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: text_match
- X
- X Purpose: Determine if a text descriptor record is the correct one
- X for a file entry.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X
- X NULL no match for text descriptor record
- X text_rec + 1L pointer to beginning of text descriptor part
- X of the record
- X
- X Termination Codes:
- X
- X Code Reason
- X ---- ------
- X none
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- char *text_match(filename,text_rec)
- X /******* FORMAL PARAMETERS *******/
- register char *filename, /* filename to look for */
- X *text_rec; /* current text descriptor record */
- X
- X{ /*** text_match ***/
- X
- X
- X while((*filename == *text_rec) && (*filename != '\0'))
- X {
- X filename++;
- X text_rec++;
- X }
- X
- X /* now check to see if we had a match */
- X
- X if(*text_rec == ' ')
- X {
- X /* return a pointer to the beginning of the text descriptor */
- X
- X return(text_rec + 1L);
- X }
- X
- X return(NULL); /* not correct record for file */
- X
- X} /*** text_match ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: put_text
- X
- X Purpose: Put the text descriptor for the directory on the screen.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X COLS X
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X SUCCESS Everything fine
- X FAILURE Error parsing new filename
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- void put_text(window,text_desc)
- X /******* FORMAL PARAMETERS *******/
- X WINDOW *window; /* where to write */
- X char *text_desc; /* text descriptor buffer */
- X
- X{ /*** put_text ***/
- X /******** LOCAL VARIABLES ********/
- X size_t length; /* string length holder */
- static char buf[MAX_SCREEN_COLS+5], /* formatting buffer */
- X spaces[] = /* spaces array for centering stuff */
- X" ";
- X
- X
- X if(text_desc != NULL) /* is there anything to write? */
- X {
- X length = (COLS - strlen(text_desc))/2;
- X spaces[length] = '\0'; /* make spaces for centering */
- X cat(5,buf,spaces,text_desc,spaces," ");
- X buf[COLS] = '\0'; /* make sure we have the right length */
- X spaces[length] = ' '; /* reset spaces array for next time */
- X
- X /* write directory text descriptor in reverse video at top of screen */
- X
- X mvwaddstr(window,SPEC_WINDOW_ROWS-1,0,buf);
- X }
- X else
- X {
- X /* erase the one that might be on the screen, since this directory
- X * doesn't have a text descriptor
- X */
- X
- X wmove(window,SPEC_WINDOW_ROWS-1,0);
- X wclrtoeol(window);
- X }
- X
- X wrefresh(window);
- X return;
- X
- X} /*** put_text ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: create_text
- X
- X Purpose: Attempt to create the text descriptor file if the user wants
- X to. The user is prompted for the text descriptor for the
- X directory and the file is written with the entry for the
- X text descriptor file itself.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X DONT_CREATE user does not want text descriptor file created
- X CANT_OPEN error opening/writing text descriptor file
- X NEW_FILE new text descriptor file created
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- int create_text(window)
- X /******* FORMAL PARAMETERS *******/
- X WINDOW *window; /* where to read/write */
- X
- X{ /*** create_text ***/
- X /******** LOCAL VARIABLES ********/
- X FILE *fptr; /* text file pointer */
- X char term_code, /* keystroke read in */
- X buf[MAX_SCREEN_COLS+1], /* for all kinds of output stuff */
- X text_buf[DIR_TEXT_MAX+1]; /* buffer for reading from screen */
- X
- X
- X sprintf(buf,"Text descriptor file %s does not exist. Create it? [y] ",
- X TEXT_FILE);
- X
- X /* prompt the user to see if they want to create the text descriptor file */
- X
- X info_mess(buf);
- X term_code = wgetch(window); /* get their response */
- X clear_mess(window); /* clear the prompt from the screen */
- X
- X /* now see what key was pressed */
- X
- X if(term_code == 'N' || term_code == 'n')
- X return(DONT_CREATE); /* don't create the file here, either */
- X
- X /* ok, we need to create the file; open it for writing */
- X
- X fptr = fopen(TEXT_FILE,"w");
- X
- X if(fptr == NULL)
- X return(CANT_OPEN);
- X
- X /* the file has been opened ok; get the descriptor for the directory,
- X * format it, and write it to the text descriptor file
- X */
- X
- X /* prompt for and read in the text descriptor for the directory itself */
- X
- X prompt_getstr(window,"Text descriptor for directory: ",text_buf,main_rows,
- X DIR_TEXT_MAX);
- X
- X text_buf[DIR_TEXT_MAX] = '\0'; /* make sure it's not too long */
- X cat(4,buf,">>>",text_buf,"\n"); /* format it correctly */
- X
- X /* now write the directory text descriptor record to the file */
- X
- X fputs(buf,fptr);
- X fputs(">\n",fptr); /* write a spacing record */
- X
- X /* now write the text descriptor entry for the text descriptor file
- X * itself; this is so the user knows what the file is when they bring
- X * the text descriptors in
- X */
- X
- X cat(3,buf,TEXT_FILE," text descriptor file\n");
- X fputs(buf,fptr);
- X
- X fclose(fptr);
- X return(NEW_FILE);
- X
- X} /*** create_text ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: get_text
- X
- X Purpose: Set up and get the text descriptors for the current
- X directory. Being able to update slot_width is essential
- X for proc_dir() and is one of the reasons this routine
- X exists. slot_width is set in set_args() but set_args()
- X is only called from main().
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X args.text X X
- X args.text_startup X
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X none
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- void get_text(args,dirptr,curr_pool,dir_text,mess_flag,slot_width,text_flag,
- X pool_length,num_file)
- X
- X /******* FORMAL PARAMETERS *******/
- X ARG_DEF *args; /* run-time arguments */
- X ENT_DEF *dirptr; /* pointer to directory information */
- X POOL_DEF **curr_pool; /* pointer to current memory pool */
- X char **dir_text, /* pointer to directory text descrip */
- X *mess_flag; /* set if information mess on screen */
- X short *slot_width, /* slot width for current directory */
- X *text_flag; /* set if descrip file was processed */
- X size_t pool_length; /* length for allocating new pools */
- X short num_file; /* number of files in directory */
- X
- X{ /*** get_text ***/
- X /******** LOCAL VARIABLES ********/
- X short status; /* return status from read_text_des() */
- X
- X
- X *text_flag = 0;
- X
- X if(args->text)
- X {
- X /* yes, read in the text descriptors */
- X
- X *text_flag = args->text; /* set descrip flag for this direct. */
- X
- X if(args->text == DISPLAY_TEXT && !args->text_startup)
- X *slot_width += TEXT_MAX + 1; /* assume we will get text descrips */
- X
- X status = read_text_des(dirptr,curr_pool,dir_text,pool_length,num_file);
- X
- X /* check to see if there were any problems getting the text descriptors */
- X
- X if(status == BAD_FILE)
- X {
- X info_mess("Invalid format for text descriptor file");
- X *mess_flag = 1;
- X *text_flag = 0; /* no text descrips for directory */
- X
- X if(args->text == DISPLAY_TEXT) /* only update slot_width if needed */
- X *slot_width = *slot_width - (TEXT_MAX + 1);
- X
- X sleep(1);
- X }
- X else if(status == CANT_OPEN)
- X {
- X info_mess("Cannot open text descriptor file");
- X *mess_flag = 1;
- X *text_flag = 0; /* no text descrips for directory */
- X
- X if(args->text == DISPLAY_TEXT) /* only update slot_width if needed */
- X *slot_width = *slot_width - (TEXT_MAX + 1);
- X
- X sleep(1);
- X }
- X else if(status == NO_FILE)
- X {
- X *text_flag = 0; /* no text descrips for directory */
- X
- X if(args->text == DISPLAY_TEXT) /* update slot_width if it needs it */
- X *slot_width = *slot_width - (TEXT_MAX + 1);
- X }
- X }
- X
- X
- X return;
- X
- X} /*** get_text ***/
- END_OF_FILE
- if test 20210 -ne `wc -c <'text.c'`; then
- echo shar: \"'text.c'\" unpacked with wrong size!
- fi
- # end of 'text.c'
- fi
- if test -f 'xecute.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xecute.c'\"
- else
- echo shar: Extracting \"'xecute.c'\" \(22377 characters\)
- sed "s/^X//" >'xecute.c' <<'END_OF_FILE'
- X/******************************************************************************
- X*******************************************************************************
- X
- X Site: Western Michigan University Academic Computer Center
- X
- X System: Directory/File System Maintenance
- X
- X Program: maint
- X
- X Version=01 Level=00 01/24/92 Leonard J. Peirce
- X
- X Purpose: Execute the commands in a directory, informing the user of
- X the result of each.
- X
- X Arguments: See individual routines
- X
- X External variables: See individual routines
- X
- X Maint external functions:
- X
- X Defined: xecute
- X
- X Called: free_comstr, mystrcpy
- X
- X Files accessed: Files with commands associated with them
- X
- X Return codes: See individual routines
- X
- X Compiling instructions: See Makefile
- X
- X Linking instructions: See Makefile
- X
- X Other information: (C) Copyright 1990, Leonard J. Peirce
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- X/******************************************************************************/
- X/* */
- X/* # I N C L U D E F I L E S */
- X/* */
- X/******************************************************************************/
- X
- X#include <fcntl.h>
- X#include <errno.h>
- X#include <stdio.h>
- X#include <string.h>
- X#ifdef ultrix
- X#include <cursesX.h>
- X#else
- X#include <curses.h>
- X#endif
- X#include "maint.h"
- X#include <sys/stat.h>
- X
- X/******************************************************************************/
- X/* */
- X/* # D E F I N E S */
- X/* */
- X/******************************************************************************/
- X
- X#define XMESS_PAUSE 4 /* length of pause for error messages */
- X
- X/******************************************************************************/
- X/* */
- X/* S T R U C T U R E S , U N I O N S , T Y P E D E F S */
- X/* */
- X/******************************************************************************/
- X
- X/******************************************************************************/
- X/* */
- X/* 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 */
- X/* */
- X/******************************************************************************/
- X
- extern char *mystrcpy();
- X
- extern int unlink(),
- X chmod(),
- X rename(),
- X read(),
- X write(),
- X open(),
- X close(),
- X errno;
- X
- extern void free_comstr();
- X
- X void xecute();
- X
- X/******************************************************************************/
- X/* */
- X/* 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 */
- X/* */
- X/******************************************************************************/
- X
- static char *make_err_msg();
- X
- static int write_text(),
- X copy_file(),
- X rename_file();
- X
- static void make_xmess();
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: xecute
- X
- X Purpose: Execute all of the file commands for the current directory.
- X Display success and failure messages to the screen for each
- X of the files.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X none
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- void xecute(ent,dir_text,num_file)
- X /******* FORMAL PARAMETERS *******/
- X ENT_DEF *ent; /* file entry pointer */
- X char *dir_text; /* pointer to directory text descrip. */
- X short num_file; /* number of files in directory */
- X
- X{ /*** xecute ***/
- X /******** LOCAL VARIABLES ********/
- X int status, /* return code status holder */
- X prefix_len, /* length of message prefix string */
- X text_write; /* set to FAILURE if write_text fails */
- register COM_DEF *comm_ptr; /* pointer to command structure */
- X short i; /* loop and array index */
- X char buf[SPEC_MAX*2+10]; /* for formatting messages */
- X
- X
- X text_write = SUCCESS; /* assume it will work */
- X i = 0;
- X
- X while(i < num_file)
- X {
- X if(ent->command != NULL) /* does this file have any commands? */
- X {
- X comm_ptr = ent->command; /* get a pointer to the comm struct */
- X
- X if(comm_ptr->comm_copy)
- X {
- X status = copy_file(ent->filename,comm_ptr->copy_name);
- X make_xmess(buf,ent->filename,&prefix_len,status,COPY,ent->type);
- X xmess(buf,prefix_len);
- X
- X if(status != SUCCESS)
- X {
- X beep();
- X sleep(XMESS_PAUSE); /* let user read error message */
- X }
- X
- X errno = 0;
- X }
- X
- X if(comm_ptr->comm_ren)
- X {
- X status = rename_file(ent->filename,comm_ptr->ren_name);
- X make_xmess(buf,ent->filename,&prefix_len,status,RENAME,ent->type);
- X xmess(buf,prefix_len);
- X
- X if(status != SUCCESS)
- X {
- X beep();
- X sleep(XMESS_PAUSE);
- X }
- X
- X errno = 0;
- X }
- X
- X if(comm_ptr->comm_prot)
- X {
- X if(chmod(ent->filename,(int) comm_ptr->prot) == 0)
- X status = SUCCESS;
- X else
- X status = FAILURE;
- X
- X make_xmess(buf,ent->filename,&prefix_len,status,RENAME,ent->type);
- X xmess(buf,prefix_len);
- X
- X if(status != SUCCESS)
- X {
- X beep();
- X sleep(XMESS_PAUSE);
- X }
- X
- X errno = 0;
- X }
- X
- X if(comm_ptr->comm_own)
- X {
- X if(chown(ent->filename,comm_ptr->owner,-1) == 0)
- X status = SUCCESS;
- X else
- X status = FAILURE;
- X
- X make_xmess(buf,ent->filename,&prefix_len,status,OWNER,ent->type);
- X xmess(buf,prefix_len);
- X
- X if(status != SUCCESS)
- X {
- X beep();
- X sleep(XMESS_PAUSE);
- X }
- X
- X errno = 0;
- X }
- X
- X if(comm_ptr->comm_grp)
- X {
- X if(chown(ent->filename,-1,comm_ptr->group) == 0)
- X status = SUCCESS;
- X else
- X status = FAILURE;
- X
- X make_xmess(buf,ent->filename,&prefix_len,status,GROUP,ent->type);
- X xmess(buf,prefix_len);
- X
- X if(status != SUCCESS)
- X {
- X beep();
- X sleep(XMESS_PAUSE);
- X }
- X
- X errno = 0;
- X }
- X
- X if(comm_ptr->comm_text != NULL && text_write == SUCCESS)
- X {
- X /* yes, write a text descriptor */
- X
- X text_write = write_text(ent->filename,comm_ptr->text,
- X dir_text,FALSE);
- X
- X ent->text = NULL; /* no more text descriptor */
- X }
- X
- X if(comm_ptr->comm_del)
- X {
- X if(ent->type != DIRECTORY)
- X {
- X /* nothing special, just use unlink */
- X
- X if(unlink(ent->filename) == 0)
- X status = SUCCESS;
- X else
- X status = FAILURE;
- X
- X make_xmess(buf,ent->filename,&prefix_len,status,DELETE,
- X ent->type);
- X }
- X else
- X {
- X if(rmdir(ent->filename) == 0)
- X status = SUCCESS;
- X else
- X status = FAILURE;
- X
- X make_xmess(buf,ent->filename,&prefix_len,status,DELETE,
- X ent->type);
- X }
- X
- X xmess(buf,prefix_len);
- X
- X if(status != SUCCESS)
- X {
- X beep();
- X sleep(XMESS_PAUSE);
- X }
- X
- X ent->text = NULL; /* no more text descriptor */
- X errno = 0;
- X }
- X
- X free_comstr(ent->command); /* free the command structure */
- X ent->command = NULL;
- X }
- X
- X if(ent->text != NULL && text_write == SUCCESS)
- X {
- X /* yes, write a text descriptor */
- X
- X text_write = write_text(ent->filename,ent->text,dir_text,FALSE);
- X }
- X
- X ++ent;
- X ++i;
- X }
- X
- X text_write = write_text(NULLPTR,NULLPTR,NULLPTR,TRUE);
- X return;
- X
- X} /*** xecute ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: copy_file
- X
- X Purpose: Copy the source file to the destination file.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X SUCCESS
- X CANT_STAT cannot stat source file
- X CANT_OPEN cannot open source file
- X CANT_OPEN_DEST cannot open destination file
- X CANT_WRITE error writing to destination file
- X CANT_CHMOD cannot do a chmod() on file
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- static int copy_file(source,dest)
- X /******* FORMAL PARAMETERS *******/
- X char *source, /* file to copy from */
- X *dest; /* file to copy to */
- X
- X{ /*** copy_file ***/
- X /******** LOCAL VARIABLES ********/
- struct stat statbuf; /* for stat on source file */
- X char buf[BUFSIZ+5]; /* read/write buffer */
- X int numbyte, /* bytes read/written */
- X badwrite, /* loop control variable */
- X inputfd, /* input file descriptor */
- X outputfd; /* output file descriptor */
- X
- X
- X if(stat(source,&statbuf) < 0)
- X return(CANT_STAT);
- X
- X if((inputfd = open(source,O_RDONLY,0)) < 0)
- X return(CANT_OPEN);
- X
- X /* see if the destination is a directory; if it is, we have some work to
- X * do to create the destination filename
- X */
- X
- X if(stat(dest,&statbuf) == 0 && ((statbuf.st_mode & S_IFMT) == S_IFDIR))
- X {
- X /* it is a directory; cat the source name onto the destination name */
- X
- X strcat(dest,"/");
- X strcat(dest,source);
- X }
- X
- X if((outputfd = open(dest,O_WRONLY | O_TRUNC | O_CREAT,0)) < 0)
- X {
- X close(inputfd);
- X return(CANT_OPEN_DEST);
- X }
- X
- X numbyte = read(inputfd,buf,BUFSIZ);
- X badwrite = FALSE;
- X
- X while(numbyte > 0 && !badwrite)
- X {
- X if((write(outputfd,buf,numbyte)) == -1)
- X badwrite = TRUE;
- X else
- X numbyte = read(inputfd,buf,BUFSIZ);
- X }
- X
- X close(inputfd);
- X close(outputfd);
- X
- X if(badwrite) /* did it work? */
- X {
- X unlink(dest); /* nope, get rid of destination file */
- X return(CANT_WRITE);
- X }
- X
- X /* make sure the destination file has the same mode as the source */
- X
- X if(chmod(dest,(int) statbuf.st_mode) != 0)
- X return(CANT_CHMOD);
- X
- X return(SUCCESS);
- X
- X} /*** copy_file ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: rename_file
- X
- X Purpose: Rename the source file to the destination file.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X SUCCESS
- X FAILURE
- X CANT_STAT cannot stat destination file
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- static int rename_file(source,dest)
- X /******* FORMAL PARAMETERS *******/
- X char *source, /* file to be renamed */
- X *dest; /* file to rename to */
- X
- X{ /*** rename_file ***/
- X /******** LOCAL VARIABLES ********/
- struct stat statbuf; /* for stat on source file */
- X
- X
- X /* see if the destination is a directory; if it is, we have some work to
- X * do to create the destination filename
- X */
- X
- X if(stat(dest,&statbuf) == 0 && ((statbuf.st_mode & S_IFMT) == S_IFDIR))
- X {
- X /* it is a directory; cat the source name onto the destination name */
- X
- X strcat(dest,"/");
- X strcat(dest,source);
- X }
- X
- X if(rename(source,dest) != 0)
- X return(FAILURE);
- X
- X return(SUCCESS);
- X
- X} /*** rename_file ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: make_xmess
- X
- X Purpose: Create a message for the xecute() routine by looking at
- X what is being performed and the status code. First, the
- X action is determined to get the correct string. Then, the
- X correct result string is determined, based on the action
- X type. If an error occurred, errno is examined to see if an
- X intelligent error message can be constructed from it's value.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X COLS X
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X none
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- static void make_xmess(buf,filename,prefix_len,status,action,type)
- X /******* FORMAL PARAMETERS *******/
- X char *buf, /* where to put the message */
- X *filename; /* file being operated on */
- X int *prefix_len, /* length of message prefix string */
- X status; /* status code to check */
- X u_char action, /* what is happening */
- X type; /* type of file being acted upon */
- X
- X{ /*** make_xmess ***/
- X /******** LOCAL VARIABLES ********/
- X char *msg_ptr, /* pointer to action type message */
- X *error_ptr, /* pointer to errno message */
- X *result_ptr; /* pointer to result message */
- X int msg_len; /* length of action message part */
- static char delete_msg[] = {"Delete "},
- X copy_msg[] = {"Copy "},
- X rename_msg[] = {"Rename "},
- X protect_msg[] = {"Protect "},
- X text_msg[] = {"Text "},
- X owner_msg[] = {"Change owner "},
- X group_msg[] = {"Change group "},
- X ok_msg[] = {"? [OK]"},
- X error_msg[] = {"? *ERROR*"},
- X null_msg[] = {""};
- X
- X
- X error_ptr = null_msg; /* Suns don't like NULL too well.... */
- X
- X switch(action) /* what are we doing? */
- X {
- X case(DELETE):
- X msg_ptr = delete_msg;
- X msg_len = sizeof(delete_msg);
- X break;
- X case(COPY):
- X msg_ptr = copy_msg;
- X msg_len = sizeof(copy_msg);
- X break;
- X case(RENAME):
- X msg_ptr = rename_msg;
- X msg_len = sizeof(rename_msg);
- X break;
- X case(PROTECT):
- X msg_ptr = protect_msg;
- X msg_len = sizeof(protect_msg);
- X break;
- X case(GROUP):
- X msg_ptr = group_msg;
- X msg_len = sizeof(group_msg);
- X break;
- X case(OWNER):
- X msg_ptr = owner_msg;
- X msg_len = sizeof(owner_msg);
- X break;
- X case(TEXT):
- X msg_ptr = text_msg;
- X msg_len = sizeof(text_msg);
- X break;
- X default:
- X break; /* should NEVER get here.... */
- X }
- X
- X if(status == SUCCESS)
- X {
- X /* the action worked; creating the message will be easy here */
- X
- X result_ptr = ok_msg;
- X }
- X else if(status == FAILURE)
- X {
- X result_ptr = error_msg;
- X
- X /* make an explicit error message if possible */
- X
- X error_ptr = make_err_msg(status,action,type);
- X }
- X else
- X {
- X result_ptr = error_msg;
- X }
- X
- X /* construct the message */
- X
- X sprintf(buf,"%s%s%s%s",msg_ptr,filename,result_ptr,error_ptr);
- X *prefix_len = msg_len;
- X return;
- X
- X} /*** make_xmess ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: write_text
- X
- X Purpose: Inverted coroutine (to xecute()) to write text descriptor
- X records to the text descriptor fioel. A record of length
- X zero signifies that the entry is to be deleted.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X none
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X SUCCESS
- X FAILURE
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- static int write_text(filename,text,dir_text,eof_flag)
- X /******* FORMAL PARAMETERS *******/
- X char *filename, /* filename that has a text descrip */
- X *text, /* text descriptor */
- X *dir_text; /* directory text descriptor */
- X u_char eof_flag; /* set if we're done */
- X
- X{ /*** write_text ***/
- X /******** LOCAL VARIABLES ********/
- static FILE *fptr; /* pointer to text descriptor file */
- static u_char state, /* state variable */
- X file_open; /* set if file has been opened */
- X
- X
- X /* special case where an attempt is made to close the file when nothing
- X * had been written to it
- X */
- X
- X if(eof_flag == TRUE && !file_open)
- X {
- X state = 0;
- X return(SUCCESS);
- X }
- X
- X if(state == 1)
- X goto lab0;
- X
- X fptr = fopen(TEXT_FILE,"w");
- X
- X if(fptr == NULL)
- X return(FALSE);
- X
- X /* write the directory text descriptor record */
- X
- X fprintf(fptr,">>>%s\n",dir_text);
- X fputs(">\n",fptr);
- X
- X state = 1;
- X file_open = 1;
- X
- X while(eof_flag == FALSE)
- X {
- X if(text != NULL) /* NULL descriptor means delete it */
- X fprintf(fptr,"%s %s\n",filename,text);
- X
- X return(SUCCESS); /* coroutine "read" */
- X
- lab0: ; /* this is where we return */
- X }
- X
- X state = 0;
- X file_open = 0;
- X fclose(fptr);
- X
- X return(SUCCESS);
- X
- X} /*** write_text ***/
- X
- X/*******************************************************************************
- X********************************************************************************
- X
- X Function: make_err_msg
- X
- X Purpose: Try to make an intelligent error message based on an action
- X and the value of errno.
- X
- X Global variables:
- X
- X Name Examine/Modify/Use/Read/Write
- X ---- -----------------------------
- X errno X
- X
- X Return Codes:
- X
- X Code Reason
- X ---- ------
- X retptr pointer to message
- X
- X********************************************************************************
- X*******************************************************************************/
- X
- static char *make_err_msg(status,action,type)
- X /******* FORMAL PARAMETERS *******/
- X int status; /* status from attempted operation */
- X u_char action, /* what command is being done */
- X type; /* type of file being acted upon */
- X
- X{ /*** make_err_msg ***/
- X /******** LOCAL VARIABLES ********/
- X char *retptr = NULL; /* message to return */
- X
- X
- X /* first see if the status can be used to create an intelligent message */
- X
- X if(status != FAILURE && status != SUCCESS)
- X {
- X /* yep, use it */
- X
- X switch(status)
- X {
- X case(CANT_STAT):
- X case(CANT_OPEN):
- X retptr = " Cannot open source file";
- X break;
- X case(CANT_OPEN_DEST):
- X retptr = " Cannot open destination file";
- X break;
- X case(CANT_WRITE):
- X retptr = " Write to destination file failed";
- X break;
- X case(CANT_CHMOD):
- X retptr = " Cannot set protection mode on destination file";
- X break;
- X default:
- X break;
- X }
- X
- X return(retptr);
- X }
- X
- X /* nope, the status was no good to use; check the action and errno */
- X
- X switch(action)
- X {
- X case(RENAME):
- X
- X switch(errno)
- X {
- X case(ENOENT):
- X retptr = " Invalid destination specificiation";
- X break;
- X case(EACCES):
- X retptr = " Cannot open destination file";
- X break;
- X case(EPERM):
- X retptr = " Destination file exists";
- X break;
- X case(EXDEV):
- X retptr = " Destination file is on a different device";
- X break;
- X case(EROFS):
- X retptr = " Destination directory is in a read-only filesystem";
- X break;
- X#if !defined(SYSV) || defined(sun)
- X case(ELOOP):
- X retptr = " Too many symbolic links in filename";
- X break;
- X case(EDQUOT):
- X retptr = " Disk quota exhausted";
- X break;
- X#endif
- X case(ENOSPC):
- X retptr = " File system is full";
- X break;
- X default:
- X break;
- X }
- X
- X break;
- X
- X case(COPY):
- X
- X switch(errno)
- X {
- X case(EACCES):
- X retptr = " Cannot open destination file";
- X break;
- X case(EIO):
- X retptr = " I/O error";
- X break;
- X#if !defined(SYSV) || defined(sun)
- X case(ELOOP):
- X retptr = " Too many symbolic links in filename";
- X break;
- X case(EDQUOT):
- X retptr = " Disk quota exhausted";
- X break;
- X#endif
- X case(ENOENT):
- X retptr = " Invalid destination specificiation";
- X break;
- X case(ENOSPC):
- X retptr = " File system is full";
- X break;
- X default:
- X break;
- X }
- X
- X break;
- X
- X case(PROTECT):
- X
- X switch(errno)
- X {
- X case(EACCES):
- X retptr = " Protection violation";
- X break;
- X case(EIO):
- X retptr = " I/O error";
- X break;
- X case(ENOENT):
- X retptr = " File does not exist";
- X break;
- X case(EPERM):
- X retptr = " Not owner of file";
- X break;
- X case(EROFS):
- X retptr = " File resides in a read-only filesystem";
- X break;
- X default:
- X break;
- X }
- X
- X break;
- X
- X case(DELETE):
- X
- X if(type != DIRECTORY)
- X {
- X switch(errno)
- X {
- X case(ENOENT):
- X retptr = " File does not exist";
- X break;
- X case(EACCES):
- X retptr = " Protection violation";
- X break;
- X case(EPERM):
- X retptr = " Permission denied (mount point or not owner)";
- X break;
- X case(EIO):
- X retptr = " I/O error";
- X break;
- X default:
- X break;
- X }
- X }
- X else
- X {
- X /* trying to delete a directory with rmdir */
- X
- X switch(errno)
- X {
- X#if !defined(SYSV) || defined(sun)
- X case(ENOTEMPTY):
- X retptr = " Directory is not empty";
- X break;
- X#endif
- X case(EPERM):
- X retptr = " Not owner";
- X break;
- X case(EBUSY):
- X retptr = " Mount point for a mounted file system";
- X break;
- X case(EIO):
- X retptr = " I/O error";
- X break;
- X default:
- X break;
- X }
- X }
- X
- X break;
- X
- X case(OWNER):
- X case(GROUP):
- X
- X switch(errno)
- X {
- X case(ENOENT):
- X retptr = " File does not exist";
- X break;
- X case(EPERM):
- X retptr = " Must be superuser";
- X break;
- X case(EROFS):
- X retptr = " File resides in a read-only filesystem";
- X break;
- X default:
- X break;
- X }
- X
- X break;
- X
- X default:
- X
- X break;
- X }
- X
- X return(retptr);
- X
- X} /*** make_err_msg ***/
- END_OF_FILE
- if test 22377 -ne `wc -c <'xecute.c'`; then
- echo shar: \"'xecute.c'\" unpacked with wrong size!
- fi
- # end of 'xecute.c'
- fi
- echo shar: End of archive 3 \(of 7\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 7 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-