home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / src / chmod.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  10.1 KB  |  468 lines

  1. /* Chmod command -- for the Midnight Commander
  2.    Copyright (C) 1994 Radek Doulik
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
  17.  */
  18.  
  19. #include <config.h>
  20. #include <string.h>
  21. #include <stdio.h>
  22. /* Needed for the extern declarations of integer parameters */
  23. #include <sys/types.h>
  24. #include <sys/param.h>
  25. #include <sys/stat.h>
  26. #include <grp.h>
  27. #include <pwd.h>
  28. #ifdef HAVE_UNISTD_H
  29. #   include <unistd.h>
  30. #endif
  31. #include "tty.h"
  32. #include "mad.h"
  33. #include "util.h"
  34. #include "win.h"
  35. #include "color.h"
  36. #include "dlg.h"
  37. #include "widget.h"
  38. #include "dialog.h"    /* For do_refresh() */
  39.  
  40. #include "dir.h"
  41. #include "panel.h"        /* Needed for the externs */
  42. #include "file.h"
  43. #include "main.h"
  44. #include "chmod.h"
  45. #include "achown.h"
  46. #include "chown.h"
  47.  
  48. static int single_set;
  49. struct Dlg_head *ch_dlg;
  50.  
  51. #define PX        5
  52. #define PY        2
  53.  
  54. #define FX        40
  55. #define FY        2
  56.  
  57. #define BX        6
  58. #define BY        17
  59.  
  60. #define TX        40
  61. #define TY        12
  62.  
  63. #define PERMISSIONS    12
  64. #define BUTTONS        6
  65.  
  66. #define B_MARKED    B_USER
  67. #define B_ALL        B_USER+1
  68. #define B_SETMRK        B_USER+2
  69. #define B_CLRMRK        B_USER+3
  70.  
  71. int mode_change, need_update;
  72. int c_file, end_chmod;
  73.  
  74. umode_t and_mask, or_mask, c_stat;
  75. char *c_fname, *c_fown, *c_fgrp, *c_fperm;
  76. int c_fsize;
  77.  
  78. static WLabel *statl;
  79. static int normal_color;
  80. static int title_color;
  81. static int selection_color;
  82.  
  83. struct {
  84.     mode_t mode;
  85.     char *text;
  86.     int selected;
  87.     WCheck *check;
  88. } check_perm[PERMISSIONS] = {
  89.  
  90.     {
  91.     S_IXOTH, "execute/search by others", 0, 0,
  92.     },
  93.     {
  94.     S_IWOTH, "write by others", 0, 0,
  95.     },
  96.     {
  97.     S_IROTH, "read by others", 0, 0,
  98.     },
  99.     {
  100.     S_IXGRP, "execute/search by group", 0, 0,
  101.     },
  102.     {
  103.     S_IWGRP, "write by group", 0, 0,
  104.     },
  105.     {
  106.     S_IRGRP, "read by group", 0, 0,
  107.     },
  108.     {
  109.     S_IXUSR, "execute/search by owner", 0, 0,
  110.     },
  111.     {
  112.     S_IWUSR, "write by owner", 0, 0,
  113.     },
  114.     {
  115.     S_IRUSR, "read by owner", 0, 0,
  116.     },
  117.     {
  118.     S_ISVTX, "sticky bit", 0, 0,
  119.     },
  120.     {
  121.     S_ISGID, "set group ID on execution", 0, 0,
  122.     },
  123.     {
  124.     S_ISUID, "set user ID on execution", 0, 0,
  125.     },
  126. };
  127.  
  128. struct {
  129.     int ret_cmd, y, x;
  130.     char *text;
  131.     int hkey, hpos;
  132. } chmod_but[BUTTONS] = {
  133.  
  134.     {
  135.     B_CANCEL, 2, 33, "[ Cancel ]", 'c', 2,
  136.     },
  137.     {
  138.     B_ENTER, 2, 17, "[ Set ]", 's', 2,
  139.     },
  140.     {
  141.     B_CLRMRK, 0, 42, "[ Clear marked ]", 'l', 3,
  142.     },
  143.     {
  144.     B_SETMRK, 0, 27, "[ Set marked ]", 'e', 3,
  145.     },
  146.     {
  147.     B_MARKED, 0, 12, "[ Marked all ]", 'm', 2,
  148.     },
  149.     {
  150.     B_ALL, 0, 0, "[ Set all ]", 'a', 6,
  151.     },
  152. };
  153.  
  154. #ifdef HAVE_X
  155. static void chmod_toggle_select (void)
  156. {
  157. #ifdef HAVE_TK
  158.     char *wn = (char *) ch_dlg->current->widget->wdata;
  159.     int  id = ch_dlg->current->dlg_id -BUTTONS + single_set * 2;
  160.     
  161.     check_perm [id].selected ^= 1;
  162.  
  163.     tk_evalf ("%s configure -color $setup(%s)",
  164.           wn+1, check_perm [id].selected ? "marked":"black");
  165. #endif
  166. }
  167.  
  168. #else
  169. static void chmod_toggle_select (void)
  170. {
  171.     int Id = ch_dlg->current->dlg_id - BUTTONS + single_set * 2;
  172.  
  173.     attrset (normal_color);
  174.     check_perm[Id].selected ^= 1;
  175.  
  176.     dlg_move (ch_dlg, PY + PERMISSIONS - Id, PX + 1);
  177.     addch ((check_perm[Id].selected) ? '*' : ' ');
  178.     dlg_move (ch_dlg, PY + PERMISSIONS - Id, PX + 3);
  179. }
  180.  
  181. static void chmod_refresh (void)
  182. {
  183.     attrset (REVERSE_COLOR);
  184.     dlg_erase (ch_dlg);
  185.     
  186.     draw_box (ch_dlg, 1, 2, 20 - single_set, 66);
  187.     draw_box (ch_dlg, PY, PX, PERMISSIONS + 2, 33);
  188.     draw_box (ch_dlg, FY, FX, 10, 25);
  189.  
  190.     dlg_move (ch_dlg, FY + 1, FX + 2);
  191.     addstr ("Name");
  192.     dlg_move (ch_dlg, FY + 3, FX + 2);
  193.     addstr ("Permissions (Octal)");
  194.     dlg_move (ch_dlg, FY + 5, FX + 2);
  195.     addstr ("Owner name");
  196.     dlg_move (ch_dlg, FY + 7, FX + 2);
  197.     addstr ("Group name");
  198.     
  199.     attrset (title_color);
  200.     dlg_move (ch_dlg, 1, 28);
  201.     addstr (" Chmod command ");
  202.     dlg_move (ch_dlg, PY, PX + 1);
  203.     addstr (" Permission ");
  204.     dlg_move (ch_dlg, FY, FX + 1);
  205.     addstr (" File ");
  206.     
  207.     attrset (selection_color);
  208.  
  209.     dlg_move (ch_dlg, TY, TX);
  210.     addstr ("Use SPACE to change");
  211.     dlg_move (ch_dlg, TY + 1, TX);
  212.     addstr ("an option, ARROW KEYS");
  213.     dlg_move (ch_dlg, TY + 2, TX);
  214.     addstr ("to move between options");
  215.     dlg_move (ch_dlg, TY + 3, TX);
  216.     addstr ("and T or INS to mark");
  217. }
  218. #endif
  219.  
  220. static int chmod_callback (Dlg_head *h, int Par, int Msg)
  221. {
  222.     char buffer [10];
  223.     
  224.     switch (Msg) {
  225.     case DLG_ACTION:
  226.     if (Par >= BUTTONS - single_set * 2){
  227.         c_stat ^= check_perm[Par - BUTTONS + single_set * 2].mode;
  228.         sprintf (buffer, "%o", c_stat);
  229.         label_set_text (statl, buffer);
  230.         chmod_toggle_select ();
  231.         mode_change = 1;
  232.     }
  233.     break;
  234.  
  235.     case DLG_KEY:
  236.     if ((Par == 'T' || Par == 't' || Par == KEY_IC) &&
  237.         ch_dlg->current->dlg_id >= BUTTONS - single_set * 2) {
  238.         chmod_toggle_select ();
  239.         if (Par == KEY_IC)
  240.         dlg_one_down (ch_dlg);
  241.         return 1;
  242.     }
  243.     break;
  244. #ifndef HAVE_X
  245.     case DLG_DRAW:
  246.     chmod_refresh ();
  247.     break;
  248. #endif
  249.     }
  250.     return 0;
  251. }
  252.  
  253. static void init_chmod (void)
  254. {
  255.     int i;
  256.  
  257.     do_refresh ();
  258.     end_chmod = c_file = need_update = 0;
  259.     single_set = (cpanel->marked < 2) ? 2 : 0;
  260.  
  261.     if (use_colors){
  262.     normal_color = COLOR_NORMAL;
  263.     title_color  = COLOR_HOT_NORMAL;
  264.     selection_color = COLOR_NORMAL;
  265.     } else {
  266.     normal_color = NORMAL_COLOR;
  267.     title_color  = SELECTED_COLOR;
  268.     selection_color = SELECTED_COLOR;
  269.     }
  270.     
  271.     ch_dlg = create_dlg (0, 0, 22 - single_set, 70, dialog_colors,
  272.              chmod_callback, "[Chmod]", "chmod", DLG_CENTER);
  273.              
  274.     x_set_dialog_title (ch_dlg, "Chmod command");
  275.  
  276. #define XTRACT(i) BY+chmod_but[i].y-single_set, BX+chmod_but[i].x, \
  277.                   chmod_but[i].ret_cmd, chmod_but[i].text, chmod_but[i].hkey,                    chmod_but[i].hpos, 0, 0
  278.  
  279.     tk_new_frame (ch_dlg, "b.");
  280.     for (i = 0; i < BUTTONS; i++) {
  281.     if (i == 2 && single_set)
  282.         break;
  283.     else
  284.         add_widgetl (ch_dlg, button_new (XTRACT (i)), XV_WLAY_RIGHTOF);
  285.     }
  286.  
  287.  
  288. #define XTRACT2(i) 0, check_perm [i].text, 0,-1
  289.     tk_new_frame (ch_dlg, "c.");
  290.     for (i = 0; i < PERMISSIONS; i++) {
  291.     check_perm[i].check = check_new (PY + (PERMISSIONS - i), PX + 2,
  292.                      XTRACT2 (i));
  293.     add_widget (ch_dlg, check_perm[i].check);
  294.     }
  295. }
  296.  
  297. int stat_file (char *filename, struct stat *st)
  298. {
  299.     if (stat (filename, st))
  300.     return 0;
  301.     if (!(S_ISREG(st->st_mode) || S_ISDIR(st->st_mode) ||
  302.       S_ISLNK(st->st_mode)))
  303.     return 0;
  304.  
  305.     return 1;
  306. }
  307.  
  308. static void chmod_done (void)
  309. {
  310.     if (need_update)
  311.     update_panels (UP_OPTIMIZE, UP_KEEPSEL, UP_KEEPSEL);
  312.     repaint_screen ();
  313. }
  314.  
  315. static char *next_file (void)
  316. {
  317.     while (!cpanel->dir.list[c_file].f.marked)
  318.     c_file++;
  319.  
  320.     return cpanel->dir.list[c_file].fname;
  321. }
  322.  
  323. static void do_chmod (struct stat *sf)
  324. {
  325.     sf->st_mode &= and_mask;
  326.     sf->st_mode |= or_mask;
  327.     chmod (cpanel->dir.list [c_file].fname, sf->st_mode);
  328.     file_mark (cpanel, c_file, 0);
  329. }
  330.  
  331. static void apply_mask (struct stat *sf)
  332. {
  333.     char *fname;
  334.  
  335.     need_update = end_chmod = 1;
  336.     do_chmod (sf);
  337.     cpanel->marked--;
  338.  
  339.     do {
  340.     fname = next_file ();
  341.     if (!stat_file (fname, sf))
  342.         return;
  343.     c_stat = sf->st_mode;
  344.  
  345.     do_chmod (sf);
  346.     cpanel->marked--;
  347.     } while (cpanel->marked);
  348. }
  349.  
  350. void chmod_cmd (void)
  351. {
  352.     char buffer [10];
  353.     char *fname;
  354.     int i;
  355.     struct stat sf_stat;
  356.  
  357.     do {            /* do while any files remaining */
  358.     init_chmod ();
  359.     if (cpanel->marked)
  360.         fname = next_file ();    /* next marked file */
  361.     else
  362.         fname = selection (cpanel)->fname;    /* single file */
  363.  
  364.     if (!stat_file (fname, &sf_stat))    /* get status of file */
  365.         break;
  366.     
  367.     c_stat = sf_stat.st_mode;
  368.     mode_change = 0;    /* clear changes flag */
  369.  
  370.     /* set check buttons */
  371.     for (i = 0; i < PERMISSIONS; i++){
  372.         check_perm[i].check->state = (c_stat & check_perm[i].mode) ? 1 : 0;
  373.         check_perm[i].selected = 0;
  374.     }
  375.  
  376.     tk_new_frame (ch_dlg, "l.");
  377.     /* Set the labels */
  378.     c_fname = name_trunc (fname, 21);
  379.     add_widget (ch_dlg, label_new (FY+2, FX+2, c_fname));
  380.     c_fown = name_trunc (get_owner (sf_stat.st_uid), 21);
  381.     add_widget (ch_dlg, label_new (FY+6, FX+2, c_fown));
  382.     c_fgrp = name_trunc (get_group (sf_stat.st_gid), 21);
  383.     add_widget (ch_dlg, label_new (FY+8, FX+2, c_fgrp));
  384.     sprintf (buffer, "%o", c_stat);
  385.     statl = label_new (FY+4, FX+2, buffer);
  386.     add_widget (ch_dlg, statl);
  387.     tk_end_frame ();
  388.     
  389.     run_dlg (ch_dlg);    /* retrieve an action */
  390.     
  391.     /* do action */
  392.     switch (ch_dlg->ret_value){
  393.     case B_ENTER:
  394.         if (mode_change)
  395.         chmod (fname, c_stat);
  396.         need_update = 1;
  397.         break;
  398.         
  399.     case B_CANCEL:
  400.         end_chmod = 1;
  401.         break;
  402.         
  403.     case B_ALL:
  404.     case B_MARKED:
  405.         and_mask = or_mask = 0;
  406.         and_mask = ~and_mask;
  407.  
  408.         for (i = 0; i < PERMISSIONS; i++) {
  409.         if (check_perm[i].selected || ch_dlg->ret_value == B_ALL)
  410.             if (check_perm[i].check->state & C_BOOL)
  411.             or_mask |= check_perm[i].mode;
  412.             else
  413.             and_mask &= ~check_perm[i].mode;
  414.         }
  415.  
  416.         apply_mask (&sf_stat);
  417.         break;
  418.         
  419.     case B_SETMRK:
  420.         and_mask = or_mask = 0;
  421.         and_mask = ~and_mask;
  422.  
  423.         for (i = 0; i < PERMISSIONS; i++) {
  424.         if (check_perm[i].selected)
  425.             or_mask |= check_perm[i].mode;
  426.         }
  427.  
  428.         apply_mask (&sf_stat);
  429.         break;
  430.     case B_CLRMRK:
  431.         and_mask = or_mask = 0;
  432.         and_mask = ~and_mask;
  433.  
  434.         for (i = 0; i < PERMISSIONS; i++) {
  435.         if (check_perm[i].selected)
  436.             and_mask &= ~check_perm[i].mode;
  437.         }
  438.  
  439.         apply_mask (&sf_stat);
  440.         break;
  441.     }
  442.  
  443.     if (cpanel->marked && ch_dlg->ret_value!=B_CANCEL) {
  444.         file_mark (cpanel, c_file, 0);
  445.         cpanel->marked--;
  446.         need_update = 1;
  447.     }
  448.     destroy_dlg (ch_dlg);
  449.     } while (cpanel->marked && !end_chmod);
  450.     chmod_done ();
  451. }
  452.  
  453. void ch1_cmd (int id)
  454. {
  455.   if (advanced_chfns)
  456.       chown_advanced_cmd ();
  457.   else
  458.       chmod_cmd ();
  459. }
  460.  
  461. void ch2_cmd (int id)
  462. {
  463.   if (advanced_chfns)
  464.       chown_advanced_cmd ();
  465.   else
  466.       chown_cmd ();
  467. }
  468.