/* cp->cache[N] is allocated and must be filled in this case */ static int get_cached(cache_t *cp, uid_t id) { int i; for (i = 0; i < cp->size; i++) if (cp->cache[i].id == id) return i; i = cp->size++; cp->cache = xrealloc_vector(cp->cache, 2, i); cp->cache[i++].id = id; return -i; }
static void fill_match_lines(unsigned pos) { if (!pattern_valid) return; /* Run the regex on each line of the current file */ while (pos <= max_fline) { /* If this line matches */ if (regexec(&pattern, flines[pos], 0, NULL, 0) == 0 /* and we didn't match it last time */ && !(num_matches && match_lines[num_matches-1] == pos) ) { match_lines = xrealloc_vector(match_lines, 4, num_matches); match_lines[num_matches++] = pos; } pos++; } }
/* Add line and/or update count */ static void save_line(const char *string, int count) { int i; for (i = 0; i < G.lines_cnt; i++) { if (strcmp(string, G.lines[i].string) == 0) { /* It's already there, only update count */ G.lines[i].count += count; return; } } /* Add new line */ G.lines = xrealloc_vector(G.lines, 4, G.lines_cnt); G.lines[G.lines_cnt].string = xstrdup(string); G.lines[G.lines_cnt].count = count; /*G.lines[G.lines_cnt].disk_count = 0;*/ G.lines_cnt++; }
static void parse_conf_file(const char *filename) { parser_t *parser; char *tokens[2]; parser = config_open2(filename, fopen_for_read); if (parser) { while (config_read(parser, tokens, 2, 2, "# \t", PARSE_NORMAL)) { act_tab = xrealloc_vector(act_tab, 1, n_act); act_tab[n_act].key = xstrdup(tokens[0]); act_tab[n_act].action = xstrdup(tokens[1]); n_act++; } config_close(parser); } else { act_tab = (void*)f_act_tab; n_act = ARRAY_SIZE(f_act_tab); } }
void FAST_FUNC erase_mtab(const char *name) { struct mntent *entries; int i, count; FILE *mountTable; struct mntent *m; mountTable = setmntent(bb_path_mtab_file, "r"); /* Bummer. Fall back on trying the /proc filesystem */ if (!mountTable) mountTable = setmntent("/proc/mounts", "r"); if (!mountTable) { bb_perror_msg(bb_path_mtab_file); return; } entries = NULL; count = 0; while ((m = getmntent(mountTable)) != 0) { entries = xrealloc_vector(entries, 3, count); entries[count].mnt_fsname = xstrdup(m->mnt_fsname); entries[count].mnt_dir = xstrdup(m->mnt_dir); entries[count].mnt_type = xstrdup(m->mnt_type); entries[count].mnt_opts = xstrdup(m->mnt_opts); entries[count].mnt_freq = m->mnt_freq; entries[count].mnt_passno = m->mnt_passno; count++; } endmntent(mountTable); //TODO: make update atomic mountTable = setmntent(bb_path_mtab_file, "w"); if (mountTable) { for (i = 0; i < count; i++) { if (strcmp(entries[i].mnt_fsname, name) != 0 && strcmp(entries[i].mnt_dir, name) != 0) addmntent(mountTable, &entries[i]); } endmntent(mountTable); } else if (errno != EROFS) bb_perror_msg(bb_path_mtab_file); }
/* This finds the pid of the specified process. * Currently, it's implemented by rummaging through * the proc filesystem. * * Returns a list of all matching PIDs * It is the caller's duty to free the returned pidlist. * * Modified by Vladimir Oleynik for use with libbb/procps.c */ pid_t* FAST_FUNC find_pid_by_name(const char *procName) { pid_t* pidList; int i = 0; procps_status_t* p = NULL; pidList = xzalloc(sizeof(*pidList)); while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_COMM|PSSCAN_ARGVN/*|PSSCAN_EXE*/))) { if (comm_match(p, procName) /* or we require argv0 to match (essential for matching reexeced /proc/self/exe)*/ || (p->argv0 && strcmp(bb_basename(p->argv0), procName) == 0) /* or we require /proc/PID/exe link to match */ /* || (p->exe && strcmp(bb_basename(p->exe), procName) == 0)*/ ) { pidList = xrealloc_vector(pidList, 2, i); pidList[i++] = p->pid; } } pidList[i] = 0; return pidList; }
/* * Register several long options. options is a string of long options, * separated by commas or whitespace. * This nukes options! */ static struct option *add_long_options(struct option *long_options, char *options) { int long_nr = 0; int arg_opt, tlen; char *tokptr = strtok(options, ", \t\n"); if (long_options) while (long_options[long_nr].name) long_nr++; while (tokptr) { arg_opt = no_argument; tlen = strlen(tokptr); if (tlen) { tlen--; if (tokptr[tlen] == ':') { arg_opt = required_argument; if (tlen && tokptr[tlen-1] == ':') { tlen--; arg_opt = optional_argument; } tokptr[tlen] = '\0'; if (tlen == 0) bb_error_msg_and_die("empty long option specified"); } long_options = xrealloc_vector(long_options, 4, long_nr); long_options[long_nr].has_arg = arg_opt; /*long_options[long_nr].flag = NULL; - xrealloc_vector did it */ long_options[long_nr].val = LONG_OPT; long_options[long_nr].name = xstrdup(tokptr); long_nr++; /*memset(&long_options[long_nr], 0, sizeof(long_options[0])); - xrealloc_vector did it */ } tokptr = strtok(NULL, ", \t\n"); } return long_options; }
static void parse_map_file(const char *filename) { parser_t *parser; char *tokens[6]; parser = config_open2(filename, fopen_for_read); if (parser) { while (config_read(parser, tokens, 6, 6, "# \t", PARSE_NORMAL)) { evt_tab = xrealloc_vector(evt_tab, 1, n_evt); evt_tab[n_evt].s_type = xstrdup(tokens[0]); evt_tab[n_evt].n_type = xstrtou(tokens[1], 16); evt_tab[n_evt].s_code = xstrdup(tokens[2]); evt_tab[n_evt].n_code = xatou16(tokens[3]); evt_tab[n_evt].value = xatoi_positive(tokens[4]); evt_tab[n_evt].desc = xstrdup(tokens[5]); n_evt++; } config_close(parser); } else { evt_tab = (void*)f_evt_tab; n_evt = ARRAY_SIZE(f_evt_tab); } }
/* Devilishly complex routine. * * Has to deal with EOF and EPIPE on input, * with line wrapping, with last line not ending in '\n' * (possibly not ending YET!), with backspace and tabs. * It reads input again if last time we got an EOF (thus supporting * growing files) or EPIPE (watching output of slow process like make). * * Variables used: * flines[] - array of lines already read. Linewrap may cause * one source file line to occupy several flines[n]. * flines[max_fline] - last line, possibly incomplete. * terminated - 1 if flines[max_fline] is 'terminated' * (if there was '\n' [which isn't stored itself, we just remember * that it was seen]) * max_lineno - last line's number, this one doesn't increment * on line wrap, only on "real" new lines. * readbuf[0..readeof-1] - small preliminary buffer. * readbuf[readpos] - next character to add to current line. * last_line_pos - screen line position of next char to be read * (takes into account tabs and backspaces) * eof_error - < 0 error, == 0 EOF, > 0 not EOF/error */ static void read_lines(void) { #define readbuf bb_common_bufsiz1 char *current_line, *p; int w = width; char last_terminated = terminated; #if ENABLE_FEATURE_LESS_REGEXP unsigned old_max_fline = max_fline; time_t last_time = 0; unsigned seconds_p1 = 3; /* seconds_to_loop + 1 */ #endif if (option_mask32 & FLAG_N) w -= 8; IF_FEATURE_LESS_REGEXP(again0:) p = current_line = ((char*)xmalloc(w + 4)) + 4; max_fline += last_terminated; if (!last_terminated) { const char *cp = flines[max_fline]; strcpy(p, cp); p += strlen(current_line); free(MEMPTR(flines[max_fline])); /* last_line_pos is still valid from previous read_lines() */ } else { last_line_pos = 0; } while (1) { /* read lines until we reach cur_fline or wanted_match */ *p = '\0'; terminated = 0; while (1) { /* read chars until we have a line */ char c; /* if no unprocessed chars left, eat more */ if (readpos >= readeof) { ndelay_on(0); eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf)); ndelay_off(0); readpos = 0; readeof = eof_error; if (eof_error <= 0) goto reached_eof; } c = readbuf[readpos]; /* backspace? [needed for manpages] */ /* <tab><bs> is (a) insane and */ /* (b) harder to do correctly, so we refuse to do it */ if (c == '\x8' && last_line_pos && p[-1] != '\t') { readpos++; /* eat it */ last_line_pos--; /* was buggy (p could end up <= current_line)... */ *--p = '\0'; continue; } { size_t new_last_line_pos = last_line_pos + 1; if (c == '\t') { new_last_line_pos += 7; new_last_line_pos &= (~7); } if ((int)new_last_line_pos >= w) break; last_line_pos = new_last_line_pos; } /* ok, we will eat this char */ readpos++; if (c == '\n') { terminated = 1; last_line_pos = 0; break; } /* NUL is substituted by '\n'! */ if (c == '\0') c = '\n'; *p++ = c; *p = '\0'; } /* end of "read chars until we have a line" loop */ /* Corner case: linewrap with only "" wrapping to next line */ /* Looks ugly on screen, so we do not store this empty line */ if (!last_terminated && !current_line[0]) { last_terminated = 1; max_lineno++; continue; } reached_eof: last_terminated = terminated; flines = xrealloc_vector(flines, 8, max_fline); flines[max_fline] = (char*)xrealloc(MEMPTR(current_line), strlen(current_line) + 1 + 4) + 4; LINENO(flines[max_fline]) = max_lineno; if (terminated) max_lineno++; if (max_fline >= MAXLINES) { eof_error = 0; /* Pretend we saw EOF */ break; } if (!(option_mask32 & FLAG_S) ? (max_fline > cur_fline + max_displayed_line) : (max_fline >= cur_fline && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line) ) { #if !ENABLE_FEATURE_LESS_REGEXP break; #else if (wanted_match >= num_matches) { /* goto_match called us */ fill_match_lines(old_max_fline); old_max_fline = max_fline; } if (wanted_match < num_matches) break; #endif } if (eof_error <= 0) { if (eof_error < 0) { if (errno == EAGAIN) { /* not yet eof or error, reset flag (or else * we will hog CPU - select() will return * immediately */ eof_error = 1; } else { print_statusline(bb_msg_read_error); } } #if !ENABLE_FEATURE_LESS_REGEXP break; #else if (wanted_match < num_matches) { break; } else { /* goto_match called us */ time_t t = time(NULL); if (t != last_time) { last_time = t; if (--seconds_p1 == 0) break; } sched_yield(); goto again0; /* go loop again (max 2 seconds) */ } #endif } max_fline++; current_line = ((char*)xmalloc(w + 4)) + 4; p = current_line; last_line_pos = 0; } /* end of "read lines until we reach cur_fline" loop */ fill_match_lines(old_max_fline); #if ENABLE_FEATURE_LESS_REGEXP /* prevent us from being stuck in search for a match */ wanted_match = -1; #endif #undef readbuf }
static void re_wrap(void) { int w = width; int new_line_pos; int src_idx; int dst_idx; int new_cur_fline = 0; uint32_t lineno; char linebuf[w + 1]; const char **old_flines = flines; const char *s; char **new_flines = NULL; char *d; if (option_mask32 & FLAG_N) w -= 8; src_idx = 0; dst_idx = 0; s = old_flines[0]; lineno = LINENO(s); d = linebuf; new_line_pos = 0; while (1) { *d = *s; if (*d != '\0') { new_line_pos++; if (*d == '\t') /* tab */ new_line_pos += 7; s++; d++; if (new_line_pos >= w) { int sz; /* new line is full, create next one */ *d = '\0'; next_new: sz = (d - linebuf) + 1; /* + 1: NUL */ d = ((char*)xmalloc(sz + 4)) + 4; LINENO(d) = lineno; memcpy(d, linebuf, sz); new_flines = xrealloc_vector(new_flines, 8, dst_idx); new_flines[dst_idx] = d; dst_idx++; if (new_line_pos < w) { /* if we came here thru "goto next_new" */ if (src_idx > max_fline) break; lineno = LINENO(s); } d = linebuf; new_line_pos = 0; } continue; } /* *d == NUL: old line ended, go to next old one */ free(MEMPTR(old_flines[src_idx])); /* btw, convert cur_fline... */ if (cur_fline == src_idx) new_cur_fline = dst_idx; src_idx++; /* no more lines? finish last new line (and exit the loop) */ if (src_idx > max_fline) goto next_new; s = old_flines[src_idx]; if (lineno != LINENO(s)) { /* this is not a continuation line! * create next _new_ line too */ goto next_new; } } free(old_flines); flines = (const char **)new_flines; max_fline = dst_idx - 1; last_line_pos = new_line_pos; cur_fline = new_cur_fline; /* max_lineno is screen-size independent */ #if ENABLE_FEATURE_LESS_REGEXP pattern_valid = 0; #endif }
int sort_main(int argc UNUSED_PARAM, char **argv) { FILE *fp, *outfile = stdout; char *line, **lines = NULL; char *str_ignored, *str_o, *str_t; llist_t *lst_k = NULL; int i, flag; int linecount = 0; xfunc_error_retval = 2; /* Parse command line options */ /* -o and -t can be given at most once */ opt_complementary = "o--o:t--t:" /* -t, -o: maximum one of each */ "k::"; /* -k takes list */ getopt32(argv, OPT_STR, &str_ignored, &str_ignored, &str_o, &lst_k, &str_t); #if ENABLE_FEATURE_SORT_BIG if (option_mask32 & FLAG_o) outfile = xfopen_for_write(str_o); if (option_mask32 & FLAG_t) { if (!str_t[0] || str_t[1]) bb_error_msg_and_die("bad -t parameter"); key_separator = str_t[0]; } /* parse sort key */ while (lst_k) { enum { FLAG_allowed_for_k = FLAG_n | /* Numeric sort */ FLAG_g | /* Sort using strtod() */ FLAG_M | /* Sort date */ FLAG_b | /* Ignore leading blanks */ FLAG_r | /* Reverse */ FLAG_d | /* Ignore !(isalnum()|isspace()) */ FLAG_f | /* Force uppercase */ FLAG_i | /* Ignore !isprint() */ 0 }; struct sort_key *key = add_key(); char *str_k = llist_pop(&lst_k); const char *temp2; i = 0; /* i==0 before comma, 1 after (-k3,6) */ while (*str_k) { /* Start of range */ /* Cannot use bb_strtou - suffix can be a letter */ key->range[2*i] = str2u(&str_k); if (*str_k == '.') { str_k++; key->range[2*i+1] = str2u(&str_k); } while (*str_k) { if (*str_k == ',' && !i++) { str_k++; break; } /* no else needed: fall through to syntax error because comma isn't in OPT_STR */ temp2 = strchr(OPT_STR, *str_k); if (!temp2) bb_error_msg_and_die("unknown key option"); flag = 1 << (temp2 - OPT_STR); if (flag & ~FLAG_allowed_for_k) bb_error_msg_and_die("unknown sort type"); /* b after ',' means strip _trailing_ space */ if (i && flag == FLAG_b) flag = FLAG_bb; key->flags |= flag; str_k++; } } } #endif /* global b strips leading and trailing spaces */ if (option_mask32 & FLAG_b) option_mask32 |= FLAG_bb; /* Open input files and read data */ argv += optind; if (!*argv) *--argv = (char*)"-"; do { /* coreutils 6.9 compat: abort on first open error, * do not continue to next file: */ fp = xfopen_stdin(*argv); for (;;) { line = GET_LINE(fp); if (!line) break; lines = xrealloc_vector(lines, 6, linecount); lines[linecount++] = line; } fclose_if_not_stdin(fp); } while (*++argv); #if ENABLE_FEATURE_SORT_BIG /* if no key, perform alphabetic sort */ if (!key_list) add_key()->range[0] = 1; /* handle -c */ if (option_mask32 & FLAG_c) { int j = (option_mask32 & FLAG_u) ? -1 : 0; for (i = 1; i < linecount; i++) if (compare_keys(&lines[i-1], &lines[i]) > j) { fprintf(stderr, "Check line %d\n", i); return EXIT_FAILURE; } return EXIT_SUCCESS; } #endif /* Perform the actual sort */ qsort(lines, linecount, sizeof(char *), compare_keys); /* handle -u */ if (option_mask32 & FLAG_u) { flag = 0; /* coreutils 6.3 drop lines for which only key is the same */ /* -- disabling last-resort compare... */ option_mask32 |= FLAG_s; for (i = 1; i < linecount; i++) { if (!compare_keys(&lines[flag], &lines[i])) free(lines[i]); else lines[++flag] = lines[i]; } if (linecount) linecount = flag+1; } /* Print it */ flag = (option_mask32 & FLAG_z) ? '\0' : '\n'; for (i = 0; i < linecount; i++) fprintf(outfile, "%s%c", lines[i], flag); fflush_stdout_and_exit(EXIT_SUCCESS); }
static void add_input_file(FILE *file) { G.input_file_list = xrealloc_vector(G.input_file_list, 2, G.input_file_count); G.input_file_list[G.input_file_count++] = file; }
#if ENABLE_FEATURE_TOPMEM if (scan_mask != TOPMEM_MASK) #endif { n = ntop; top = xrealloc_vector(top, 6, ntop++); top[n].pid = p->pid; top[n].ppid = p->ppid; top[n].vsz = p->vsz; #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE top[n].ticks = p->stime + p->utime; #endif top[n].uid = p->uid; strcpy(top[n].state, p->state); strcpy(top[n].comm, p->comm); #if ENABLE_FEATURE_TOP_SMP_PROCESS top[n].last_seen_on_cpu = p->last_seen_on_cpu; #endif } #if ENABLE_FEATURE_TOPMEM else { /* TOPMEM */ if (!(p->smaps.mapped_ro | p->smaps.mapped_rw)) continue; /* kernel threads are ignored */ n = ntop; /* No bug here - top and topmem are the same */ top = xrealloc_vector(topmem, 6, ntop++); strcpy(topmem[n].comm, p->comm); topmem[n].pid = p->pid; topmem[n].vsz = p->smaps.mapped_rw + p->smaps.mapped_ro; topmem[n].vszrw = p->smaps.mapped_rw; topmem[n].rss_sh = p->smaps.shared_clean + p->smaps.shared_dirty;
int cut_main(int argc UNUSED_PARAM, char **argv) { /* growable array holding a series of lists */ struct cut_list *cut_lists = NULL; unsigned nlists = 0; /* number of elements in above list */ char delim = '\t'; /* delimiter, default is tab */ char *sopt, *ltok; unsigned opt; opt_complementary = "b--bcf:c--bcf:f--bcf"; opt = getopt32(argv, optstring, &sopt, &sopt, &sopt, <ok); // argc -= optind; argv += optind; if (!(opt & (CUT_OPT_BYTE_FLGS | CUT_OPT_CHAR_FLGS | CUT_OPT_FIELDS_FLGS))) bb_error_msg_and_die("expected a list of bytes, characters, or fields"); if (opt & CUT_OPT_DELIM_FLGS) { if (ltok[0] && ltok[1]) { /* more than 1 char? */ bb_error_msg_and_die("the delimiter must be a single character"); } delim = ltok[0]; } /* non-field (char or byte) cutting has some special handling */ if (!(opt & CUT_OPT_FIELDS_FLGS)) { static const char _op_on_field[] ALIGN1 = " only when operating on fields"; if (opt & CUT_OPT_SUPPRESS_FLGS) { bb_error_msg_and_die ("suppressing non-delimited lines makes sense%s", _op_on_field); } if (delim != '\t') { bb_error_msg_and_die ("a delimiter may be specified%s", _op_on_field); } } /* * parse list and put values into startpos and endpos. * valid list formats: N, N-, N-M, -M * more than one list can be separated by commas */ { char *ntok; int s = 0, e = 0; /* take apart the lists, one by one (they are separated with commas) */ while ((ltok = strsep(&sopt, ",")) != NULL) { /* it's actually legal to pass an empty list */ if (!ltok[0]) continue; /* get the start pos */ ntok = strsep(<ok, "-"); if (!ntok[0]) { s = BOL; } else { s = xatoi_positive(ntok); /* account for the fact that arrays are zero based, while * the user expects the first char on the line to be char #1 */ if (s != 0) s--; } /* get the end pos */ if (ltok == NULL) { e = NON_RANGE; } else if (!ltok[0]) { e = EOL; } else { e = xatoi_positive(ltok); /* if the user specified and end position of 0, * that means "til the end of the line" */ if (e == 0) e = EOL; e--; /* again, arrays are zero based, lines are 1 based */ if (e == s) e = NON_RANGE; } /* add the new list */ cut_lists = xrealloc_vector(cut_lists, 4, nlists); /* NB: startpos is always >= 0, * while endpos may be = NON_RANGE (-1) */ cut_lists[nlists].startpos = s; cut_lists[nlists].endpos = e; nlists++; } /* make sure we got some cut positions out of all that */ if (nlists == 0) bb_error_msg_and_die("missing list of positions"); /* now that the lists are parsed, we need to sort them to make life * easier on us when it comes time to print the chars / fields / lines */ qsort(cut_lists, nlists, sizeof(cut_lists[0]), cmpfunc); } { int retval = EXIT_SUCCESS; if (!*argv) *--argv = (char *)"-"; do { FILE *file = fopen_or_warn_stdin(*argv); if (!file) { retval = EXIT_FAILURE; continue; } cut_file(file, delim, cut_lists, nlists); fclose_if_not_stdin(file); } while (*++argv); if (ENABLE_FEATURE_CLEAN_UP) free(cut_lists); fflush_stdout_and_exit(retval); } }
int acpid_main(int argc UNUSED_PARAM, char **argv) { int nfd; int opts; struct pollfd *pfd; const char *opt_dir = "/etc/acpi"; const char *opt_input = "/dev/input/event"; const char *opt_logfile = "/var/log/acpid.log"; const char *opt_action = "/etc/acpid.conf"; const char *opt_map = "/etc/acpi.map"; #if ENABLE_FEATURE_PIDFILE const char *opt_pidfile = "/var/run/acpid.pid"; #endif INIT_G(); opt_complementary = "df:e--e"; opts = getopt32(argv, "c:de:fl:a:M:" IF_FEATURE_PIDFILE("p:") IF_FEATURE_ACPID_COMPAT("g:m:s:S:v"), &opt_dir, &opt_input, &opt_logfile, &opt_action, &opt_map IF_FEATURE_PIDFILE(, &opt_pidfile) IF_FEATURE_ACPID_COMPAT(, NULL, NULL, NULL, NULL) ); if (!(opts & OPT_f)) { /* No -f "Foreground", we go to background */ bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); } if (!(opts & OPT_d)) { /* No -d "Debug", we log to log file. * This includes any output from children. */ xmove_fd(xopen(opt_logfile, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); xdup2(STDOUT_FILENO, STDERR_FILENO); /* Also, acpid's messages (but not children) will go to syslog too */ openlog(applet_name, LOG_PID, LOG_DAEMON); logmode = LOGMODE_SYSLOG | LOGMODE_STDIO; } /* else: -d "Debug", log is not redirected */ parse_conf_file(opt_action); parse_map_file(opt_map); xchdir(opt_dir); bb_signals((1 << SIGCHLD), SIG_IGN); bb_signals(BB_FATAL_SIGS, record_signo); pfd = NULL; nfd = 0; while (1) { int fd; char *dev_event; dev_event = xasprintf((opts & OPT_e) ? "%s" : "%s%u", opt_input, nfd); fd = open(dev_event, O_RDONLY | O_NONBLOCK); if (fd < 0) { if (nfd == 0) bb_simple_perror_msg_and_die(dev_event); break; } free(dev_event); pfd = xrealloc_vector(pfd, 1, nfd); pfd[nfd].fd = fd; pfd[nfd].events = POLLIN; nfd++; } write_pidfile(opt_pidfile); while (safe_poll(pfd, nfd, -1) > 0) { int i; for (i = 0; i < nfd; i++) { const char *event; if (!(pfd[i].revents & POLLIN)) { if (pfd[i].revents == 0) continue; /* this fd has nothing */ /* Likely POLLERR, POLLHUP, POLLNVAL. * Do not listen on this fd anymore. */ close(pfd[i].fd); nfd--; for (; i < nfd; i++) pfd[i].fd = pfd[i + 1].fd; break; /* do poll() again */ } event = NULL; if (option_mask32 & OPT_e) { char *buf; int len; buf = xmalloc_reads(pfd[i].fd, NULL); /* buf = "button/power PWRB 00000080 00000000" */ len = strlen(buf) - 9; if (len >= 0) buf[len] = '\0'; event = find_action(NULL, buf); free(buf); } else { struct input_event ev; if (sizeof(ev) != full_read(pfd[i].fd, &ev, sizeof(ev))) continue; if (ev.value != 1 && ev.value != 0) continue; event = find_action(&ev, NULL); } if (!event) continue; // spawn event handler process_event(event); } } if (ENABLE_FEATURE_CLEAN_UP) { while (nfd--) close(pfd[nfd].fd); free(pfd); } remove_pidfile(opt_pidfile); return EXIT_SUCCESS; }
int man_main(int argc UNUSED_PARAM, char **argv) { parser_t *parser; const char *pager; char **man_path_list; char *sec_list; char *cur_path, *cur_sect; int count_mp, cur_mp; int opt, not_found; char *token[2]; opt_complementary = "-1"; /* at least one argument */ opt = getopt32(argv, "+aw"); argv += optind; sec_list = xstrdup("1:2:3:4:5:6:7:8:9"); /* Last valid man_path_list[] is [0x10] */ count_mp = 0; man_path_list = xzalloc(0x11 * sizeof(man_path_list[0])); man_path_list[0] = getenv("MANPATH"); if (!man_path_list[0]) /* default, may be overridden by /etc/man.conf */ man_path_list[0] = (char*)"/usr/man"; else count_mp++; pager = getenv("MANPAGER"); if (!pager) { pager = getenv("PAGER"); if (!pager) pager = "more"; } /* Parse man.conf */ parser = config_open2("/etc/man.conf", fopen_for_read); while (config_read(parser, token, 2, 0, "# \t", PARSE_NORMAL)) { if (!token[1]) continue; if (strcmp("MANPATH", token[0]) == 0) { /* Do we already have it? */ char **path_element = man_path_list; while (*path_element) { if (strcmp(*path_element, token[1]) == 0) goto skip; path_element++; } man_path_list = xrealloc_vector(man_path_list, 4, count_mp); man_path_list[count_mp] = xstrdup(token[1]); count_mp++; /* man_path_list is NULL terminated */ /*man_path_list[count_mp] = NULL; - xrealloc_vector did it */ } if (strcmp("MANSECT", token[0]) == 0) { free(sec_list); sec_list = xstrdup(token[1]); } skip: ; } config_close(parser); not_found = 0; do { /* for each argv[] */ int found = 0; cur_mp = 0; if (strchr(*argv, '/')) { found = show_manpage(pager, *argv, /*man:*/ 1, 0); goto check_found; } while ((cur_path = man_path_list[cur_mp++]) != NULL) { /* for each MANPATH */ do { /* for each MANPATH item */ char *next_path = strchrnul(cur_path, ':'); int path_len = next_path - cur_path; cur_sect = sec_list; do { /* for each section */ char *next_sect = strchrnul(cur_sect, ':'); int sect_len = next_sect - cur_sect; char *man_filename; int cat0man1 = 0; /* Search for cat, then man page */ while (cat0man1 < 2) { int found_here; man_filename = xasprintf("%.*s/%s%.*s/%s.%.*s" Z_SUFFIX, path_len, cur_path, "cat\0man" + (cat0man1 * 4), sect_len, cur_sect, *argv, sect_len, cur_sect); found_here = show_manpage(pager, man_filename, cat0man1, 0); found |= found_here; cat0man1 += found_here + 1; free(man_filename); } if (found && !(opt & OPT_a)) goto next_arg; cur_sect = next_sect; while (*cur_sect == ':') cur_sect++; } while (*cur_sect); cur_path = next_path; while (*cur_path == ':') cur_path++; } while (*cur_path); } check_found: if (!found) { bb_error_msg("no manual entry for '%s'", *argv); not_found = 1; } next_arg: argv++; } while (*argv); return not_found; }
static ps_out_t* new_out_t(void) { out = xrealloc_vector(out, 2, out_cnt); return &out[out_cnt++]; }
int sort_main(int argc UNUSED_PARAM, char **argv) { char *line, **lines; char *str_ignored, *str_o, *str_t; llist_t *lst_k = NULL; int i; int linecount; unsigned opts; xfunc_error_retval = 2; /* Parse command line options */ /* -o and -t can be given at most once */ opt_complementary = "o--o:t--t"; /* -t, -o: at most one of each */ opts = getopt32(argv, OPT_STR, &str_ignored, &str_ignored, &str_o, &lst_k, &str_t); /* global b strips leading and trailing spaces */ if (opts & FLAG_b) option_mask32 |= FLAG_bb; #if ENABLE_FEATURE_SORT_BIG if (opts & FLAG_t) { if (!str_t[0] || str_t[1]) bb_error_msg_and_die("bad -t parameter"); key_separator = str_t[0]; } /* note: below this point we use option_mask32, not opts, * since that reduces register pressure and makes code smaller */ /* Parse sort key */ while (lst_k) { enum { FLAG_allowed_for_k = FLAG_n | /* Numeric sort */ FLAG_g | /* Sort using strtod() */ FLAG_M | /* Sort date */ FLAG_b | /* Ignore leading blanks */ FLAG_r | /* Reverse */ FLAG_d | /* Ignore !(isalnum()|isspace()) */ FLAG_f | /* Force uppercase */ FLAG_i | /* Ignore !isprint() */ 0 }; struct sort_key *key = add_key(); char *str_k = llist_pop(&lst_k); i = 0; /* i==0 before comma, 1 after (-k3,6) */ while (*str_k) { /* Start of range */ /* Cannot use bb_strtou - suffix can be a letter */ key->range[2*i] = str2u(&str_k); if (*str_k == '.') { str_k++; key->range[2*i+1] = str2u(&str_k); } while (*str_k) { int flag; const char *idx; if (*str_k == ',' && !i++) { str_k++; break; } /* no else needed: fall through to syntax error because comma isn't in OPT_STR */ idx = strchr(OPT_STR, *str_k); if (!idx) bb_error_msg_and_die("unknown key option"); flag = 1 << (idx - OPT_STR); if (flag & ~FLAG_allowed_for_k) bb_error_msg_and_die("unknown sort type"); /* b after ',' means strip _trailing_ space */ if (i && flag == FLAG_b) flag = FLAG_bb; key->flags |= flag; str_k++; } } } #endif /* Open input files and read data */ argv += optind; if (!*argv) *--argv = (char*)"-"; linecount = 0; lines = NULL; do { /* coreutils 6.9 compat: abort on first open error, * do not continue to next file: */ FILE *fp = xfopen_stdin(*argv); for (;;) { line = GET_LINE(fp); if (!line) break; lines = xrealloc_vector(lines, 6, linecount); lines[linecount++] = line; } fclose_if_not_stdin(fp); } while (*++argv); #if ENABLE_FEATURE_SORT_BIG /* If no key, perform alphabetic sort */ if (!key_list) add_key()->range[0] = 1; /* Handle -c */ if (option_mask32 & FLAG_c) { int j = (option_mask32 & FLAG_u) ? -1 : 0; for (i = 1; i < linecount; i++) { if (compare_keys(&lines[i-1], &lines[i]) > j) { fprintf(stderr, "Check line %u\n", i); return EXIT_FAILURE; } } return EXIT_SUCCESS; } #endif /* Perform the actual sort */ qsort(lines, linecount, sizeof(lines[0]), compare_keys); /* Handle -u */ if (option_mask32 & FLAG_u) { int j = 0; /* coreutils 6.3 drop lines for which only key is the same */ /* -- disabling last-resort compare... */ option_mask32 |= FLAG_s; for (i = 1; i < linecount; i++) { if (compare_keys(&lines[j], &lines[i]) == 0) free(lines[i]); else lines[++j] = lines[i]; } if (linecount) linecount = j+1; } /* Print it */ #if ENABLE_FEATURE_SORT_BIG /* Open output file _after_ we read all input ones */ if (option_mask32 & FLAG_o) xmove_fd(xopen(str_o, O_WRONLY|O_CREAT|O_TRUNC), STDOUT_FILENO); #endif { int ch = (option_mask32 & FLAG_z) ? '\0' : '\n'; for (i = 0; i < linecount; i++) printf("%s%c", lines[i], ch); } fflush_stdout_and_exit(EXIT_SUCCESS); }