📄 ls.c
字号:
{#ifdef SA_NOCLDSTOP struct sigaction sigact; sigact.sa_handler = SIG_DFL; sigemptyset (&sigact.sa_mask); sigact.sa_flags = 0; sigaction (sig, &sigact, NULL);#else signal (sig, SIG_DFL);#endif } raise (sig);}intmain (int argc, char **argv){ register int i; register struct pending *thispend; unsigned int n_files; program_name = argv[0]; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); atexit (close_stdout);#define N_ENTRIES(Array) (sizeof Array / sizeof *(Array)) assert (N_ENTRIES (color_indicator) + 1 == N_ENTRIES (indicator_name)); exit_status = 0; dir_defaulted = 1; print_dir_name = 1; pending_dirs = 0; i = decode_switches (argc, argv); if (print_with_color) parse_ls_color (); /* Test print_with_color again, because the call to parse_ls_color may have just reset it -- e.g., if LS_COLORS is invalid. */ if (print_with_color) { prep_non_filename_text (); /* Avoid following symbolic links when possible. */ if (color_indicator[C_ORPHAN].string != NULL || (color_indicator[C_MISSING].string != NULL && format == long_format)) check_symlink_color = 1; { unsigned j; static int const sigs[] = { SIGHUP, SIGINT, SIGPIPE, SIGQUIT, SIGTERM, SIGTSTP }; unsigned nsigs = sizeof sigs / sizeof *sigs;#ifdef SA_NOCLDSTOP struct sigaction oldact, newact; sigset_t caught_signals; sigemptyset (&caught_signals); for (j = 0; j < nsigs; j++) sigaddset (&caught_signals, sigs[j]); newact.sa_handler = sighandler; newact.sa_mask = caught_signals; newact.sa_flags = 0;#endif for (j = 0; j < nsigs; j++) { int sig = sigs[j];#ifdef SA_NOCLDSTOP sigaction (sig, NULL, &oldact); if (oldact.sa_handler != SIG_IGN) sigaction (sig, &newact, NULL);#else if (signal (sig, SIG_IGN) != SIG_IGN) signal (sig, sighandler);#endif } } } if (dereference == DEREF_UNDEFINED) dereference = ((immediate_dirs || indicator_style == classify || format == long_format) ? DEREF_NEVER : DEREF_COMMAND_LINE_SYMLINK_TO_DIR); /* When using -R, initialize a data structure we'll use to detect any directory cycles. */ if (recursive) { active_dir_set = hash_initialize (INITIAL_TABLE_SIZE, NULL, dev_ino_hash, dev_ino_compare, dev_ino_free); if (active_dir_set == NULL) xalloc_die (); obstack_init (&dev_ino_obstack); } format_needs_stat = sort_type == sort_time || sort_type == sort_size || format == long_format || dereference == DEREF_ALWAYS || print_block_size || print_inode; format_needs_type = (format_needs_stat == 0 && (recursive || print_with_color || indicator_style != none)); if (dired) { obstack_init (&dired_obstack); obstack_init (&subdired_obstack); } nfiles = 100; files = XMALLOC (struct fileinfo, nfiles); files_index = 0; clear_files (); n_files = argc - i; if (0 < n_files) dir_defaulted = 0; for (; i < argc; i++) { gobble_file (argv[i], unknown, 1, ""); } if (dir_defaulted) { if (immediate_dirs) gobble_file (".", directory, 1, ""); else queue_directory (".", 0); } if (files_index) { sort_files (); if (!immediate_dirs) extract_dirs_from_files ("", 0); /* `files_index' might be zero now. */ } /* In the following if/else blocks, it is sufficient to test `pending_dirs' (and not pending_dirs->name) because there may be no markers in the queue at this point. A marker may be enqueued when extract_dirs_from_files is called with a non-empty string or via print_dir. */ if (files_index) { print_current_files (); if (pending_dirs) DIRED_PUTCHAR ('\n'); } else if (n_files <= 1 && pending_dirs && pending_dirs->next == 0) print_dir_name = 0; while (pending_dirs) { thispend = pending_dirs; pending_dirs = pending_dirs->next; if (LOOP_DETECT) { if (thispend->name == NULL) { /* thispend->name == NULL means this is a marker entry indicating we've finished processing the directory. Use its dev/ino numbers to remove the corresponding entry from the active_dir_set hash table. */ struct dev_ino di = dev_ino_pop (); struct dev_ino *found = hash_delete (active_dir_set, &di); /* ASSERT_MATCHING_DEV_INO (thispend->realname, di); */ assert (found); dev_ino_free (found); free_pending_ent (thispend); continue; } } print_dir (thispend->name, thispend->realname); free_pending_ent (thispend); print_dir_name = 1; } if (dired) { /* No need to free these since we're about to exit. */ dired_dump_obstack ("//DIRED//", &dired_obstack); dired_dump_obstack ("//SUBDIRED//", &subdired_obstack); printf ("//DIRED-OPTIONS// --quoting-style=%s\n", quoting_style_args[get_quoting_style (filename_quoting_options)]); } /* Restore default color before exiting */ if (print_with_color) { put_indicator (&color_indicator[C_LEFT]); put_indicator (&color_indicator[C_RIGHT]); } if (LOOP_DETECT) { assert (hash_get_n_entries (active_dir_set) == 0); hash_free (active_dir_set); } exit (exit_status);}/* Set all the option flags according to the switches specified. Return the index of the first non-option argument. */static intdecode_switches (int argc, char **argv){ int c; char *time_style_option = 0; /* Record whether there is an option specifying sort type. */ int sort_type_specified = 0; qmark_funny_chars = 0; /* initialize all switches to default settings */ switch (ls_mode) { case LS_MULTI_COL: /* This is for the `dir' program. */ format = many_per_line; set_quoting_style (NULL, escape_quoting_style); break; case LS_LONG_FORMAT: /* This is for the `vdir' program. */ format = long_format; set_quoting_style (NULL, escape_quoting_style); break; case LS_LS: /* This is for the `ls' program. */ if (isatty (STDOUT_FILENO)) { format = many_per_line; /* See description of qmark_funny_chars, above. */ qmark_funny_chars = 1; } else { format = one_per_line; qmark_funny_chars = 0; } break; default: abort (); } time_type = time_mtime; sort_type = sort_name; sort_reverse = 0; numeric_ids = 0; print_block_size = 0; indicator_style = none; print_inode = 0; dereference = DEREF_UNDEFINED; recursive = 0; immediate_dirs = 0; all_files = 0; really_all_files = 0; ignore_patterns = 0; /* FIXME: put this in a function. */ { char const *q_style = getenv ("QUOTING_STYLE"); if (q_style) { int i = ARGMATCH (q_style, quoting_style_args, quoting_style_vals); if (0 <= i) set_quoting_style (NULL, quoting_style_vals[i]); else error (0, 0, _("ignoring invalid value of environment variable QUOTING_STYLE: %s"), quotearg (q_style)); } } { char const *ls_block_size = getenv ("LS_BLOCK_SIZE"); human_output_opts = human_options (ls_block_size, false, &output_block_size); if (ls_block_size || getenv ("BLOCK_SIZE")) file_output_block_size = output_block_size; } line_length = 80; { char const *p = getenv ("COLUMNS"); if (p && *p) { long int tmp_long; if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK && 0 < tmp_long && tmp_long <= INT_MAX) { line_length = (int) tmp_long; } else { error (0, 0, _("ignoring invalid width in environment variable COLUMNS: %s"), quotearg (p)); } } }#ifdef TIOCGWINSZ { struct winsize ws; if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0) line_length = ws.ws_col; }#endif /* Using the TABSIZE environment variable is not POSIX-approved. Ignore it when POSIXLY_CORRECT is set. */ { char const *p; tabsize = 8; if (!getenv ("POSIXLY_CORRECT") && (p = getenv ("TABSIZE"))) { long int tmp_long; if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK && 0 <= tmp_long && tmp_long <= INT_MAX) { tabsize = (int) tmp_long; } else { error (0, 0, _("ignoring invalid tab size in environment variable TABSIZE: %s"), quotearg (p)); } } } while ((c = getopt_long (argc, argv, "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1", long_options, NULL)) != -1) { switch (c) { case 0: break; case 'a': all_files = 1; really_all_files = 1; break; case 'b': set_quoting_style (NULL, escape_quoting_style); break; case 'c': time_type = time_ctime; break; case 'd': immediate_dirs = 1; break; case 'f': /* Same as enabling -a -U and disabling -l -s. */ all_files = 1; really_all_files = 1; sort_type = sort_none; sort_type_specified = 1; /* disable -l */ if (format == long_format) format = (isatty (STDOUT_FILENO) ? many_per_line : one_per_line); print_block_size = 0; /* disable -s */ print_with_color = 0; /* disable --color */ break; case 'g': format = long_format; print_owner = 0; break; case 'h': human_output_opts = human_autoscale | human_SI | human_base_1024; file_output_block_size = output_block_size = 1; break; case 'i': print_inode = 1; break; case 'k': human_output_opts = 0; file_output_block_size = output_block_size = 1024; break; case 'l': format = long_format; break; case 'm': format = with_commas; break; case 'n': numeric_ids = 1; format = long_format; break; case 'o': /* Just like -l, but don't display group info. */ format = long_format; print_group = 0; break; case 'p': indicator_style = file_type; break; case 'q': qmark_funny_chars = 1; break; case 'r': sort_reverse = 1; break; case 's': print_block_size = 1; break; case 't': sort_type = sort_time; sort_type_specified = 1; break; case 'u': time_type = time_atime; break; case 'v': sort_type = sort_version; sort_type_specified = 1; break; case 'w': { long int tmp_long; if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK || tmp_long <= 0 || tmp_long > INT_MAX) error (EXIT_FAILURE, 0, _("invalid line width: %s"), quotearg (optarg)); line_length = (int) tmp_long; break; } case 'x': format = horizontal; break; case 'A': really_all_files = 0; all_files = 1; break; case 'B': add_ignore_pattern ("*~"); add_ignore_pattern (".*~"); break; case 'C': format = many_per_line; break; case 'D': dired = 1; break; case 'F': indicator_style = classify; break; case 'G': /* inhibit display of group info */ print_group = 0; break; case 'H': dereference = DEREF_COMMAND_LINE_ARGUMENTS; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -