⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utilunix.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Various utilities - Unix variants
   Copyright (C) 1994, 1995, 1996 the Free Software Foundation.
   Written 1994, 1995, 1996 by:
   Miguel de Icaza, Janne Kukonlehto, Dugan Porter,
   Jakub Jelinek, Mauricio Plaza.

   The file_date routine is mostly from GNU's fileutils package,
   written by Richard Stallman and David MacKenzie.

   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., 675 Mass Ave, Cambridge, MA 02139, USA.  */

#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <signal.h>		/* my_system */
#include <limits.h>		/* INT_MAX */
#include <sys/time.h>		/* select: timeout */
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#ifdef HAVE_SYS_WAIT_H
#    include <sys/wait.h>	/* my_system */
#endif
#include <errno.h>		/* my_system */
#include <pwd.h>
#include <grp.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_SYS_SELECT_H
#  include <sys/select.h>
#endif
#ifdef SCO_FLAVOR
#   include <sys/timeb.h>
#endif
#include <time.h>
#ifdef __linux__
#    if defined(__GLIBC__) && (__GLIBC__ < 2)
#        include <linux/termios.h>	/* This is needed for TIOCLINUX */
#    else
#        include <termios.h>
#    endif
#  include <sys/ioctl.h>
#endif
#ifdef __QNX__
#   include <unix.h>		/* exec*() from <process.h> */
#endif
#include "util.h"
#include "global.h"
#include "fsusage.h"
#include "fsusage.h"
#include "mountlist.h"
#include "mad.h"
#include "dialog.h"		/* message() */
#include "../vfs/vfs.h"		/* mc_read() */
#include "x.h"

struct sigaction startup_handler;
extern struct mount_entry *mount_list;

uid_t current_user_uid;
user_in_groups *current_user_gid;

int
max_open_files (void)
{
	static int files;

	if (files)
		return files;

#ifdef HAVE_SYSCONF
	files = sysconf (_SC_OPEN_MAX);
	if (files != -1)
		return files;
#endif
#ifdef OPEN_MAX
	return files = OPEN_MAX;
#else
	return files = 256;
#endif
}

void init_groups (void)
{
    int i;
    struct passwd *pwd;
    struct group *grp;
    user_in_groups *cug, *pug;

    pwd = getpwuid (current_user_uid=getuid ());

    current_user_gid = (pug = xmalloc (sizeof (user_in_groups), "init_groups"));
    current_user_gid->gid = getgid (); current_user_gid->next = 0;

    if (pwd == 0)
       return;

    setgrent ();
    while ((grp = getgrent ()))
       for (i = 0; grp->gr_mem[i]; i++)
           if (!strcmp (pwd->pw_name,grp->gr_mem[i]))
               {
               cug = xmalloc (sizeof (user_in_groups), "init_groups");
               cug->gid  = grp->gr_gid;
               pug->next = cug;
               cug->next = 0;
               pug = cug;
               break;
               }
    endgrent ();
}

/* Return the index of permission triplet */
int
get_user_rights (struct stat *buf)
{
    user_in_groups *cug;

    if (buf->st_uid == current_user_uid || current_user_uid == 0)
       return 0;

    for (cug = current_user_gid; cug; cug = cug->next)
       if (cug->gid == buf->st_gid) return 1;

    return 2;
}


void
delete_groups (void)
{
    user_in_groups *pug, *cug = current_user_gid;

    while (cug){
       pug = cug->next;
       free (cug);
       cug = pug;
    }
}

#define UID_CACHE_SIZE 200
#define GID_CACHE_SIZE 30

typedef struct {
    int  index;
    char *string;
} int_cache;

int_cache uid_cache [UID_CACHE_SIZE];
int_cache gid_cache [GID_CACHE_SIZE];

void init_uid_gid_cache (void)
{
    int i;

    for (i = 0; i < UID_CACHE_SIZE; i++)
	uid_cache [i].string = 0;

    for (i = 0; i < GID_CACHE_SIZE; i++)
	 gid_cache [i].string = 0;
}

static char *i_cache_match (int id, int_cache *cache, int size)
{
    int i;

    for (i = 0; i < size; i++)
	if (cache [i].index == id)
	    return cache [i].string;
    return 0;
}

static void i_cache_add (int id, int_cache *cache, int size, char *text,
			 int *last)
{
    if (cache [*last].string)
	free (cache [*last].string);
    cache [*last].string = strdup (text);
    cache [*last].index = id;
    *last = ((*last)+1) % size;
}

char *get_owner (int uid)
{
    struct passwd *pwd;
    static char ibuf [8];
    char   *name;
    static int uid_last;

    if ((name = i_cache_match (uid, uid_cache, UID_CACHE_SIZE)) != NULL)
	return name;

    pwd = getpwuid (uid);
    if (pwd){
	i_cache_add (uid, uid_cache, UID_CACHE_SIZE, pwd->pw_name, &uid_last);
	return pwd->pw_name;
    }
    else {
	sprintf (ibuf, "%d", uid);
	return ibuf;
    }
}

char *get_group (int gid)
{
    struct group *grp;
    static char gbuf [8];
    char *name;
    static int  gid_last;

    if ((name = i_cache_match (gid, gid_cache, GID_CACHE_SIZE)) != NULL)
	return name;

    grp = getgrgid (gid);
    if (grp){
	i_cache_add (gid, gid_cache, GID_CACHE_SIZE, grp->gr_name, &gid_last);
	return grp->gr_name;
    } else {
	sprintf (gbuf, "%d", gid);
	return gbuf;
    }
}

/* Since ncurses uses a handler that automatically refreshes the */
/* screen after a SIGCONT, and we don't want this behavior when */
/* spawning a child, we save the original handler here */
void save_stop_handler (void)
{
    sigaction (SIGTSTP, NULL, &startup_handler);
}

#ifdef HAVE_GNOME
#define PORT_HAS_MY_SYSTEM 1
#endif

#ifndef PORT_HAS_MY_SYSTEM
int my_system (int flags, const char *shell, const char *command)
{
    struct sigaction ignore, save_intr, save_quit, save_stop;
    pid_t pid;
    int status = 0;
    int as_shell_command = flags & EXECUTE_AS_SHELL;

    ignore.sa_handler = SIG_IGN;
    sigemptyset (&ignore.sa_mask);
    ignore.sa_flags = 0;

    sigaction (SIGINT, &ignore, &save_intr);
    sigaction (SIGQUIT, &ignore, &save_quit);

    /* Restore the original SIGTSTP handler, we don't want ncurses' */
    /* handler messing the screen after the SIGCONT */
    sigaction (SIGTSTP, &startup_handler, &save_stop);

    if ((pid = fork ()) < 0){
	fprintf (stderr, "\n\nfork () = -1\n");
	return -1;
    }
    if (pid == 0){
	sigaction (SIGINT,  &save_intr, NULL);
	sigaction (SIGQUIT, &save_quit, NULL);

#if 0
	prepare_environment ();
#endif

	if (as_shell_command)
	    execl (shell, shell, "-c", command, (char *) 0);
	else
	    execlp (shell, shell, command, (char *) 0);

	_exit (127);		/* Exec error */
    } else {
	while (waitpid (pid, &status, 0) < 0)
	    if (errno != EINTR){
		status = -1;
		break;
	    }
    }
    sigaction (SIGINT,  &save_intr, NULL);
    sigaction (SIGQUIT, &save_quit, NULL);
    sigaction (SIGTSTP, &save_stop, NULL);

#ifdef SCO_FLAVOR
	waitpid(-1, NULL, WNOHANG);
#endif /* SCO_FLAVOR */

    return WEXITSTATUS(status);
}
#endif

/* Returns a newly allocated string, if directory does not exist, return 0 */
char *tilde_expand (char *directory)
{
    struct passwd *passwd;
    char *p;
    char *name;
    int  len;

    if (*directory != '~')
	return strdup (directory);

    directory++;

    p = strchr (directory, PATH_SEP);

    /* d = "~" or d = "~/" */
    if (!(*directory) || (*directory == PATH_SEP)){
	passwd = getpwuid (geteuid ());
	p = (*directory == PATH_SEP) ? directory+1 : "";
    } else {
	if (!p){
	    p = "";
	    passwd = getpwnam (directory);
	} else {
	    name = xmalloc (p - directory + 1, "tilde_expand");
	    strncpy (name, directory, p - directory);
	    name [p - directory] = 0;
	    passwd = getpwnam (name);
	    free (name);
	}
    }

    /* If we can't figure the user name, return NULL */
    if (!passwd)
	return 0;

    len = strlen (passwd->pw_dir) + strlen (p) + 2;
    directory = xmalloc (len, "tilde_expand");
    strcpy (directory, passwd->pw_dir);
    strcat (directory, PATH_SEP_STR);
    strcat (directory, p);
    return directory;
}

int
set_nonblocking (int fd)
{
    int val;

    val = fcntl (fd, F_GETFL, 0);
    val |= O_NONBLOCK;
    return fcntl (fd, F_SETFL, val) != -1;
}

/* Pipes are guaranteed to be able to hold at least 4096 bytes */
/* More than that would be unportable */
#define MAX_PIPE_SIZE 4096

static int error_pipe[2];	/* File descriptors of error pipe */
static int old_error;		/* File descriptor of old standard error */

/* Creates a pipe to hold standard error for a later analysis. */
/* The pipe can hold 4096 bytes. Make sure no more is written */
/* or a deadlock might occur. */
void open_error_pipe (void)
{
    if (pipe (error_pipe) < 0){
	message (0, _(" Warning "), _(" Pipe failed "));
    }
    old_error = dup (2);
    if(old_error < 0 || close(2) || dup (error_pipe[1]) != 2){
	message (0, _(" Warning "), _(" Dup failed "));
	close (error_pipe[0]);
	close (error_pipe[1]);
    }
    close (error_pipe[1]);
}

void close_error_pipe (int error, char *text)
{
    char *title;
    char msg[MAX_PIPE_SIZE];
    int len = 0;

    if (error)
	title = MSG_ERROR;
    else
	title = " Warning ";
    if (old_error >= 0){
	close (2);
	dup (old_error);
	close (old_error);
	len = read (error_pipe[0], msg, MAX_PIPE_SIZE);

	if (len >= 0)
	    msg[len] = 0;
	close (error_pipe[0]);
    }
    if (error < 0)
	return;		/* Just ignore error message */
    if (text == NULL){
	if (len == 0) return;	/* Nothing to show */

	/* Show message from pipe */
	message (error, title, msg);
    } else {
	/* Show given text and possible message from pipe */
	message (error, title, " %s \n %s ", text, msg);
    }
}

/* Checks for messages in the error pipe,
 * closes the pipe and displays an error box if needed
 */
void check_error_pipe (void)
{
    char error[MAX_PIPE_SIZE];
    int len = 0;
    if (old_error >= 0){
	while (len < MAX_PIPE_SIZE)
	{
            fd_set select_set;
            struct timeval timeout;
            FD_ZERO (&select_set);
            FD_SET (error_pipe[0], &select_set);
            timeout.tv_sec = 0;
            timeout.tv_usec = 0;
            select (FD_SETSIZE, &select_set, 0, 0, &timeout);
            if (!FD_ISSET (0, &select_set))
		break;
	    read (error_pipe[0], error + len, 1);
	    len ++;
	}
	error[len] = 0;
	close (error_pipe[0]);
    }
    if (len > 0)
        message (0, _(" Warning "), error);
}

static struct sigaction ignore, save_intr, save_quit, save_stop;

/* INHANDLE is a result of some mc_open call to any vfs, this function
   returns a normal handle (to be used with read) of a pipe for reading
   of the output of COMMAND with arguments ... (must include argv[0] as
   well) which gets as its input at most INLEN bytes from the INHANDLE
   using mc_read. You have to call mc_doublepclose to close the returned
   handle afterwards. If INLEN is -1, we read as much as we can :) */
int mc_doublepopen (int inhandle, int inlen, pid_t *the_pid, char *command, ...)
{
    int pipe0 [2], pipe1 [2];
    pid_t pid;

#define closepipes() close(pipe0[0]);close(pipe0[1]);close(pipe1[0]);close(pipe1[1])
#define is_a_pipe_fd(f) ((pipe0[0] == f) || (pipe0[1] == f) || (pipe1[0] == f) || (pipe1[1] == f))

    pipe (pipe0); pipe (pipe1);
    ignore.sa_handler = SIG_IGN;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -