xaizek / vide (License: GPLv2+) (since 2018-12-07)
Graphical predecessor of vifm that uses GTK+.
<root> / src / fileops.c (b6ee84f81aa3be688da562fefcf1cdd4e08355ea) (6,450B) (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 <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include "vide.h"

/*
 * This file contains functions used to handle different file operations
 * like copying, deleting, sym linking, etc.. most functions do this by 
 * forking and running the standard unix commands for the appropriate operation
 */

static void start_reader_thread (void *ptr);

/* executes the argument array passed to it and waits for
 * the forked process to exit before returning. It is used to do most
 * of the file operations.
static gint
exec_and_wait(args)
  gchar **args;
{
  gint pid, status;

  pid = fork();
  if (pid == -1)
    return -1;
  if (pid == 0)
  {
    execvp(args[0], args);
    exit(127);
  }

  do
  {  
    if (waitpid(pid, &status, 0) == -1)
    {
      if (errno != EINTR)
        return -1;
    }
    else
      return status;
  } while(1);
}
 */

/* simply executes the argument array passed. the sigchild handler set up
 * during startup will handle the process when it has ended so that we dont
 * get zombies
 */
static gint
execute (gchar ** args)
{
  gint pid;

  if ((pid = fork ()) == 0)
    {
			close(0);
      execvp (args[0], args);
      exit (127);
    }

  return pid;
}

/* copy src to dest.. return when the operation is done */
gint file_copy (gchar * src, gchar * dest)
{
  gchar *args[5];

  args[0] = "cp";
  args[1] = "-r";
  args[2] = src;
  args[3] = dest;
  args[4] = NULL;

  return pipe_and_capture_output (args);
}

/* delete file.. return when the operation is done */
gint file_delete (gchar * file)
{
  gchar *args[4];

  args[0] = "rm";
  args[1] = "-rf";
  args[2] = file;
  args[3] = NULL;

  return pipe_and_capture_output (args);
}

/* move src to dest.. return when the operation is done */
gint file_move (gchar * src, gchar * dest)
{
  gchar *args[4];

  args[0] = "mv";
  args[1] = src;
  args[2] = dest;
  args[3] = NULL;

  return pipe_and_capture_output (args);
}

gint file_chmod (gchar * path, gchar * mode, gboolean recurse_dirs)
{
  gchar *args[5];
  gint i = 0;

  args[i++] = "chmod";
  if (recurse_dirs)
    args[i++] = "-R";
  args[i++] = mode;
  args[i++] = path;
  args[i++] = NULL;

  return pipe_and_capture_output (args);
}

gint
file_chown (gchar * path,
	    uid_t owner_id, gid_t group_id, gboolean recurse_dirs)
{
  gchar *args[5];
  gchar mode[14];
  gint i = 0;

  g_snprintf (mode, sizeof (mode), "%d:%d", (int) owner_id, (int) group_id);

  args[i++] = "chown";
  if (recurse_dirs)
    args[i++] = "-R";
  args[i++] = mode;
  args[i++] = path;
  args[i++] = NULL;

  return pipe_and_capture_output (args);
}

/* symlink src to dest */
gint file_symlink (gchar * src, gchar * dest)
{
  return symlink (src, dest);
}

gint file_mkdir (gchar * path)
{
  return mkdir (path, 0777);
}

/* execute command.. do not wait for it to exit */
gint file_exec (gchar * command)
{
  gchar *args[4];
  pid_t pid;

  args[0] = "sh";
  args[1] = "-c";
  args[2] = command;
  args[3] = NULL;

  pid = execute (args);
  return pid;
}

gint exec_in_xterm (gchar * command)
{
	/* gnome-terminal takes different aguments than xterm or rxvt */
	if(!strcmp(cfg.xterm_command, "gnome-terminal"))
	{
		gchar *args[4];
		gchar buf[PATH_MAX];

		g_snprintf(buf, sizeof(buf), "'%s'", command);

		args[0] = cfg.xterm_command;
		args[1] = "-e";
		args[2] = command;
		args[3] = NULL;

		return execute(args);

	}
	else
	{
  	gchar *args[7];

  	args[0] = cfg.xterm_command;
  	args[1] = "+sb";
  	args[2] = "-e";
  	args[3] = "sh";
  	args[4] = "-c";
  	args[5] = command;
  	args[6] = NULL;

		return execute(args);
	}

}

gint pipe_and_capture_output (gchar ** args)
{
  gint file_pipes[2];
  gint pid;
  gchar buf[1024];
  gint nread;

  if (pipe (file_pipes) != 0)
    {
      status_errno ();
      return -1;
    }

  if ((pid = fork ()) == -1)
    {
      status_errno ();
      return -1;
    }

  if (pid == 0)
    {
      close (1);
      close (2);
      dup (file_pipes[1]);
      dup (file_pipes[1]);
      close (file_pipes[0]);
      close (file_pipes[1]);

      execvp (args[0], args);
      exit (127);
    }
  else
    {
      close (file_pipes[1]);
      while ((nread = read (file_pipes[0], buf, sizeof (buf) - 1)) > 0)
	{
	  buf[nread] = '\0';
	     status_bar_message(buf);
	}
      close (file_pipes[0]);
    }

  return 0;
}

gint pipe_and_capture_output_threaded (gchar * command)
{
  gint file_pipes[2];
  gint pid;
  gchar *args[4];
  pthread_t reader_thread;


  if (pipe (file_pipes) != 0)
    {
      status_errno ();
      return -1;
    }

  if ((pid = fork ()) == -1)
    {
      status_errno ();
      return -1;
    }

  if (pid == 0)
    {
      close (1);
      close (2);
      dup (file_pipes[1]);
      dup (file_pipes[1]);
      close (file_pipes[0]);
      close (file_pipes[1]);

      args[0] = "sh";
      args[1] = "-c";
      args[2] = command;
      args[3] = NULL;
      execvp (args[0], args);
      exit (127);
    }
  else
    {
      close (file_pipes[1]);
      pthread_create (&reader_thread, NULL, (void *) &start_reader_thread,
		      duplicate (&file_pipes[0], sizeof (gint)));
    }

  return 1;
}

static void
start_reader_thread (void *ptr)
{
  gchar buf[1024];
  gint nread, error;
  gint *file_pipe = (gint *) ptr;
	error = 0;

  while ((nread = read (*file_pipe, buf, sizeof (buf) - 1)) > 0)
    {
      buf[nread] = '\0';
			error =  nread;
    }
	/* create error message dialog FIXME */
	/* not all errors are returned correctly */
	if(error != 0)
	{
			create_error_dialog(buf);
	}
  close (*file_pipe);
  g_free (file_pipe);
  pthread_exit (0);
}
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