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

📄 complete.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Input line filename/username/hostname/variable/command completion.
   (Let mc type for you...)

   Copyright (C) 1995 The Free Software Foundation

   Written by: 1995 Jakub Jelinek

   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 "tty.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#endif

/* unistd.h defines _POSIX_VERSION on POSIX.1 systems. */
#if defined(HAVE_DIRENT_H) || defined(_POSIX_VERSION)
# ifdef __os2__
#   include "dirent.h"
# else
#   include <dirent.h>
# endif
#   define NLENGTH(dirent) (strlen ((dirent)->d_name))
#else
#   define dirent direct
#   define NLENGTH(dirent) ((dirent)->d_namlen)

#   ifdef HAVE_SYS_NDIR_H
#       include <sys/ndir.h>
#   endif /* HAVE_SYS_NDIR_H */

#   ifdef HAVE_SYS_DIR_H
#       include <sys/dir.h>
#   endif /* HAVE_SYS_DIR_H */

#   ifdef HAVE_NDIR_H
#       include <ndir.h>
#   endif /* HAVE_NDIR_H */
#endif /* not (HAVE_DIRENT_H or _POSIX_VERSION) */
#include <sys/types.h>
#include <sys/stat.h>
#ifndef OS2_NT
#   include <pwd.h>
#endif

#include "global.h"
#include "mad.h"
#include "util.h"
#include "win.h"
#include "color.h"
#include "dlg.h"
#include "widget.h"
#include "dialog.h"
#include "wtools.h"
#include "complete.h"
#include "main.h"
#include "key.h"		/* XCTRL and ALT macros */

/* This flag is used in filename_completion_function */
int ignore_filenames = 0;

/* This flag is used by command_completion_function */
/* to hint the filename_completion_function */
int look_for_executables = 0;

char *filename_completion_function (char *text, int state)
{
    static DIR *directory;
    static char *filename = NULL;
    static char *dirname = NULL;
    static char *users_dirname = NULL;
    static int filename_len;
    int isdir = 1, isexec = 0;

    struct dirent *entry = NULL;

    /* If we're starting the match process, initialize us a bit. */
    if (!state){
        char *temp;

        if (dirname)
            free (dirname);
        if (filename)
            free (filename);
        if (users_dirname)
            free (users_dirname);

        filename = strdup (text);
        if (!*text)
            text = ".";
        dirname = strdup (text);

        temp = strrchr (dirname, PATH_SEP);

        if (temp){
	    strcpy (filename, ++temp);
	    *temp = 0;
	}
        else
	    strcpy (dirname, ".");

        /* We aren't done yet.  We also support the "~user" syntax. */

        /* Save the version of the directory that the user typed. */
        users_dirname = strdup (dirname);
        {
	    char *temp_dirname;

	    temp_dirname = tilde_expand (dirname);
	    if (!temp_dirname){
		free (dirname);
		free (users_dirname);
		free (filename);
		dirname = users_dirname = filename = NULL;
		return NULL;
	    }
	    free (dirname);
	    dirname = temp_dirname;
	    canonicalize_pathname (dirname);
	    /* Here we should do something with variable expansion
	       and `command`.
	       Maybe a dream - UNIMPLEMENTED yet. */
        }
        directory = opendir (dirname);
        filename_len = strlen (filename);
    }

    /* Now that we have some state, we can read the directory. */

    while (directory && (entry = readdir (directory))){
        /* Special case for no filename.
	   All entries except "." and ".." match. */
        if (!filename_len){
	    if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, ".."))
	        continue;
	} else {
	    /* Otherwise, if these match up to the length of filename, then
	       it may be a match. */
	    if ((entry->d_name[0] != filename[0]) ||
	        ((NLENGTH (entry)) < filename_len) ||
		strncmp (filename, entry->d_name, filename_len))
	        continue;
	}
	isdir = 1; isexec = 0;
	{
	    char *tmp = xmalloc (3 + strlen (dirname) + NLENGTH (entry), "Filename completion");
	    struct stat tempstat;

	    strcpy (tmp, dirname);
	    strcat (tmp, PATH_SEP_STR);
	    strcat (tmp, entry->d_name);
	    canonicalize_pathname (tmp);
	    /* Unix version */
	    if (!stat (tmp, &tempstat)){
	    	uid_t my_uid = getuid ();
	    	gid_t my_gid = getgid ();

	        if (!S_ISDIR (tempstat.st_mode)){
	            isdir = 0;
	            if ((!my_uid && (tempstat.st_mode & 0111)) ||
	                (my_uid == tempstat.st_uid && (tempstat.st_mode & 0100)) ||
	                (my_gid == tempstat.st_gid && (tempstat.st_mode & 0010)) ||
	                (tempstat.st_mode & 0001))
	                isexec = 1;
	        }
	    }
	    free (tmp);
	}
	switch (look_for_executables)
	{
	    case 2: if (!isexec)
	    	        continue;
	    	    break;
	    case 1: if (!isexec && !isdir)
	    	        continue;
	    	    break;
	}
	if (ignore_filenames && !isdir)
	    continue;
	break;
    }

    if (!entry){
        if (directory){
	    closedir (directory);
	    directory = NULL;
	}
        if (dirname){
	    free (dirname);
	    dirname = NULL;
	}
        if (filename){
	    free (filename);
	    filename = NULL;
	}
        if (users_dirname){
	    free (users_dirname);
	    users_dirname = NULL;
	}
        return NULL;
    } else {
        char *temp;

        if (users_dirname && (users_dirname[0] != '.' || users_dirname[1])){
	    int dirlen = strlen (users_dirname);
	    temp = xmalloc (3 + dirlen + NLENGTH (entry), "Filename completion");
	    strcpy (temp, users_dirname);
	    /* We need a `/' at the end. */
	    if (users_dirname[dirlen - 1] != PATH_SEP){
	        temp[dirlen] = PATH_SEP;
	        temp[dirlen + 1] = 0;
	    }
	    strcat (temp, entry->d_name);
	} else {
	    temp = xmalloc (2 + NLENGTH (entry), "Filename completion");
	    strcpy (temp, entry->d_name);
	}
	if (isdir)
	    strcat (temp, PATH_SEP_STR);
        return temp;
    }
}

/* We assume here that text[0] == '~' , if you want to call it in another way,
   you have to change the code */
#ifdef OS2_NT
char *username_completion_function (char *text, int state)
{
    return NULL;
}
#else
char *username_completion_function (char *text, int state)
{
    static struct passwd *entry;
    static int userlen;

    if (!state){ /* Initialization stuff */
        setpwent ();
        userlen = strlen (text + 1);
    }
    while ((entry = getpwent ()) != NULL){
        /* Null usernames should result in all users as possible completions. */
        if (!userlen)
            break;
        else if (text[1] == entry->pw_name[0] &&
	         !strncmp (text + 1, entry->pw_name, userlen))
	    break;
    }

    if (!entry){
        endpwent ();
        return NULL;
    } else {
        char *temp = xmalloc (3 + strlen (entry->pw_name), "Username completion");

        *temp = '~';
        strcpy (temp + 1, entry->pw_name);
        strcat (temp, PATH_SEP_STR);
        return temp;
    }
}

extern char **environ;
#endif /* OS2_NT */

/* We assume text [0] == '$' and want to have a look at text [1], if it is
   equal to '{', so that we should append '}' at the end */
char *variable_completion_function (char *text, int state)
{
    static char **env_p;
    static int varlen, isbrace;
    char *p = 0;

    if (!state){ /* Initialization stuff */
	isbrace = (text [1] == '{');
        varlen = strlen (text + 1 + isbrace);
        env_p = environ;
    }

    while (*env_p){
    	p = strchr (*env_p, '=');
    	if (p && p - *env_p >= varlen && !strncmp (text + 1 + isbrace, *env_p, varlen))
    	    break;
    	env_p++;
    }

    if (!*env_p)
        return NULL;
    else {
        char *temp = xmalloc (2 + 2 * isbrace + p - *env_p, "Variable completion");

	*temp = '$';
	if (isbrace)
	    temp [1] = '{';
        strncpy (temp + 1 + isbrace, *env_p, p - *env_p);
        if (isbrace)
            strcpy (temp + 2 + (p - *env_p), "}");
        else
            temp [1 + p - *env_p] = 0;
        env_p++;
        return temp;
    }
}

#define whitespace(c) ((c) == ' ' || (c) == '\t')
#define cr_whitespace(c) (whitespace (c) || (c) == '\n' || (c) == '\r')

static char **hosts = NULL;
static char **hosts_p = NULL;
static int hosts_alloclen = 0;
static void fetch_hosts (char *filename)
{
    FILE *file = fopen (filename, "r");
    char *temp, buffer[256], *name;
    register int i, start;

    if (!file)
        return;

    while ((temp = fgets (buffer, 255, file)) != NULL){
        /* Skip to first character. */
        for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++);
        /* Ignore comments... */
        if (buffer[i] == '#')
            continue;
        /* Handle $include. */
        if (!strncmp (buffer + i, "$include ", 9)){
	    char *includefile = buffer + i + 9;
	    char *t;

	    /* Find start of filename. */
	    while (*includefile && whitespace (*includefile))
	        includefile++;
	    t = includefile;

	    /* Find end of filename. */
	    while (*t && !cr_whitespace (*t))

⌨️ 快捷键说明

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