xaizek / vide (License: GPLv2+) (since 2018-12-07)
Graphical predecessor of vifm that uses GTK+.
<root> / src / permissions_dialog.c (3e9bd05e4707664319f49400bfd0051e5c82edcf) (10KiB) (mode 100644) [raw]
/* vide
 * Copyright (C) 2000 Ken Steen.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
#include "vide.h"

static GtkWidget *permissions_dialog;
static mode_t mask[12] =
  { S_ISUID, S_ISGID, S_ISVTX, S_IRUSR, S_IWUSR, S_IXUSR,
  S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH
};
static gchar *add_strings[12] = { "u+s", "g+s", "o+t", "u+r", "u+w", "u+x",
  "g+r", "g+w", "g+x", "o+r", "o+w", "o+x"
};
static gchar *remove_strings[12] = { "u-s", "g-s", "o-t", "u-r", "u-w", "u-x",
  "g-r", "g-w", "g-x", "o-r", "o-w", "o-x"
};

enum
{ SETUID, SETGID, STICKY, USR_READ, USR_WRITE, USR_EXEC, GRP_READ,
  GRP_WRITE, GRP_EXEC, OTH_READ, OTH_WRITE, OTH_EXEC
};
static GtkWidget *chmod_buttons[12];
static GtkWidget *set_perms_button;
static GtkWidget *add_perms_button;
static GtkWidget *remove_perms_button;
static GtkWidget *recurse_dirs_button;

static void
get_mode_string (gchar * mode_string, gint length)
{
  int i;

  if (GTK_TOGGLE_BUTTON (set_perms_button)->active)
    {
      mode_t mode = 0;
      for (i = 0; i < 12; i++)
	{
	  if (GTK_TOGGLE_BUTTON (chmod_buttons[i])->active)
	    mode |= mask[i];
	}
      g_snprintf (mode_string, length, "%o", (unsigned int) mode);
      return;
    }
  else if (GTK_TOGGLE_BUTTON (add_perms_button)->active)
    {
      *mode_string = '\0';
      for (i = 0; i < 12; i++)
	{
	  if (GTK_TOGGLE_BUTTON (chmod_buttons[i])->active)
	    {
	      strncat (mode_string, add_strings[i], length);
	      strncat (mode_string, ",", length);
	    }
	}
      i = strlen (mode_string);
      if (i > 0)
	mode_string[i - 1] = '\0';	/* get rid of trailing comma */
      return;
    }
  else if (GTK_TOGGLE_BUTTON (remove_perms_button)->active)
    {
      *mode_string = '\0';
      for (i = 0; i < 12; i++)
	{
	  if (GTK_TOGGLE_BUTTON (chmod_buttons[i])->active)
	    {
	      strncat (mode_string, remove_strings[i], length);
	      strncat (mode_string, ",", length);
	    }
	}
      i = strlen (mode_string);
      if (i > 0)
	mode_string[i - 1] = '\0';
      return;
    }
  else
    {
      fprintf (stderr, "Something messed up. Exit quickly.\n");
    }

  return;
}

static void
ok_cb (GtkWidget * widget)
{
  FileInfo *info;
  gchar path[PATH_MAX + NAME_MAX];
  gchar mode_string[50];

  get_mode_string (mode_string, sizeof (mode_string));
  info = curr_view->iter->data;
  g_snprintf (path, sizeof (path), "%s/%s", curr_view->dir, info->filename);
  file_chmod (path, mode_string,
	      GTK_TOGGLE_BUTTON (recurse_dirs_button)->active);

  gtk_grab_remove (permissions_dialog);
  gtk_widget_destroy (permissions_dialog);

  curr_view->iter = curr_view->iter->next;
  if (curr_view->iter != NULL)
    {
      info = curr_view->iter->data;
      create_permissions_dialog (info);
    }
  else
    {
      g_list_free (curr_view->iter_base);
      refresh_list (curr_view);
      gtk_clist_select_row (GTK_CLIST (curr_view->clist), curr_view->row, 0);
      gtk_widget_grab_focus (curr_view->clist);
    }
}

static void
apply_to_all_cb (GtkWidget * widget)
{
  FileInfo *info;
  gchar path[PATH_MAX + NAME_MAX];
  gchar mode_string[50];

  get_mode_string (mode_string, sizeof (mode_string));

  for (; curr_view->iter != NULL; curr_view->iter = curr_view->iter->next)
    {
      info = curr_view->iter->data;
      g_snprintf (path, sizeof (path), "%s/%s", curr_view->dir,
		  info->filename);

      file_chmod (path, mode_string,
		  GTK_TOGGLE_BUTTON (recurse_dirs_button)->active);
    }

  g_list_free (curr_view->iter_base);
  gtk_grab_remove (permissions_dialog);
  gtk_widget_destroy (permissions_dialog);
  refresh_list (curr_view);
  gtk_clist_select_row (GTK_CLIST (curr_view->clist), curr_view->row, 0);
  gtk_widget_grab_focus (curr_view->clist);
}

static void
cancel_cb (GtkWidget * widget, GtkWidget * dialog)
{
  gtk_grab_remove (dialog);
  gtk_widget_destroy (dialog);
}

static void
key_press_cb (GtkWidget * widget, GdkEventKey * event, gpointer data)
{
  if (event->keyval == GDK_Escape)
    cancel_cb (NULL, widget);
}

static void
add_chmod_button (GtkWidget * box, gint i, gchar * label, gint state)
{
  chmod_buttons[i] = gtk_toggle_button_new_with_label (label);
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chmod_buttons[i]), state);
  gtk_box_pack_start (GTK_BOX (box), chmod_buttons[i], TRUE, TRUE, 5);
  gtk_widget_show (chmod_buttons[i]);
}

static void
clear_chmod_buttons (GtkWidget * widget)
{
  int i;

  for (i = 0; i < 12; i++)
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chmod_buttons[i]),
				  FALSE);
}

static void
reset_chmod_buttons (GtkWidget * widget, FileInfo * info)
{
  int i;

  for (i = 0; i < 12; i++)
    {
      if (info->statbuf.st_mode & mask[i])
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chmod_buttons[i]),
				      TRUE);
      else
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chmod_buttons[i]),
				      FALSE);
    }
}


void
create_permissions_dialog (FileInfo * info)
{
  GtkWidget *sub_vbox;
  GtkWidget *hbox;
  GtkWidget *frame;
  GtkWidget *dialog_vbox;
  GtkWidget *action_area;
  GtkWidget *table;
  gchar label_text[NAME_MAX + 20];
  struct passwd *pw_buf;
  struct group *grp_buf;

  permissions_dialog = gtk_dialog_new ();
  dialog_vbox = GTK_DIALOG (permissions_dialog)->vbox;
  action_area = GTK_DIALOG (permissions_dialog)->action_area;
  gtk_container_set_border_width (GTK_CONTAINER (dialog_vbox), 5);
  gtk_signal_connect (GTK_OBJECT (permissions_dialog), "key_press_event",
		      GTK_SIGNAL_FUNC (key_press_cb), NULL);

  g_snprintf (label_text, sizeof (label_text),
	      "Filename: %s", info->filename);
  add_label (dialog_vbox, label_text, 0, TRUE, 5);

  table = add_table (dialog_vbox, 2, 1, TRUE, TRUE, 0);

  if ((pw_buf = getpwuid (info->statbuf.st_uid)) != NULL)
    {
      g_snprintf (label_text, sizeof (label_text),
		  "User: %s", pw_buf->pw_name);
    }
  else
    {
      g_snprintf (label_text, sizeof (label_text),
		  "User: %d", (int) info->statbuf.st_uid);
    }
  add_label_to_table (table, label_text, 0, 0, 1, 0, 1);

  if ((grp_buf = getgrgid (info->statbuf.st_gid)) != NULL)
    {
      g_snprintf (label_text, sizeof (label_text),
		  "Group: %s", grp_buf->gr_name);
    }
  else
    {
      g_snprintf (label_text, sizeof (label_text),
		  "Group: %d", (int) info->statbuf.st_gid);
    }
  add_label_to_table (table, label_text, 0, 0, 1, 1, 2);

  frame = gtk_frame_new ("File Permissions");
  gtk_box_pack_start (GTK_BOX (dialog_vbox), frame, TRUE, TRUE, 5);
  gtk_widget_show (frame);

  sub_vbox = gtk_vbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER (frame), sub_vbox);
  gtk_widget_show (sub_vbox);

  hbox = add_hbox (sub_vbox, TRUE, 0, TRUE, 0);
  add_label (hbox, "", 0.5, TRUE, 0);
  add_label (hbox, "Read", 0.5, TRUE, 0);
  add_label (hbox, "Write", 0.5, TRUE, 0);
  add_label (hbox, "Exec", 0.5, TRUE, 0);
  add_label (hbox, "Special", 0.5, TRUE, 0);

  hbox = add_hbox (sub_vbox, TRUE, 0, TRUE, 5);
  add_label (hbox, "User", 0.5, TRUE, 0);
  add_chmod_button (hbox, USR_READ, "", info->statbuf.st_mode & S_IRUSR);
  add_chmod_button (hbox, USR_WRITE, "", info->statbuf.st_mode & S_IWUSR);
  add_chmod_button (hbox, USR_EXEC, "", info->statbuf.st_mode & S_IXUSR);
  add_chmod_button (hbox, SETUID, "Set UID", info->statbuf.st_mode & S_ISUID);

  hbox = add_hbox (sub_vbox, TRUE, 0, TRUE, 5);
  add_label (hbox, "Group", 0.5, TRUE, 0);
  add_chmod_button (hbox, GRP_READ, "", info->statbuf.st_mode & S_IRGRP);
  add_chmod_button (hbox, GRP_WRITE, "", info->statbuf.st_mode & S_IWGRP);
  add_chmod_button (hbox, GRP_EXEC, "", info->statbuf.st_mode & S_IXGRP);
  add_chmod_button (hbox, SETGID, "Set GID", info->statbuf.st_mode & S_ISGID);

  hbox = add_hbox (sub_vbox, TRUE, 0, TRUE, 5);
  add_label (hbox, "Other", 0.5, TRUE, 0);
  add_chmod_button (hbox, OTH_READ, "", info->statbuf.st_mode & S_IROTH);
  add_chmod_button (hbox, OTH_WRITE, "", info->statbuf.st_mode & S_IWOTH);
  add_chmod_button (hbox, OTH_EXEC, "", info->statbuf.st_mode & S_IXOTH);
  add_chmod_button (hbox, STICKY, "Sticky", info->statbuf.st_mode & S_ISVTX);

  frame = gtk_frame_new ("Action:");
  gtk_box_pack_start (GTK_BOX (dialog_vbox), frame, TRUE, TRUE, 5);
  gtk_widget_show (frame);

  sub_vbox = gtk_vbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER (frame), sub_vbox);
  gtk_widget_show (sub_vbox);

  hbox = add_hbox (sub_vbox, TRUE, 0, TRUE, 0);
  set_perms_button = add_radio_button (hbox, "Set", NULL, TRUE, 5,
				       reset_chmod_buttons, info);
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (set_perms_button), TRUE);
  add_perms_button = add_radio_button (hbox, "Add",
				       gtk_radio_button_group
				       (GTK_RADIO_BUTTON (set_perms_button)),
				       TRUE, 5, clear_chmod_buttons, NULL);
  remove_perms_button =
    add_radio_button (hbox, "Remove",
		      gtk_radio_button_group (GTK_RADIO_BUTTON
					      (add_perms_button)), TRUE, 5,
		      clear_chmod_buttons, NULL);

  recurse_dirs_button = add_check_button (dialog_vbox, "Recurse Directories",
					  FALSE, FALSE, 5, NULL, NULL);

  add_button (action_area, "Ok", TRUE, 0, ok_cb, NULL);
  if (g_list_length (curr_view->iter) > 1)
    add_button (action_area, "Apply To All", TRUE, 0, apply_to_all_cb, NULL);
  add_button (action_area, "Cancel", TRUE, 0, cancel_cb, permissions_dialog);

  gtk_window_set_position (GTK_WINDOW (permissions_dialog),
			   GTK_WIN_POS_CENTER);
  gtk_widget_show (permissions_dialog);
  gtk_grab_add (permissions_dialog);
  gtk_window_set_transient_for (GTK_WINDOW (permissions_dialog),
				GTK_WINDOW (app.main_window));
}
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/vide

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/vide

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master