home *** CD-ROM | disk | FTP | other *** search
- #ifndef NO_IDENT
- static char *Id = "$Id: flprot.c,v 1.15 1995/10/22 22:07:44 tom Exp $";
- #endif
-
- /*
- * Title: flprot.c
- * Author: Thomas E. Dickey
- * Created: 11 May 1984
- * Last update:
- * 22 Oct 1995, DEC-C treats chars in 128-255 range different from
- * VAX-C (in the latter, none are punctuation/alpha).
- * 18 Mar 1995, prototypes
- * 18 Feb 1995, port to AXP (renamed 'alarm')
- * 05 Oct 1985, added key-argument to 'flist_help'.
- * 24 Sep 1985, corrected threshold-test on 'prot_col'.
- * 04 Jul 1985, cleanup 'filelist' definition.
- * 15 May 1985, use '_toupper' macro, not routine
- * 05 May 1985, added history-flag
- * 22 Apr 1985, use 'edtcmd', rather than 'dircmd' for input,
- * do 'crt'-call directly for screen updates.
- * 14 Apr 1985, use 'flist_info' for log-routing
- * 08 Mar 1985, permit filespec as part of argument list. If
- * this is not the current file, protection-code
- * must be explicit.
- * 21 Dec 1984, corrected error returns from 'setprot'.
- * 20 Dec 1984, use ^D, ^E for cursor movement. Broke out 'isowner'.
- * 10 Dec 1984, use 'dirent_chk2' instead of 'dirent_one'.
- * Omit coercion to readonly since ACP does ok.
- * 20 Nov 1984, use 'setprot' instead of spawning
- * 19 Oct 1984, use 'cmdstk_chg' (broken from 'dircmd')
- * 17 Oct 1984, use 'dircmd_GET' instead of 'getpad'
- * 03 Sep 1984, use "import"
- * 27 Aug 1984, cleanup of buffer sizes
- * 14 Aug 1984, use 'dirent_ccol()'
- * 14 Jul 1984, forgot to test 'M_opt' before edit
- * 12 Jul 1984, corrected DCLARG usage, added help-call
- * 10 Jul 1984, re-coded for DCLARG-list
- * 22 May 1984
- *
- * Function: This module supports an edit-function for the protection-
- * code field displayed (last on each line) by "FLIST". As
- * each change to the original code is made, it is highlighted
- * (and uppercased, for VT52, etc.) to show the user what he
- * has changed. On successful completion of the editing,
- * a "SET PROTECTION" command is constructed, and saved for
- * retrieval (if the procedure is entered as a "visible"
- * command).
- *
- * This function operates only on the current entry of the
- * file-list.
- *
- * Commands: left-arrow - move left (with wrap-around)
- * right-arrow - move right (with wrap-around)
- * up-arrow - set the current bit
- * down-arrow - clear the current bit
- * y - select entire field (even if no change)
- * n - deselect field
- * , - Move to next group
- * CTRL/U, CTRL/X - abort edit
- * ENTER, RETURN - complete edit, submit command
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
-
- #include "cmdstk.h"
- #include "flist.h"
- #include "dirent.h"
- #include "getpad.h"
- #include "getprot.h"
- #include "dircmd.h"
- #include "edtcmd.h"
- #include "dirfind.h"
- #include "dds.h"
-
- #include "strutils.h"
-
- extern int isowner(FILENT *z);
-
- static int flprot_edit (char *set_, int curfile);
- static void flprot_one(int, int *); /* function via 'dirfind' */
-
- import(filelist);
- import(M_opt);
-
- static char * savecmd = nullC; /* Text of option-code to process */
-
- tDIRCMD(flprot)
- {
- FILENT *z = FK_(*curfile_);
- DCLARG *name_ = 0, /* => filename specification */
- *code_ = 0; /* => protection-code */
- int no_edit = FALSE, /* TRUE iff code is specified */
- flag;
- char msg [CRT_COLS],
- fullname[MAX_PATH];
-
- if (!M_opt)
- {
- warn ("EDIT-PROTECTION is not applicable");
- return;
- }
- dirent_glue (fullname, z);
-
- if (!isowner(z)) return;
-
- /*
- * Analyze the argument list, if one was given. It may fall into
- * one of the following cases:
- *
- * (a) No list: edit current file
- * (b) No code: name must be that of current file (edit it, if so).
- * (c) Code: apply this to the specified file(s).
- */
- if (xdcl_)
- {
- while (xdcl_ = xdcl_->dcl_next)
- {
- if (isopt(xdcl_->dcl_text[0]))
- code_ = xdcl_;
- else
- name_ = xdcl_;
- }
- no_edit = (code_ != 0);
- if ((code_ == 0) && (name_ != 0))
- {
- if (strcmp(fullname, name_->dcl_text))
- {
- warn ("You must specify a protection code");
- return;
- }
- }
- }
-
- /*
- * If no code given, enter cursor-only edit of the protection code.
- * Note that if a field is unspecified, it is not altered. When
- * complete, save this command for retrieval.
- */
- if (!savecmd)
- savecmd = calloc(1, CRT_COLS);
- if (no_edit)
- sprintf (savecmd, "PROTECT %s", code_->dcl_text);
- else
- {
- if (!flprot_edit (savecmd, *curfile_))
- return;
- }
-
- if (name_)
- dirfind (*curfile_, -1, name_, flprot_one, TRUE, FALSE);
- else
- flprot_one (*curfile_, &flag);
-
- if (!code_ && history)
- cmdstk_chg (savecmd);
- }
-
- /* <flprot_one>:
- * Process the protection code for a single file.
- */
- static
- void flprot_one (int j, int *flag_)
- {
- int status;
- char fullname[MAX_PATH];
-
- dirent_glue (fullname, FK_(j));
- flist_log ("%s %s", savecmd, fullname);
- if ((status = setprot (fullname, savecmd)) == -1)
- {
- warn2 ("Syntax error");
- *flag_ = FALSE; /* Don't continue after first error */
- }
- else
- flist_sysmsg(status);
- dirent_chk2 (j);
- }
-
- /* <flprot_edit>:
- * If no arguments were supplied to "flprot", enter cursor-oriented edit
- * of the protection code.
- */
-
- extern int prot_col;
-
- #define NEXT if (++edit > 15) edit = 0
- #define RUBOUT '\177'
-
- typedef struct {
- char SET, /* Character-if-set */
- old; /* Original character */
- int BIT, /* mask-bit (1=disable) */
- col; /* Column of this entry */
- } PTBL;
-
- static
- PTBL ptbl[16]; /* protection-state-bits */
-
- static int
- flprot_edit (
- char *set_,
- int curfile)
- {
- FILENT *z = FK_(curfile);
- int rline = curfile - crt_top(),
- j, k, jk, edit, command, level,
- abort = FALSE,
- complete= FALSE,
- cmdcol = dirent_ccol(),
- select [4]; /* Override-flags for code-selection */
- char c, d, *c_, *d_,
- cmdbfr [CRT_COLS];
-
- if (!M_opt
- || (prot_col < 0)
- || ((prot_col+19) > crt_width()) )
- {
- warn2 ("No protection-mask to edit");
- return (FALSE);
- }
-
- /*
- * The protection-mask is the last field of the "FLIST" display
- * line. The display corresponds (with blanks between groups of
- * four bits) to the bits in the protection mask, left-to-right
- * to LSB-to-MSB. Use dead reckoning to build an index table:
- */
- strcpy (cmdbfr, crtvec[rline]);
- for (j = 0, k = prot_col; j < 16; j++, k++)
- {
- ptbl[j].old = cmdbfr[k-1];
- ptbl[j].col = k;
- switch (j % 4)
- {
- case 0: ptbl[j].SET = 'R'; break;
- case 1: ptbl[j].SET = 'W'; break;
- case 2: ptbl[j].SET = 'E'; break;
- case 3: ptbl[j].SET = 'D'; k++; /* skip a space */
- }
- ptbl[j].BIT = 1 << j;
- }
- for (level = 0; level < 4; select[level++] = FALSE);
-
- /*
- * Now that I know what the codes are now, do the edit:
- */
- edit = 4; /* Start on OWNER field */
-
- while (!abort && !complete)
- {
- switch (level = edit/4)
- {
- case 0: d_ = "SYS"; break;
- case 1: d_ = "OWN"; break;
- case 2: d_ = "GRP"; break;
- case 3: d_ = "WLD";
- }
- for (c_ = &cmdbfr[cmdcol-1]; *d_; *c_++ = tohigh(*d_++))
- /*EMPTY*/;
-
- crt_text (cmdbfr, rline, 0);
- crt_move (rline+1, k = ptbl[edit].col);
- j = level * 4; /* 0, 4, 8, 12 = field index */
- k--; /* index into cmdbfr */
- c_ = &cmdbfr[k];
-
- switch (command = edtcmd_get())
- {
- case padENTER:
- case '\r':
- complete = TRUE;
- break;
- case CTL('C'):
- case CTL('U'):
- case CTL('X'):
- case CTL('Y'):
- abort = TRUE;
- sound_alarm ();
- break;
- case CTL('D'):
- case padLEFT:
- if (--edit < 0) edit = 15; break;
- case CTL('F'):
- case padRIGHT:
- NEXT; break;
- case padUP:
- if (ptbl[edit].old != _tolower(ptbl[edit].SET))
- *c_ = tohigh(ptbl[edit].SET);
- else
- *c_ = ptbl[edit].old;
- if (select[level]) *c_ = tohigh(*c_);
- NEXT;
- break;
- case padDOWN:
- if (ptbl[edit].old != '-')
- *c_ = tohigh('.');
- else
- *c_ = '-';
- if (select[level]) *c_ = tohigh(*c_);
- NEXT;
- break;
- case '?':
- case HELPKEY:
- flist_help (curfile, "PROTECTION");
- break;
- case 'y':
- case 'Y': /* do group select */
- select[level] = TRUE;
- for (jk = j; jk < j+4; jk++)
- {
- c_ = &cmdbfr[ptbl[jk].col-1];
- if (isalpha(*c_))
- *c_ = tohigh(_toupper(*c_));
- else
- *c_ = tohigh('.');
- }
- break;
- case 'n':
- case 'N': /* do group deselect */
- select[level] = FALSE;
- for (jk = j; jk < j+4; jk++)
- {
- c_ = &cmdbfr[ptbl[jk].col-1];
- c = ptbl[jk].old;
- if ((isalpha(*c_) && isalpha(c))
- || (ispunct(*c_) && ispunct(c)) )
- *c_ = c;
- }
- break;
- case ',':
- case padCOMMA:
- if (++level >= 4) level = 0;
- edit = level * 4;
- break;
- case RUBOUT: /* patch: would be nice to backtrack */
- default:
- sound_alarm ();
- }
- }
-
- /*
- * Now, if normal exit, go back over the list of protection bits
- * to make up the actual composite SET PROTECTION command.
- */
- if (!abort)
- {
- int colon, comma, didselect = FALSE;
-
- for (j = 0; j < 16; j++)
- {
- level = j/4;
- c = ptbl[j].old;
- d = toascii(cmdbfr[ptbl[j].col-1]); /* cf: 'tohigh()' */
- if ((isalpha(d) && ispunct(c))
- || (ispunct(d) && isalpha(c)) )
- select[level] = TRUE;
- if (select[level])
- didselect = TRUE;
- }
-
- if (!didselect)
- {
- flist_info ("No changes made");
- abort = TRUE;
- goto cleanup;
- }
-
- strcpy (set_, "PROTECT=("); /* Abbreviate to match FLIST */
- set_ = strnull(set_);
- comma = FALSE;
-
- for (j = 0; j < 16; j++)
- {
- if (select[level = j/4])
- {
- if ((j % 4) == 0)
- {
- switch (level)
- {
- case 0: c_ = "SYSTEM"; break;
- case 1: c_ = "OWNER"; break;
- case 2: c_ = "GROUP"; break;
- case 3: c_ = "WORLD";
- }
- if (comma) strcat (set_, ",");
- strcat (set_, c_);
- colon = FALSE;
- comma = TRUE;
- }
- set_ = strnull(set_);
- c_ = &cmdbfr[ptbl[j].col-1];
- if (isalpha(c = toascii(*c_)))
- {
- if (!colon)
- {
- strcat (set_, ":");
- set_ = strnull(set_);
- colon = TRUE;
- }
- sprintf (set_, "%c", _toupper(c));
- }
- }
- }
- strcat (set_, ") ");
- }
-
- cleanup:
- dds_line (curfile);
- return (!abort);
- }
-