home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / flistfrontend / src / flprot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-22  |  16.0 KB  |  415 lines

  1. #ifndef NO_IDENT
  2. static char *Id = "$Id: flprot.c,v 1.15 1995/10/22 22:07:44 tom Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Title:    flprot.c
  7.  * Author:    Thomas E. Dickey
  8.  * Created:    11 May 1984
  9.  * Last update:
  10.  *        22 Oct 1995, DEC-C treats chars in 128-255 range different from
  11.  *                 VAX-C (in the latter, none are punctuation/alpha).
  12.  *        18 Mar 1995, prototypes
  13.  *        18 Feb 1995, port to AXP (renamed 'alarm')
  14.  *        05 Oct 1985, added key-argument to 'flist_help'.
  15.  *        24 Sep 1985, corrected threshold-test on 'prot_col'.
  16.  *        04 Jul 1985, cleanup 'filelist' definition.
  17.  *        15 May 1985, use '_toupper' macro, not routine
  18.  *        05 May 1985, added history-flag
  19.  *        22 Apr 1985, use 'edtcmd', rather than 'dircmd' for input,
  20.  *                 do 'crt'-call directly for screen updates.
  21.  *        14 Apr 1985, use 'flist_info' for log-routing
  22.  *        08 Mar 1985, permit filespec as part of argument list.  If
  23.  *                 this is not the current file, protection-code
  24.  *                 must be explicit.
  25.  *        21 Dec 1984, corrected error returns from 'setprot'.
  26.  *        20 Dec 1984, use ^D, ^E for cursor movement.  Broke out 'isowner'.
  27.  *        10 Dec 1984, use 'dirent_chk2' instead of 'dirent_one'.
  28.  *                 Omit coercion to readonly since ACP does ok.
  29.  *        20 Nov 1984, use 'setprot' instead of spawning
  30.  *        19 Oct 1984, use 'cmdstk_chg' (broken from 'dircmd')
  31.  *        17 Oct 1984, use 'dircmd_GET' instead of 'getpad'
  32.  *        03 Sep 1984, use "import"
  33.  *        27 Aug 1984, cleanup of buffer sizes
  34.  *        14 Aug 1984, use 'dirent_ccol()'
  35.  *        14 Jul 1984, forgot to test 'M_opt' before edit
  36.  *        12 Jul 1984, corrected DCLARG usage, added help-call
  37.  *        10 Jul 1984, re-coded for DCLARG-list
  38.  *        22 May 1984
  39.  *
  40.  * Function:    This module supports an edit-function for the protection-
  41.  *        code field displayed (last on each line) by "FLIST".  As
  42.  *        each change to the original code is made, it is highlighted
  43.  *        (and uppercased, for VT52, etc.) to show the user what he
  44.  *        has changed.  On successful completion of the editing,
  45.  *        a "SET PROTECTION" command is constructed, and saved for
  46.  *        retrieval (if the procedure is entered as a "visible"
  47.  *        command).
  48.  *
  49.  *        This function operates only on the current entry of the
  50.  *        file-list.
  51.  *
  52.  * Commands:    left-arrow    - move left (with wrap-around)
  53.  *        right-arrow    - move right (with wrap-around)
  54.  *        up-arrow    - set the current bit
  55.  *        down-arrow    - clear the current bit
  56.  *        y        - select entire field (even if no change)
  57.  *        n        - deselect field
  58.  *        ,        - Move to next group
  59.  *        CTRL/U, CTRL/X    - abort edit
  60.  *        ENTER, RETURN    - complete edit, submit command
  61.  */
  62.  
  63. #include    <stdlib.h>
  64. #include    <stdio.h>
  65. #include    <ctype.h>
  66. #include    <string.h>
  67.  
  68. #include    "cmdstk.h"
  69. #include    "flist.h"
  70. #include    "dirent.h"
  71. #include    "getpad.h"
  72. #include    "getprot.h"
  73. #include    "dircmd.h"
  74. #include    "edtcmd.h"
  75. #include    "dirfind.h"
  76. #include    "dds.h"
  77.  
  78. #include    "strutils.h"
  79.  
  80. extern    int    isowner(FILENT *z);
  81.  
  82. static    int    flprot_edit (char *set_, int curfile);
  83. static    void    flprot_one(int, int *);    /* function via 'dirfind'    */
  84.  
  85. import(filelist);
  86. import(M_opt);
  87.  
  88. static    char *    savecmd = nullC;    /* Text of option-code to process */
  89.  
  90. tDIRCMD(flprot)
  91. {
  92.     FILENT    *z    = FK_(*curfile_);
  93.     DCLARG    *name_    = 0,        /* => filename specification    */
  94.         *code_    = 0;        /* => protection-code        */
  95.     int    no_edit    = FALSE,    /* TRUE iff code is specified    */
  96.         flag;
  97.     char    msg    [CRT_COLS],
  98.         fullname[MAX_PATH];
  99.  
  100.     if (!M_opt)
  101.     {
  102.         warn ("EDIT-PROTECTION is not applicable");
  103.         return;
  104.     }
  105.     dirent_glue (fullname, z);
  106.  
  107.     if (!isowner(z))    return;
  108.  
  109.     /*
  110.      * Analyze the argument list, if one was given.  It may fall into
  111.      * one of the following cases:
  112.      *
  113.      *    (a) No list: edit current file
  114.      *    (b) No code: name must be that of current file (edit it, if so).
  115.      *    (c) Code: apply this to the specified file(s).
  116.      */
  117.     if (xdcl_)
  118.     {
  119.         while (xdcl_ = xdcl_->dcl_next)
  120.         {
  121.             if (isopt(xdcl_->dcl_text[0]))
  122.                 code_ = xdcl_;
  123.             else
  124.                 name_ = xdcl_;
  125.         }
  126.         no_edit = (code_ != 0);
  127.         if ((code_ == 0) && (name_ != 0))
  128.         {
  129.             if (strcmp(fullname, name_->dcl_text))
  130.             {
  131.                 warn ("You must specify a protection code");
  132.                 return;
  133.             }
  134.         }
  135.     }
  136.  
  137.     /*
  138.      * If no code given, enter cursor-only edit of the protection code.
  139.      * Note that if a field is unspecified, it is not altered.  When
  140.      * complete, save this command for retrieval.
  141.      */
  142.     if (!savecmd)
  143.         savecmd = calloc(1, CRT_COLS);
  144.     if (no_edit)
  145.         sprintf (savecmd, "PROTECT %s", code_->dcl_text);
  146.     else
  147.     {
  148.         if (!flprot_edit (savecmd, *curfile_))
  149.             return;
  150.     }
  151.  
  152.     if (name_)
  153.         dirfind (*curfile_, -1, name_, flprot_one, TRUE, FALSE);
  154.     else
  155.         flprot_one (*curfile_, &flag);
  156.  
  157.     if (!code_ && history)
  158.         cmdstk_chg (savecmd);
  159. }
  160.  
  161. /* <flprot_one>:
  162.  * Process the protection code for a single file.
  163.  */
  164. static
  165. void    flprot_one (int j, int *flag_)
  166. {
  167.     int    status;
  168.     char    fullname[MAX_PATH];
  169.  
  170.     dirent_glue (fullname, FK_(j));
  171.     flist_log ("%s %s", savecmd, fullname);
  172.     if ((status = setprot (fullname, savecmd)) == -1)
  173.     {
  174.         warn2 ("Syntax error");
  175.         *flag_ = FALSE;        /* Don't continue after first error */
  176.     }
  177.     else
  178.         flist_sysmsg(status);
  179.     dirent_chk2 (j);
  180. }
  181.  
  182. /* <flprot_edit>:
  183.  * If no arguments were supplied to "flprot", enter cursor-oriented edit
  184.  * of the protection code.
  185.  */
  186.  
  187. extern    int    prot_col;
  188.  
  189. #define    NEXT    if (++edit > 15) edit = 0
  190. #define    RUBOUT    '\177'
  191.  
  192. typedef    struct    {
  193.     char    SET,        /* Character-if-set    */
  194.         old;        /* Original character    */
  195.     int    BIT,        /* mask-bit (1=disable)    */
  196.         col;        /* Column of this entry    */
  197.     } PTBL;
  198.  
  199. static
  200. PTBL    ptbl[16];        /* protection-state-bits    */
  201.  
  202. static int
  203. flprot_edit (
  204.     char    *set_,
  205.     int    curfile)
  206. {
  207.     FILENT    *z    = FK_(curfile);
  208.     int    rline    = curfile - crt_top(),
  209.         j, k, jk, edit, command, level,
  210.         abort    = FALSE,
  211.         complete= FALSE,
  212.         cmdcol    = dirent_ccol(),
  213.         select    [4];        /* Override-flags for code-selection */
  214.     char    c, d, *c_, *d_,
  215.         cmdbfr    [CRT_COLS];
  216.  
  217.     if (!M_opt
  218.     ||  (prot_col < 0)
  219.     ||  ((prot_col+19) > crt_width()) )
  220.     {
  221.         warn2 ("No protection-mask to edit");
  222.         return (FALSE);
  223.     }
  224.  
  225.     /*
  226.      * The protection-mask is the last field of the "FLIST" display
  227.      * line.  The display corresponds (with blanks between groups of
  228.      * four bits) to the bits in the protection mask, left-to-right
  229.      * to LSB-to-MSB.  Use dead reckoning to build an index table:
  230.      */
  231.     strcpy (cmdbfr, crtvec[rline]);
  232.     for (j = 0, k = prot_col; j < 16; j++, k++)
  233.     {
  234.         ptbl[j].old = cmdbfr[k-1];
  235.         ptbl[j].col = k;
  236.         switch (j % 4)
  237.         {
  238.         case 0:    ptbl[j].SET = 'R';    break;
  239.         case 1:    ptbl[j].SET = 'W';    break;
  240.         case 2:    ptbl[j].SET = 'E';    break;
  241.         case 3:    ptbl[j].SET = 'D';    k++;    /* skip a space */
  242.         }
  243.         ptbl[j].BIT = 1 << j;
  244.     }
  245.     for (level = 0; level < 4; select[level++] = FALSE);
  246.  
  247.     /*
  248.      * Now that I know what the codes are now, do the edit:
  249.      */
  250.     edit = 4;            /* Start on OWNER field    */
  251.  
  252.     while (!abort && !complete)
  253.     {
  254.         switch (level = edit/4)
  255.         {
  256.         case 0:    d_ = "SYS";    break;
  257.         case 1:    d_ = "OWN";    break;
  258.         case 2:    d_ = "GRP";    break;
  259.         case 3: d_ = "WLD";
  260.         }
  261.         for (c_ = &cmdbfr[cmdcol-1]; *d_; *c_++ = tohigh(*d_++))
  262.             /*EMPTY*/;
  263.  
  264.         crt_text (cmdbfr, rline, 0);
  265.         crt_move (rline+1, k = ptbl[edit].col);
  266.         j = level * 4;        /* 0, 4, 8, 12 = field index    */
  267.         k--;            /* index into cmdbfr        */
  268.         c_ = &cmdbfr[k];
  269.  
  270.         switch (command = edtcmd_get())
  271.         {
  272.         case padENTER:
  273.         case '\r':
  274.             complete = TRUE;
  275.             break;
  276.         case CTL('C'):
  277.         case CTL('U'):
  278.         case CTL('X'):
  279.         case CTL('Y'):
  280.             abort = TRUE;
  281.             sound_alarm ();
  282.             break;
  283.         case CTL('D'):
  284.         case padLEFT:
  285.             if (--edit < 0) edit = 15;    break;
  286.         case CTL('F'):
  287.         case padRIGHT:
  288.             NEXT;                break;
  289.         case padUP:
  290.             if (ptbl[edit].old != _tolower(ptbl[edit].SET))
  291.                 *c_ = tohigh(ptbl[edit].SET);
  292.             else
  293.                 *c_ = ptbl[edit].old;
  294.             if (select[level])    *c_ = tohigh(*c_);
  295.             NEXT;
  296.             break;
  297.         case padDOWN:
  298.             if (ptbl[edit].old != '-')
  299.                 *c_ = tohigh('.');
  300.             else
  301.                 *c_ = '-';
  302.             if (select[level])    *c_ = tohigh(*c_);
  303.             NEXT;
  304.             break;
  305.         case '?':
  306.         case HELPKEY:
  307.             flist_help (curfile, "PROTECTION");
  308.             break;
  309.         case 'y':
  310.         case 'Y':    /* do group select */
  311.             select[level] = TRUE;
  312.             for (jk = j; jk < j+4; jk++)
  313.             {
  314.                 c_ = &cmdbfr[ptbl[jk].col-1];
  315.                 if (isalpha(*c_))
  316.                     *c_ = tohigh(_toupper(*c_));
  317.                 else
  318.                     *c_ = tohigh('.');
  319.             }
  320.             break;
  321.         case 'n':
  322.         case 'N':    /* do group deselect */
  323.             select[level] = FALSE;
  324.             for (jk = j; jk < j+4; jk++)
  325.             {
  326.                 c_ = &cmdbfr[ptbl[jk].col-1];
  327.                 c  = ptbl[jk].old;
  328.                 if ((isalpha(*c_) && isalpha(c))
  329.                 ||  (ispunct(*c_) && ispunct(c)) )
  330.                     *c_ = c;
  331.             }
  332.             break;
  333.         case ',':
  334.         case padCOMMA:
  335.             if (++level >= 4)    level = 0;
  336.             edit = level * 4;
  337.             break;
  338.         case RUBOUT:    /* patch: would be nice to backtrack */
  339.         default:
  340.             sound_alarm ();
  341.         }
  342.     }
  343.  
  344.     /*
  345.      * Now, if normal exit, go back over the list of protection bits
  346.      * to make up the actual composite SET PROTECTION command.
  347.      */
  348.     if (!abort)
  349.     {
  350.         int    colon, comma, didselect = FALSE;
  351.  
  352.         for (j = 0; j < 16; j++)
  353.         {
  354.             level = j/4;
  355.             c = ptbl[j].old;
  356.             d = toascii(cmdbfr[ptbl[j].col-1]); /* cf: 'tohigh()' */
  357.             if ((isalpha(d) && ispunct(c))
  358.             ||  (ispunct(d) && isalpha(c)) )
  359.                 select[level] = TRUE;
  360.             if (select[level])
  361.                 didselect = TRUE;
  362.         }
  363.  
  364.         if (!didselect)
  365.         {
  366.             flist_info ("No changes made");
  367.             abort = TRUE;
  368.             goto cleanup;
  369.         }
  370.  
  371.         strcpy (set_, "PROTECT=(");    /* Abbreviate to match FLIST */
  372.         set_ = strnull(set_);
  373.         comma = FALSE;
  374.  
  375.         for (j = 0; j < 16; j++)
  376.         {
  377.             if (select[level = j/4])
  378.             {
  379.                 if ((j % 4) == 0)
  380.                 {
  381.                     switch (level)
  382.                     {
  383.                     case 0:    c_ = "SYSTEM";    break;
  384.                     case 1:    c_ = "OWNER";    break;
  385.                     case 2:    c_ = "GROUP";    break;
  386.                     case 3:    c_ = "WORLD";
  387.                     }
  388.                     if (comma) strcat (set_, ",");
  389.                     strcat (set_, c_);
  390.                     colon = FALSE;
  391.                     comma = TRUE;
  392.                 }
  393.                 set_ = strnull(set_);
  394.                 c_   = &cmdbfr[ptbl[j].col-1];
  395.                 if (isalpha(c = toascii(*c_)))
  396.                 {
  397.                     if (!colon)
  398.                     {
  399.                         strcat (set_, ":");
  400.                         set_ = strnull(set_);
  401.                         colon = TRUE;
  402.                     }
  403.                     sprintf (set_, "%c", _toupper(c));
  404.                 }
  405.             }
  406.         }
  407.         strcat (set_, ") ");
  408.     }
  409.  
  410. cleanup:
  411.     dds_line (curfile);
  412.     return (!abort);
  413. }
  414.