Just a little correction at the it.po file.
[midnight-commander.git] / src / chmod.c
blobd2cfd503a8002594024bc058f19cde53371b5052
1 /* Chmod command -- for the Midnight Commander
2 Copyright (C) 1994 Radek Doulik
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include <config.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <errno.h> /* For errno on SunOS systems */
23 /* Needed for the extern declarations of integer parameters */
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #ifdef HAVE_UNISTD_H
27 # include <unistd.h>
28 #endif
30 #include "global.h"
31 #include "tty.h" /* A_REVERSE */
32 #include "color.h" /* dialog_colors */
33 #include "dlg.h" /* add_widget() */
34 #include "widget.h" /* NORMAL_BUTTON */
35 #include "dialog.h" /* do_refresh() */
36 #include "wtools.h" /* message() */
37 #include "panel.h" /* do_file_mark() */
38 #include "main.h" /* update_panels() */
39 #include "chmod.h"
41 static int single_set;
43 #define PX 5
44 #define PY 2
46 #define FX 40
47 #define FY 2
49 #define BX 6
50 #define BY 17
52 #define TX 40
53 #define TY 12
55 #define PERMISSIONS 12
56 #define BUTTONS 6
58 #define B_MARKED B_USER
59 #define B_ALL B_USER+1
60 #define B_SETMRK B_USER+2
61 #define B_CLRMRK B_USER+3
63 static int mode_change, need_update;
64 static int c_file, end_chmod;
66 static umode_t and_mask, or_mask, c_stat;
67 static char *c_fname, *c_fown, *c_fgrp;
69 static WLabel *statl;
71 static struct {
72 mode_t mode;
73 char *text;
74 int selected;
75 WCheck *check;
76 } check_perm[PERMISSIONS] =
78 { S_IXOTH, N_("execute/search by others"), 0, 0, },
79 { S_IWOTH, N_("write by others"), 0, 0, },
80 { S_IROTH, N_("read by others"), 0, 0, },
81 { S_IXGRP, N_("execute/search by group"), 0, 0, },
82 { S_IWGRP, N_("write by group"), 0, 0, },
83 { S_IRGRP, N_("read by group"), 0, 0, },
84 { S_IXUSR, N_("execute/search by owner"), 0, 0, },
85 { S_IWUSR, N_("write by owner"), 0, 0, },
86 { S_IRUSR, N_("read by owner"), 0, 0, },
87 { S_ISVTX, N_("sticky bit"), 0, 0, },
88 { S_ISGID, N_("set group ID on execution"), 0, 0, },
89 { S_ISUID, N_("set user ID on execution"), 0, 0, },
92 static struct {
93 int ret_cmd, flags, y, x;
94 char *text;
95 } chmod_but[BUTTONS] =
97 { B_CANCEL, NORMAL_BUTTON, 2, 33, N_("&Cancel") },
98 { B_ENTER, DEFPUSH_BUTTON, 2, 17, N_("&Set") },
99 { B_CLRMRK, NORMAL_BUTTON, 0, 42, N_("C&lear marked") },
100 { B_SETMRK, NORMAL_BUTTON, 0, 27, N_("S&et marked") },
101 { B_MARKED, NORMAL_BUTTON, 0, 12, N_("&Marked all") },
102 { B_ALL, NORMAL_BUTTON, 0, 0, N_("Set &all") },
105 static void chmod_toggle_select (Dlg_head *h)
107 int Id = h->current->dlg_id - BUTTONS + single_set * 2;
109 attrset (COLOR_NORMAL);
110 check_perm[Id].selected ^= 1;
112 dlg_move (h, PY + PERMISSIONS - Id, PX + 1);
113 addch ((check_perm[Id].selected) ? '*' : ' ');
114 dlg_move (h, PY + PERMISSIONS - Id, PX + 3);
117 static void chmod_refresh (Dlg_head *h)
119 common_dialog_repaint (h);
121 attrset (COLOR_NORMAL);
123 draw_box (h, PY, PX, PERMISSIONS + 2, 33);
124 draw_box (h, FY, FX, 10, 25);
126 dlg_move (h, FY + 1, FX + 2);
127 addstr (_("Name"));
128 dlg_move (h, FY + 3, FX + 2);
129 addstr (_("Permissions (Octal)"));
130 dlg_move (h, FY + 5, FX + 2);
131 addstr (_("Owner name"));
132 dlg_move (h, FY + 7, FX + 2);
133 addstr (_("Group name"));
135 dlg_move (h, TY, TX);
136 addstr (_("Use SPACE to change"));
137 dlg_move (h, TY + 1, TX);
138 addstr (_("an option, ARROW KEYS"));
139 dlg_move (h, TY + 2, TX);
140 addstr (_("to move between options"));
141 dlg_move (h, TY + 3, TX);
142 addstr (_("and T or INS to mark"));
144 attrset (COLOR_HOT_NORMAL);
146 dlg_move (h, PY, PX + 1);
147 addstr (_(" Permission "));
148 dlg_move (h, FY, FX + 1);
149 addstr (_(" File "));
152 static int chmod_callback (Dlg_head *h, int Par, int Msg)
154 char buffer [BUF_TINY];
156 switch (Msg) {
157 case DLG_ACTION:
158 if (Par >= BUTTONS - single_set * 2){
159 c_stat ^= check_perm[Par - BUTTONS + single_set * 2].mode;
160 g_snprintf (buffer, sizeof (buffer), "%o", c_stat);
161 label_set_text (statl, buffer);
162 chmod_toggle_select (h);
163 mode_change = 1;
165 break;
167 case DLG_KEY:
168 if ((Par == 'T' || Par == 't' || Par == KEY_IC) &&
169 h->current->dlg_id >= BUTTONS - single_set * 2) {
170 chmod_toggle_select (h);
171 if (Par == KEY_IC)
172 dlg_one_down (h);
173 return 1;
175 break;
177 case DLG_DRAW:
178 chmod_refresh (h);
179 break;
181 return 0;
184 static Dlg_head *
185 init_chmod (void)
187 int i;
188 Dlg_head *ch_dlg;
190 do_refresh ();
191 end_chmod = c_file = need_update = 0;
192 single_set = (cpanel->marked < 2) ? 2 : 0;
194 ch_dlg =
195 create_dlg (0, 0, 22 - single_set, 70, dialog_colors,
196 chmod_callback, "[Chmod]", _("Chmod command"),
197 DLG_CENTER);
199 for (i = 0; i < BUTTONS; i++) {
200 if (i == 2 && single_set)
201 break;
202 else
203 add_widget (ch_dlg,
204 button_new (BY + chmod_but[i].y - single_set,
205 BX + chmod_but[i].x,
206 chmod_but[i].ret_cmd,
207 chmod_but[i].flags,
208 _(chmod_but[i].text), 0, 0, NULL));
211 for (i = 0; i < PERMISSIONS; i++) {
212 check_perm[i].check =
213 check_new (PY + (PERMISSIONS - i), PX + 2, 0,
214 _(check_perm[i].text), NULL);
215 add_widget (ch_dlg, check_perm[i].check);
218 return ch_dlg;
221 int stat_file (char *filename, struct stat *st)
223 if (mc_stat (filename, st))
224 return 0;
226 return 1;
229 static void chmod_done (void)
231 if (need_update)
232 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
233 repaint_screen ();
236 static char *next_file (void)
238 while (!cpanel->dir.list[c_file].f.marked)
239 c_file++;
241 return cpanel->dir.list[c_file].fname;
244 static void do_chmod (struct stat *sf)
246 sf->st_mode &= and_mask;
247 sf->st_mode |= or_mask;
248 if (mc_chmod (cpanel->dir.list [c_file].fname, sf->st_mode) == -1)
249 message (1, MSG_ERROR, _(" Cannot chmod \"%s\" \n %s "),
250 cpanel->dir.list [c_file].fname, unix_error_string (errno));
252 do_file_mark (cpanel, c_file, 0);
255 static void apply_mask (struct stat *sf)
257 char *fname;
259 need_update = end_chmod = 1;
260 do_chmod (sf);
262 do {
263 fname = next_file ();
264 if (!stat_file (fname, sf))
265 return;
266 c_stat = sf->st_mode;
268 do_chmod (sf);
269 } while (cpanel->marked);
272 void chmod_cmd (void)
274 char buffer [BUF_TINY];
275 char *fname;
276 int i;
277 struct stat sf_stat;
278 Dlg_head *ch_dlg;
280 do { /* do while any files remaining */
281 ch_dlg = init_chmod ();
282 if (cpanel->marked)
283 fname = next_file (); /* next marked file */
284 else
285 fname = selection (cpanel)->fname; /* single file */
287 if (!stat_file (fname, &sf_stat)){ /* get status of file */
288 destroy_dlg (ch_dlg);
289 break;
292 c_stat = sf_stat.st_mode;
293 mode_change = 0; /* clear changes flag */
295 /* set check buttons */
296 for (i = 0; i < PERMISSIONS; i++){
297 check_perm[i].check->state = (c_stat & check_perm[i].mode) ? 1 : 0;
298 check_perm[i].selected = 0;
301 /* Set the labels */
302 c_fname = name_trunc (fname, 21);
303 add_widget (ch_dlg, label_new (FY+2, FX+2, c_fname, NULL));
304 c_fown = name_trunc (get_owner (sf_stat.st_uid), 21);
305 add_widget (ch_dlg, label_new (FY+6, FX+2, c_fown, NULL));
306 c_fgrp = name_trunc (get_group (sf_stat.st_gid), 21);
307 add_widget (ch_dlg, label_new (FY+8, FX+2, c_fgrp, NULL));
308 g_snprintf (buffer, sizeof (buffer), "%o", c_stat);
309 statl = label_new (FY+4, FX+2, buffer, NULL);
310 add_widget (ch_dlg, statl);
312 run_dlg (ch_dlg); /* retrieve an action */
314 /* do action */
315 switch (ch_dlg->ret_value){
316 case B_ENTER:
317 if (mode_change)
318 if (mc_chmod (fname, c_stat) == -1)
319 message (1, MSG_ERROR, _(" Cannot chmod \"%s\" \n %s "),
320 fname, unix_error_string (errno));
321 need_update = 1;
322 break;
324 case B_CANCEL:
325 end_chmod = 1;
326 break;
328 case B_ALL:
329 case B_MARKED:
330 and_mask = or_mask = 0;
331 and_mask = ~and_mask;
333 for (i = 0; i < PERMISSIONS; i++) {
334 if (check_perm[i].selected || ch_dlg->ret_value == B_ALL) {
335 if (check_perm[i].check->state & C_BOOL)
336 or_mask |= check_perm[i].mode;
337 else
338 and_mask &= ~check_perm[i].mode;
342 apply_mask (&sf_stat);
343 break;
345 case B_SETMRK:
346 and_mask = or_mask = 0;
347 and_mask = ~and_mask;
349 for (i = 0; i < PERMISSIONS; i++) {
350 if (check_perm[i].selected)
351 or_mask |= check_perm[i].mode;
354 apply_mask (&sf_stat);
355 break;
356 case B_CLRMRK:
357 and_mask = or_mask = 0;
358 and_mask = ~and_mask;
360 for (i = 0; i < PERMISSIONS; i++) {
361 if (check_perm[i].selected)
362 and_mask &= ~check_perm[i].mode;
365 apply_mask (&sf_stat);
366 break;
369 if (cpanel->marked && ch_dlg->ret_value!=B_CANCEL) {
370 do_file_mark (cpanel, c_file, 0);
371 need_update = 1;
373 destroy_dlg (ch_dlg);
374 } while (cpanel->marked && !end_chmod);
375 chmod_done ();