static struct pidset filter_out_forks(struct pidset in) { /* * Discard any process whose parent is also in our remaining match * set and looks sufficiently like it for us to decide this one's * an uninteresting fork (e.g. of a shell script executing a * complex pipeline). */ struct pidset ret; int pid; pidset_init(&ret); for (pid = pidset_first(&in); pid >= 0; pid = pidset_next(&in)) { const struct procdata *proc = get_proc(pid); if (pidset_in(&in, proc->ppid)) { /* The parent is in our set too. Is it similar? */ const struct procdata *parent = get_proc(proc->ppid); if (!strnullcmp(parent->exe, proc->exe) && !argcmp(parent->argv, proc->argv)) { /* Yes; don't list it. */ continue; } } pidset_add(&ret, pid); } return ret; }
static int find_prefix_opt(const char *arg, int nopt, Clp_Option *opt, Clp_LongMinMatch *lmmvec, int *ambiguous, int *ambiguous_values, int negated) /* Looks for an unambiguous match of `arg' against one of the long options in `opt'. Returns positive if it finds one; otherwise, returns -1 and possibly changes `ambiguous' and `ambiguous_values' to keep track of at most MAX_AMBIGUOUS_VALUES possibilities. */ { int i; for (i = 0; i < nopt; i++) { int len, lmm; if (!opt[i].long_name || (negated && !TEST(&opt[i], Clp_Negate)) || (!negated && TEST(&opt[i], Clp_OnlyNegated))) continue; lmm = (negated ? lmmvec[i].neg : lmmvec[i].pos); len = argcmp(opt[i].long_name, arg, lmm); if (len > 0) return i; else if (len < 0) { if (*ambiguous < MAX_AMBIGUOUS_VALUES) ambiguous_values[*ambiguous] = i; (*ambiguous)++; } } return -1; }
static int parse_bool(Clp_Parser *clp, const char *arg, int complain, void *thunk) { int i; char lcarg[6]; if (strlen(arg) > 5 || strchr(arg, '=') != 0) goto error; for (i = 0; arg[i] != 0; i++) lcarg[i] = tolower(arg[i]); lcarg[i] = 0; if (argcmp("yes", lcarg, 1) > 0 || argcmp("true", lcarg, 1) > 0 || argcmp("1", lcarg, 1) > 0) { clp->val.i = 1; return 1; } else if (argcmp("no", lcarg, 1) > 0 || argcmp("false", lcarg, 1) > 0 || argcmp("1", lcarg, 1) > 0) { clp->val.i = 0; return 1; } error: if (complain) Clp_OptionError(clp, "`%O' expects a true-or-false value, not `%s'", arg); return 0; }
static Clp_Option * find_long(Clp_Parser *clp, char *arg) /* If arg corresponds to one of clp's options, finds that option & returns it. If any argument is given after an = sign in arg, sets clp->have_arg = 1 and clp->arg to that argument. Sets cli->ambiguous to 1 iff there was no match because the argument was ambiguous. */ { Clp_Internal *cli = clp->internal; int value, len; Clp_Option *opt = cli->opt; int first_negative_ambiguous; /* Look for a normal option. */ value = find_prefix_opt (arg, cli->nopt, opt, cli->long_min_match, &cli->ambiguous, cli->ambiguous_values, clp->negated); if (value >= 0) goto worked; /* If we can't find it, look for a negated option. */ /* I know this is silly, but it makes me happy to accept --no-no-option as a double negative synonym for --option. :) */ first_negative_ambiguous = cli->ambiguous; while (arg[0] == 'n' && arg[1] == 'o' && arg[2] == '-') { arg += 3; clp->negated = !clp->negated; value = find_prefix_opt (arg, cli->nopt, opt, cli->long_min_match, &cli->ambiguous, cli->ambiguous_values, clp->negated); if (value >= 0) goto worked; } /* No valid option was found; return 0. Mark the ambiguous values found through `--no' by making them negative. */ { int i, max = cli->ambiguous; if (max > MAX_AMBIGUOUS_VALUES) max = MAX_AMBIGUOUS_VALUES; for (i = first_negative_ambiguous; i < max; i++) cli->ambiguous_values[i] = -cli->ambiguous_values[i] - 1; return 0; } worked: len = argcmp(opt[value].long_name, arg, cli->long_min_match[value].pos); if (arg[len] == '=') { clp->have_arg = 1; clp->arg = arg + len + 1; } return &opt[value]; }
/* wc counts the number of bytes, words, and/or lines in a file or group of files. */ int main(int argc, char *argv[]) { int byte_flag = 0; int word_flag = 0; int line_flag = 0; int length_flag = 0; int file_index = 0; /* process flags */ for (int i = 1; i < argc && !file_index; ++i) { if (argcmp(argv[i],"-c","--chars")) byte_flag = 1; else if (argcmp(argv[i],"-w","--words")) word_flag = 1; else if (argcmp(argv[i],"-l","--lines")) line_flag = 1; else if (argcmp(argv[i],"-L","--max-line-length")) length_flag = 1; else if (argcmp(argv[i],"-h","--help")) { print_help(); exit(EXIT_SUCCESS); } else if (argcmp(argv[i],"-v","--version")) { print_version(); exit(EXIT_SUCCESS); } else file_index = i; } int file_count = argc - file_index; if (!byte_flag && !word_flag && !line_flag && !length_flag) { byte_flag = word_flag = line_flag = 1; } /* TODO: handle piped input */ int piped = 0; char *piped_input; if(!isatty(fileno(stdin))) { piped_input = read_stdin(); piped = 1; file_count = 1; } /* user error: no piped input and no files given */ if (argc == 1 && !piped) { print_usage(); exit(EXIT_SUCCESS); } FILE *src; int bytes[file_count]; int words[file_count]; int lines[file_count]; int lengths[file_count]; if (!piped) { // process files int file_failure = 0; for (int i = 0; i < file_count; ++i) { if (!(src=fopen(argv[i+file_index], "r"))) { printf( "wc: %s: file cound not be opened" "(or does not exist)\n", argv[i+file_index]); file_failure = 1; continue; } if (byte_flag) bytes[i] = byte_count_file(src); if (word_flag) words[i] = word_count_file(src); if (line_flag) lines[i] = line_count_file(src); if (length_flag) lengths[i] = max_line_length_file(src); fclose(src); } if (file_failure) exit(EXIT_FAILURE); } else { // process STDIN if (byte_flag) bytes[0] = byte_count_str(piped_input); if (word_flag) words[0] = word_count_str(piped_input); if (line_flag) lines[0] = line_count_str(piped_input); if (length_flag) lengths[0] = max_line_length_str(piped_input); } int bytes_total; int words_total; int lines_total; int length_total; int bytes_digits; int words_digits; int lines_digits; int length_digits; for (int i=0; i<file_count; ++i) { if (byte_flag) { bytes_total = sum(bytes, file_count); bytes_digits = log10(bytes_total) + 2; } if (word_flag) { words_total = sum(words, file_count); words_digits = log10(words_total) + 2; } if (line_flag) { lines_total = sum(lines, file_count); lines_digits = log10(lines_total) + 2; } if (length_flag) { length_total = maximum(lengths[i], length_total); length_digits = log10(length_total) + 2; } } /* print requested counts */ for (int i=0; i<file_count; ++i) { if (line_flag) printf("%*d ", lines_digits, lines[i]); if (word_flag) printf("%*d ", words_digits, words[i]); if (byte_flag) printf("%*d ", bytes_digits, bytes[i]); if (length_flag) printf("%*d ", length_digits, lengths[i]); if (!piped) printf(" %s\n", argv[i+file_index]); else printf("\n"); } /* print 'total' line if multiple files were passed to wc */ if (file_count > 1) { if (line_flag) printf("%*d ", lines_digits, lines_total); if (word_flag) printf("%*d ", words_digits, words_total); if (byte_flag) printf("%*d ", bytes_digits, bytes_total); if (length_flag) printf("%*d ", length_digits, length_total); printf(" total\n"); } return 0; }