?? cfls.c
字號(hào):
/* `dir', `vdir' and `ls' directory listing programs for GNU.
Copyright (C) 1985, 1988, 1989, 1990 Free Software Foundation, Inc.
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 1, 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. */
/* If the macro MULTI_COL is defined,
the multi-column format is the default regardless
of the type of output device.
This is for the `dir' program.
If the macro LONG_FORMAT is defined,
the long format is the default regardless of the
type of output device.
This is for the `vdir' program.
If neither is defined,
the output format depends on whether the output
device is a terminal.
This is for the `ls' program. */
/* Written by Richard Stallman and David MacKenzie. */
/* Modified for PCDOS and 32 Char filenames by Norman D. Culver */
/* Additonal mods for cff */
#include "cfls.h"
/* Return an int indicating the result of comparing two longs. */
#ifdef INT_16_BITS
#define longdiff(a, b) ((a) < (b) ? -1 : (a) > (b) ? 1 : 0)
#else
#define longdiff(a, b) ((a) - (b))
#endif
int glob_match ();
char *copystring ();
char *getgroup ();
char *getuser ();
char *make_link_path ();
char *xmalloc ();
char *xrealloc ();
int argmatch ();
int compare_atime ();
int rev_cmp_atime ();
int compare_ctime ();
int rev_cmp_ctime ();
int compare_mtime ();
int rev_cmp_mtime ();
int compare_size ();
int rev_cmp_size ();
int compare_name ();
int rev_cmp_name ();
int compare_extension ();
int rev_cmp_extension ();
int decode_switches ();
int file_interesting ();
long gobble_file ();
int is_not_dot_or_dotdot ();
int length_of_file_name_and_frills ();
void add_ignore_pattern ();
void add_list_pattern ();
void attach ();
void clear_files ();
void error ();
void extract_dirs_from_files ();
void get_link_name ();
void indent ();
void invalid_arg ();
void print_current_files ();
void print_dir ();
void print_file_name_and_frills ();
void print_horizontal ();
void print_long_format ();
void print_many_per_line ();
void print_name_with_quoting ();
void print_type_indicator ();
void print_with_commas ();
void queue_directory ();
void sort_files ();
void usage ();
enum filetype
{
symbolic_link,
directory,
arg_directory, /* Directory given as command line arg. */
normal /* All others. */
};
typedef struct _lstat {
unsigned long st_mode;
unsigned long st_atime;
unsigned long st_mtime;
unsigned long st_ctime;
unsigned long st_ino;
unsigned long st_size;
unsigned long st_alloc;
} LSTAT;
struct file
{
/* The file name. */
char *name;
int namlen;
LSTAT stats;
char *linkname;
unsigned long linkmode;
enum filetype filetype;
};
/* The table of files in the current directory:
`files' points to a vector of `struct file', one per file.
`nfiles' is the number of elements space has been allocated for.
`files_index' is the number actually in use. */
/* Address of block containing the files that are described. */
struct file *files;
/* Length of block that `files' points to, measured in files. */
int nfiles;
/* Index of first unused in `files'. */
int files_index;
/* Record of one pending directory waiting to be listed. */
struct pending
{
char *name;
/* If the directory is actually the file pointed to by a symbolic link we
were told to list, `realname' will contain the name of the symbolic
link, otherwise zero. */
char *realname;
struct ignore_pattern *list_patterns;
struct pending *next;
};
struct pending *pending_dirs;
/* Current time (seconds since 1970). When we are printing a file's time,
include the year if it is more than 6 months before this time. */
long current_time;
/* The number of digits to use for block sizes.
4, or more if needed for bigger numbers. */
int block_size_size;
/* The name the program was run with, stripped of any leading path. */
char *program_name;
/* Option flags */
/* long_format for lots of info, one per line.
one_per_line for just names, one per line.
many_per_line for just names, many per line, sorted vertically.
horizontal for just names, many per line, sorted horizontally.
with_commas for just names, many per line, separated by commas.
-l, -1, -C, -x and -m control this parameter. */
enum format
{
long_format, /* -l */
one_per_line, /* -1 */
many_per_line, /* -C */
horizontal, /* -x */
with_commas /* -m */
};
enum format format;
/* Type of time to print or sort by. Controlled by -c and -u. */
enum time_type
{
time_mtime, /* default */
time_ctime, /* -c */
time_atime /* -u */
};
enum time_type time_type;
/* The file characteristic to sort by. Controlled by -t, -S, -U, -X. */
enum sort_type
{
sort_none, /* -U */
sort_name, /* default */
sort_extension, /* -X */
sort_time, /* -t */
sort_size /* -S */
};
enum sort_type sort_type;
/* Direction of sort.
0 means highest first if numeric,
lowest first if alphabetic;
these are the defaults.
1 means the opposite order in each case. -r */
int sort_reverse;
/* Nonzero means print the user and group id's as numbers rather
than as names. -n */
int numeric_users;
/* Nonzero means mention the size in 512 byte blocks of each file. -s */
int print_block_size;
/* Nonzero means show file sizes in kilobytes instead of blocks
(the size of which is system-dependant). -k */
int kilobyte_blocks;
/* none means don't mention the type of files.
all means mention the types of all files.
not_programs means do so except for executables.
Controlled by -F and -p. */
enum indicator_style
{
none, /* default */
all, /* -F */
not_programs /* -p */
};
enum indicator_style indicator_style;
/* Nonzero means mention the inode number of each file. -i */
int print_inode;
/* Nonzero means when a symbolic link is found, display info on
the file linked to. -L */
int trace_links;
/* Nonzero means when a directory is found, display info on its
contents. -R */
int trace_dirs;
/* Nonzero means when an argument is a directory name, display info
on it itself. -d */
int immediate_dirs;
/* Nonzero means don't omit files whose names start with `.'. -A */
int all_files;
/* Nonzero means don't omit files `.' and `..'
This flag implies `all_files'. -a */
int really_all_files;
/* A linked list of shell-style globbing patterns. If a non-argument
file name matches any of these patterns, it is omitted, or listed.
List_patterns only occur if the shell fails to glob a pattern on
the command line, PCDOS is a good example. Ignore_patterns are
controlled by -I. Multiple -I options accumulate.
The -B option adds `*~' and `.*~' to this list. */
struct ignore_pattern
{
char *pattern;
struct ignore_pattern *next;
};
struct ignore_pattern *ignore_patterns;
/* Nonzero means quote nongraphic chars in file names. -b */
int quote_funny_chars;
/* Nonzero means output nongraphic chars in file names as `?'. -q */
int qmark_funny_chars;
/* Nonzero means output each file name using C syntax for a string.
Always accompanied by `quote_funny_chars'.
This mode, together with -x or -C or -m,
and without such frills as -F or -s,
is guaranteed to make it possible for a program receiving
the output to tell exactly what file names are present. -Q */
int quote_as_string;
/* The number of chars per hardware tab stop. -T */
int tabsize;
/* Nonzero means we are listing the working directory because no
non-option arguments were given. */
int dir_defaulted;
/* Nonzero means print each directory name before listing it. */
int print_dir_name;
/* The line length to use for breaking lines in many-per-line format.
Can be set with -w. */
int line_length;
/* If nonzero, the file listing format requires that stat be called on
each file. */
int format_needs_stat;
struct option long_options[] =
{
{"all", 0, NULL, 'a'},
{"escape", 0, NULL, 'b'},
{"directory", 0, NULL, 'd'},
{"inode", 0, NULL, 'i'},
{"kilobytes", 0, NULL, 'k'},
{"numeric-uid-gid", 0, NULL, 'n'},
{"hide-control-chars", 0, NULL, 'q'},
{"reverse", 0, NULL, 'r'},
{"size", 0, NULL, 's'},
{"width", 1, NULL, 'w'},
{"almost-all", 0, NULL, 'A'},
{"ignore-backups", 0, NULL, 'B'},
{"classify", 0, NULL, 'F'},
{"file-type", 0, NULL, 'F'},
{"ignore", 1, NULL, 'I'},
{"dereference", 0, NULL, 'L'},
{"literal", 0, NULL, 'N'},
{"quote-name", 0, NULL, 'Q'},
{"recursive", 0, NULL, 'R'},
{"format", 1, NULL, 12},
{"sort", 1, NULL, 10},
{"tabsize", 1, NULL, 'T'},
{"time", 1, NULL, 11},
{NULL, 0, NULL, 0}
};
char *format_args[] =
{
"verbose", "long", "commas", "horizontal", "across",
"vertical", "single-column", NULL
};
enum format formats[] =
{
long_format, long_format, with_commas, horizontal, horizontal,
many_per_line, one_per_line
};
char *sort_args[] =
{
"none", "time", "size", "extension", 0
};
enum sort_type sort_types[] =
{
sort_none, sort_time, sort_size, sort_extension
};
char *time_args[] =
{
"atime", "access", "use", "ctime", "status", 0
};
enum time_type time_types[] =
{
time_atime, time_atime, time_atime, time_ctime, time_ctime
};
static int
is_printable(const char *cp, int len)
{
register int i;
for(i = 0; i < len; ++i) {
if(!isgraph(cp[i])) {
if(cp[i] == '\0')
break;
return 0;
}
}
return (i > 0) ? 1 : 0;
}
/* Set all the option flags according to the switches specified.
Return the index of the first non-option argument. */
int
decode_switches (argc, argv)
int argc;
char **argv;
{
register char *p;
int c;
int longind;
qmark_funny_chars = 0;
quote_funny_chars = 0;
/* initialize all switches to default settings */
#ifdef MULTI_COL
#define PROGNAME "dir"
/* This is for the `dir' program. */
format = many_per_line;
quote_funny_chars = 1;
#else
#ifdef LONG_FORMAT
#define PROGNAME "vdir"
/* This is for the `vdir' program. */
format = long_format;
quote_funny_chars = 1;
#else
#define PROGNAME "cfls"
/* This is for the `ls' program. */
if (isatty (1))
{
format = many_per_line;
qmark_funny_chars = 1;
}
else
{
format = one_per_line;
qmark_funny_chars = 0;
}
#endif
#endif
time_type = time_mtime;
sort_type = sort_name;
sort_reverse = 0;
numeric_users = 0;
print_block_size = 0;
kilobyte_blocks = 0;
indicator_style = none;
print_inode = 0;
trace_links = 0;
trace_dirs = 0;
immediate_dirs = 0;
all_files = 0;
really_all_files = 0;
ignore_patterns = 0;
quote_as_string = 0;
p = getenv ("COLUMNS");
line_length = p ? atoi (p) : 80;
#ifdef TIOCGWINSZ
{
struct winsize ws;
if (ioctl (1, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0)
line_length = ws.ws_col;
}
#endif
p = getenv ("TABSIZE");
tabsize = p ? atoi (p) : 8;
while ((c = getopt_long (argc, argv, "abcdgiklmnpqrstuw:xABCFI:LNQRST:UX1",
long_options, &longind)) != EOF)
{
switch (c)
{
case 'a':
all_files = 1;
really_all_files = 1;
break;
case 'b':
quote_funny_chars = 1;
qmark_funny_chars = 0;
break;
case 'c':
time_type = time_ctime;
break;
case 'd':
immediate_dirs = 1;
break;
case 'g':
/* No effect. For BSD compatibility. */
break;
case 'i':
print_inode = 1;
break;
case 'k':
kilobyte_blocks = 1;
break;
case 'l':
format = long_format;
break;
case 'm':
format = with_commas;
break;
case 'n':
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -