This source file includes following definitions.
- chown_init
- chown_refresh
- chown_bg_callback
- chown_dlg_create
- chown_done
- try_chown
- do_chown
- apply_chowns
- chown_cmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 #include <config.h>
28
29 #include <errno.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <pwd.h>
33 #include <grp.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37
38 #include "lib/global.h"
39
40 #include "lib/tty/tty.h"
41 #include "lib/skin.h"
42 #include "lib/vfs/vfs.h"
43 #include "lib/strutil.h"
44 #include "lib/util.h"
45 #include "lib/widget.h"
46
47 #include "src/setup.h"
48
49 #include "cmd.h"
50
51
52
53
54
55 #define GH 12
56 #define GW 21
57
58 #define BUTTONS 5
59
60 #define B_SETALL B_USER
61 #define B_SETUSR (B_USER + 1)
62 #define B_SETGRP (B_USER + 2)
63
64 #define LABELS 5
65
66 #define chown_label(n,txt) label_set_text (chown_label [n].l, txt)
67
68
69
70
71
72
73
74 static struct
75 {
76 int ret_cmd;
77 button_flags_t flags;
78 int y;
79 int len;
80 const char *text;
81 } chown_but[BUTTONS] = {
82
83 { B_SETALL, NORMAL_BUTTON, 5, 0, N_("Set &all") },
84 { B_SETGRP, NORMAL_BUTTON, 5, 0, N_("Set &groups") },
85 { B_SETUSR, NORMAL_BUTTON, 5, 0, N_("Set &users") },
86 { B_ENTER, DEFPUSH_BUTTON, 3, 0, N_("&Set") },
87 { B_CANCEL, NORMAL_BUTTON, 3, 0, N_("&Cancel") }
88
89 };
90
91
92 static int blen = 0;
93
94 static struct
95 {
96 int y;
97 WLabel *l;
98 } chown_label[LABELS] = {
99
100 { 4, NULL },
101 { 6, NULL },
102 { 8, NULL },
103 { 10, NULL },
104 { 12, NULL }
105
106 };
107
108 static int current_file;
109 static gboolean ignore_all;
110
111 static WListbox *l_user, *l_group;
112
113
114
115
116
117 static void
118 chown_init (void)
119 {
120 static gboolean i18n = FALSE;
121 int i;
122
123 if (i18n)
124 return;
125
126 i18n = TRUE;
127
128 #ifdef ENABLE_NLS
129 for (i = 0; i < BUTTONS; i++)
130 chown_but[i].text = _(chown_but[i].text);
131 #endif
132
133 for (i = 0; i < BUTTONS; i++)
134 {
135 chown_but[i].len = str_term_width1 (chown_but[i].text) + 3;
136 if (chown_but[i].flags == DEFPUSH_BUTTON)
137 chown_but[i].len += 2;
138
139 if (i < BUTTONS - 2)
140 blen += chown_but[i].len;
141 }
142
143 blen += 2;
144 }
145
146
147
148 static void
149 chown_refresh (const Widget *h)
150 {
151 int y = 3;
152 int x = 7 + GW * 2;
153
154 tty_setcolor (COLOR_NORMAL);
155
156 widget_gotoyx (h, y + 0, x);
157 tty_print_string (_("Name"));
158 widget_gotoyx (h, y + 2, x);
159 tty_print_string (_("Owner name"));
160 widget_gotoyx (h, y + 4, x);
161 tty_print_string (_("Group name"));
162 widget_gotoyx (h, y + 6, x);
163 tty_print_string (_("Size"));
164 widget_gotoyx (h, y + 8, x);
165 tty_print_string (_("Permission"));
166 }
167
168
169
170 static cb_ret_t
171 chown_bg_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
172 {
173 switch (msg)
174 {
175 case MSG_DRAW:
176 frame_callback (w, NULL, MSG_DRAW, 0, NULL);
177 chown_refresh (WIDGET (w->owner));
178 return MSG_HANDLED;
179
180 default:
181 return frame_callback (w, sender, msg, parm, data);
182 }
183 }
184
185
186
187 static WDialog *
188 chown_dlg_create (WPanel *panel)
189 {
190 int single_set;
191 WDialog *ch_dlg;
192 WGroup *g;
193 int lines, cols;
194 int i, y;
195 struct passwd *l_pass;
196 struct group *l_grp;
197
198 single_set = (panel->marked < 2) ? 3 : 0;
199 lines = GH + 4 + (single_set != 0 ? 2 : 4);
200 cols = GW * 3 + 2 + 6;
201
202 ch_dlg =
203 dlg_create (TRUE, 0, 0, lines, cols, WPOS_CENTER, FALSE, dialog_colors, NULL, NULL,
204 "[Chown]", _("Chown command"));
205 g = GROUP (ch_dlg);
206
207
208 ch_dlg->bg->callback = chown_bg_callback;
209
210 group_add_widget (g, groupbox_new (2, 3, GH, GW, _("User name")));
211 l_user = listbox_new (3, 4, GH - 2, GW - 2, FALSE, NULL);
212 group_add_widget (g, l_user);
213
214 listbox_add_item (l_user, LISTBOX_APPEND_AT_END, 0, _("<Unknown user>"), NULL, FALSE);
215
216 setpwent ();
217 while ((l_pass = getpwent ()) != NULL)
218 listbox_add_item (l_user, LISTBOX_APPEND_SORTED, 0, l_pass->pw_name, NULL, FALSE);
219 endpwent ();
220
221 group_add_widget (g, groupbox_new (2, 4 + GW, GH, GW, _("Group name")));
222 l_group = listbox_new (3, 5 + GW, GH - 2, GW - 2, FALSE, NULL);
223 group_add_widget (g, l_group);
224
225 listbox_add_item (l_group, LISTBOX_APPEND_AT_END, 0, _("<Unknown group>"), NULL, FALSE);
226
227 setgrent ();
228 while ((l_grp = getgrent ()) != NULL)
229 listbox_add_item (l_group, LISTBOX_APPEND_SORTED, 0, l_grp->gr_name, NULL, FALSE);
230 endgrent ();
231
232 group_add_widget (g, groupbox_new (2, 5 + GW * 2, GH, GW, _("File")));
233
234 for (i = 0; i < LABELS; i++)
235 {
236 chown_label[i].l = label_new (chown_label[i].y, 7 + GW * 2, NULL);
237 group_add_widget (g, chown_label[i].l);
238 }
239
240 if (single_set == 0)
241 {
242 int x;
243
244 group_add_widget (g, hline_new (lines - chown_but[0].y - 1, -1, -1));
245
246 y = lines - chown_but[0].y;
247 x = (cols - blen) / 2;
248
249 for (i = 0; i < BUTTONS - 2; i++)
250 {
251 group_add_widget (g, button_new (y, x, chown_but[i].ret_cmd, chown_but[i].flags,
252 chown_but[i].text, NULL));
253 x += chown_but[i].len + 1;
254 }
255 }
256
257 i = BUTTONS - 2;
258 y = lines - chown_but[i].y;
259 group_add_widget (g, hline_new (y - 1, -1, -1));
260 group_add_widget (g, button_new (y, WIDGET (ch_dlg)->rect.cols / 2 - chown_but[i].len,
261 chown_but[i].ret_cmd, chown_but[i].flags, chown_but[i].text,
262 NULL));
263 i++;
264 group_add_widget (g, button_new (y, WIDGET (ch_dlg)->rect.cols / 2 + 1, chown_but[i].ret_cmd,
265 chown_but[i].flags, chown_but[i].text, NULL));
266
267
268 widget_select (WIDGET (l_user));
269
270 return ch_dlg;
271 }
272
273
274
275 static void
276 chown_done (gboolean need_update)
277 {
278 if (need_update)
279 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
280 repaint_screen ();
281 }
282
283
284
285 static gboolean
286 try_chown (const vfs_path_t *p, uid_t u, gid_t g)
287 {
288 const char *fname = NULL;
289
290 while (mc_chown (p, u, g) == -1 && !ignore_all)
291 {
292 int my_errno = errno;
293 int result;
294 char *msg;
295
296 if (fname == NULL)
297 fname = x_basename (vfs_path_as_str (p));
298 msg = g_strdup_printf (_("Cannot chown \"%s\"\n%s"), fname, unix_error_string (my_errno));
299 result =
300 query_dialog (MSG_ERROR, msg, D_ERROR, 4, _("&Ignore"), _("Ignore &all"), _("&Retry"),
301 _("&Cancel"));
302 g_free (msg);
303
304 switch (result)
305 {
306 case 0:
307
308 return TRUE;
309
310 case 1:
311 ignore_all = TRUE;
312
313 return TRUE;
314
315 case 2:
316
317 break;
318
319 case 3:
320 default:
321
322 return FALSE;
323 }
324 }
325
326 return TRUE;
327 }
328
329
330
331 static gboolean
332 do_chown (WPanel *panel, const vfs_path_t *p, uid_t u, gid_t g)
333 {
334 gboolean ret;
335
336 ret = try_chown (p, u, g);
337
338 do_file_mark (panel, current_file, 0);
339
340 return ret;
341 }
342
343
344
345 static void
346 apply_chowns (WPanel *panel, vfs_path_t *vpath, uid_t u, gid_t g)
347 {
348 gboolean ok;
349
350 if (!do_chown (panel, vpath, u, g))
351 return;
352
353 do
354 {
355 const GString *fname;
356 struct stat sf;
357
358 fname = panel_find_marked_file (panel, ¤t_file);
359 vpath = vfs_path_from_str (fname->str);
360 ok = (mc_stat (vpath, &sf) == 0);
361
362 if (!ok)
363 {
364
365
366 do_file_mark (panel, current_file, 0);
367
368
369 ok = TRUE;
370 }
371 else
372 ok = do_chown (panel, vpath, u, g);
373
374 vfs_path_free (vpath, TRUE);
375 }
376 while (ok && panel->marked != 0);
377 }
378
379
380
381
382
383 void
384 chown_cmd (WPanel *panel)
385 {
386 gboolean need_update;
387 gboolean end_chown;
388
389 chown_init ();
390
391 current_file = 0;
392 ignore_all = FALSE;
393
394 do
395 {
396 vfs_path_t *vpath;
397 WDialog *ch_dlg;
398 struct stat sf_stat;
399 const GString *fname;
400 int result;
401 char buffer[BUF_TINY];
402 uid_t new_user = (uid_t) (-1);
403 gid_t new_group = (gid_t) (-1);
404
405 do_refresh ();
406
407 need_update = FALSE;
408 end_chown = FALSE;
409
410 fname = panel_get_marked_file (panel, ¤t_file);
411 if (fname == NULL)
412 break;
413
414 vpath = vfs_path_from_str (fname->str);
415
416 if (mc_stat (vpath, &sf_stat) != 0)
417 {
418 vfs_path_free (vpath, TRUE);
419 break;
420 }
421
422 ch_dlg = chown_dlg_create (panel);
423
424
425 listbox_set_current (l_user, listbox_search_text (l_user, get_owner (sf_stat.st_uid)));
426 listbox_set_current (l_group, listbox_search_text (l_group, get_group (sf_stat.st_gid)));
427
428 chown_label (0, str_trunc (fname->str, GW - 4));
429 chown_label (1, str_trunc (get_owner (sf_stat.st_uid), GW - 4));
430 chown_label (2, str_trunc (get_group (sf_stat.st_gid), GW - 4));
431 size_trunc_len (buffer, GW - 4, sf_stat.st_size, 0, panels_options.kilobyte_si);
432 chown_label (3, buffer);
433 chown_label (4, string_perm (sf_stat.st_mode));
434
435 result = dlg_run (ch_dlg);
436
437 switch (result)
438 {
439 case B_CANCEL:
440 end_chown = TRUE;
441 break;
442
443 case B_ENTER:
444 case B_SETALL:
445 {
446 struct group *grp;
447 struct passwd *user;
448 char *text;
449
450 listbox_get_current (l_group, &text, NULL);
451 grp = getgrnam (text);
452 if (grp != NULL)
453 new_group = grp->gr_gid;
454 listbox_get_current (l_user, &text, NULL);
455 user = getpwnam (text);
456 if (user != NULL)
457 new_user = user->pw_uid;
458 if (result == B_ENTER)
459 {
460 if (panel->marked <= 1)
461 {
462
463 if (mc_chown (vpath, new_user, new_group) == -1)
464 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"),
465 fname->str, unix_error_string (errno));
466 end_chown = TRUE;
467 }
468 else if (!try_chown (vpath, new_user, new_group))
469 {
470
471 result = B_CANCEL;
472 end_chown = TRUE;
473 }
474 }
475 else
476 {
477 apply_chowns (panel, vpath, new_user, new_group);
478 end_chown = TRUE;
479 }
480
481 need_update = TRUE;
482 break;
483 }
484
485 case B_SETUSR:
486 {
487 struct passwd *user;
488 char *text;
489
490 listbox_get_current (l_user, &text, NULL);
491 user = getpwnam (text);
492 if (user != NULL)
493 {
494 new_user = user->pw_uid;
495 apply_chowns (panel, vpath, new_user, new_group);
496 need_update = TRUE;
497 end_chown = TRUE;
498 }
499 break;
500 }
501
502 case B_SETGRP:
503 {
504 struct group *grp;
505 char *text;
506
507 listbox_get_current (l_group, &text, NULL);
508 grp = getgrnam (text);
509 if (grp != NULL)
510 {
511 new_group = grp->gr_gid;
512 apply_chowns (panel, vpath, new_user, new_group);
513 need_update = TRUE;
514 end_chown = TRUE;
515 }
516 break;
517 }
518
519 default:
520 break;
521 }
522
523 if (panel->marked != 0 && result != B_CANCEL)
524 {
525 do_file_mark (panel, current_file, 0);
526 need_update = TRUE;
527 }
528
529 vfs_path_free (vpath, TRUE);
530
531 widget_destroy (WIDGET (ch_dlg));
532 }
533 while (panel->marked != 0 && !end_chown);
534
535 chown_done (need_update);
536 }
537
538