/* * returns the index in the string just past where the address ends. */ static int get_address(const char *my_str, int *linenum, regex_t ** regex) { const char *pos = my_str; if (isdigit(*my_str)) { *linenum = strtol(my_str, (char**)&pos, 10); /* endstr shouldn't ever equal NULL */ } else if (*my_str == '$') { *linenum = -1; pos++; } else if (*my_str == '/' || *my_str == '\\') { int next; char delimiter; char *temp; delimiter = '/'; if (*my_str == '\\') delimiter = *++pos; next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); if (next != 0) { temp = copy_parsing_escapes(pos, next); G.previous_regex_ptr = *regex = xzalloc(sizeof(regex_t)); xregcomp(*regex, temp, G.regex_type); free(temp); } else { *regex = G.previous_regex_ptr; if (!G.previous_regex_ptr) bb_error_msg_and_die("no previous regexp"); } /* Move position to next character after last delimiter */ pos += (next+1); } return pos - my_str; }
/* * returns the index in the string just past where the address ends. */ static int get_address(const char *my_str, int *linenum, regex_t ** regex) { const char *pos = my_str; if (isdigit(*my_str)) { *linenum = strtol(my_str, (char**)&pos, 10); /* endstr shouldnt ever equal NULL */ } else if (*my_str == '$') { *linenum = -1; pos++; } else if (*my_str == '/' || *my_str == '\\') { int next; char delimiter; char *temp; delimiter = '/'; if (*my_str == '\\') delimiter = *++pos; next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); temp = copy_parsing_escapes(pos, next); *regex = xmalloc(sizeof(regex_t)); xregcomp(*regex, temp, G.regex_type|REG_NEWLINE); free(temp); /* Move position to next character after last delimiter */ pos += (next+1); } return pos - my_str; }
/* * returns the index in the string just past where the address ends. */ static int get_address(char *my_str, int *linenum, regex_t ** regex) { char *pos = my_str; if (isdigit(*my_str)) { *linenum = strtol(my_str, &pos, 10); /* endstr shouldnt ever equal NULL */ } else if (*my_str == '$') { *linenum = -1; pos++; } else if (*my_str == '/' || *my_str == '\\') { int next; char delimiter; char *temp; if (*my_str == '\\') delimiter = *(++pos); else delimiter = '/'; next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); if (next == -1) bb_error_msg_and_die("unterminated match expression"); temp=copy_parsing_slashn(pos,next); *regex = (regex_t *) xmalloc(sizeof(regex_t)); xregcomp(*regex, temp, REG_NEWLINE); free(temp); /* Move position to next character after last delimiter */ pos+=(next+1); } return pos - my_str; }
static VALUE *docolon(VALUE *sv, VALUE *pv) { enum { NMATCH = 2 }; VALUE *v; #if defined(__UC_LIBC__) regexp *re_buffer; int len; #else regex_t re_buffer; regmatch_t re_regs[NMATCH]; #endif tostring(sv); tostring(pv); if (pv->u.s[0] == '^') { bb_error_msg( "warning: '%s': using '^' as the first character\n" "of a basic regular expression is not portable; it is ignored", pv->u.s); } #if defined(__UC_LIBC__) re_buffer = regcomp(pv->u.s); if (re_buffer == NULL) { regerror("NULL buffer"); exit(1); } len = regexec(re_buffer, sv->u.s); v = int_value(len); free(re_buffer); #else memset(&re_buffer, 0, sizeof(re_buffer)); memset(re_regs, 0, sizeof(re_regs)); xregcomp(&re_buffer, pv->u.s, 0); /* expr uses an anchored pattern match, so check that there was a * match and that the match starts at offset 0. */ if (regexec(&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH && re_regs[0].rm_so == 0 ) { /* Were \(...\) used? */ if (re_buffer.re_nsub > 0 && re_regs[1].rm_so >= 0) { sv->u.s[re_regs[1].rm_eo] = '\0'; v = str_value(sv->u.s + re_regs[1].rm_so); } else { v = int_value(re_regs[0].rm_eo); } } else { /* Match failed -- return the right kind of null. */ if (re_buffer.re_nsub > 0) v = str_value(""); else v = int_value(0); } regfree(&re_buffer); #endif return v; }
/* * returns the index in the string just past where the address ends. */ static int get_address(struct sed_cmd *sed_cmd, const char *str, int *linenum, regex_t **regex) { char *my_str = strdup(str); int idx = 0; char olddelimiter; olddelimiter = sed_cmd->delimiter; sed_cmd->delimiter = '/'; if (isdigit(my_str[idx])) { do { idx++; } while (isdigit(my_str[idx])); my_str[idx] = 0; *linenum = atoi(my_str); } else if (my_str[idx] == '$') { *linenum = -1; idx++; } else if (my_str[idx] == '/') { idx = index_of_next_unescaped_regexp_delim(sed_cmd, my_str, ++idx); if (idx == -1) error_msg_and_die("unterminated match expression"); my_str[idx] = '\0'; *regex = (regex_t *)xmalloc(sizeof(regex_t)); xregcomp(*regex, my_str+1, REG_NEWLINE); idx++; /* so it points to the next character after the last '/' */ } else { error_msg("get_address: no address found in string\n" "\t(you probably didn't check the string you passed me)"); idx = -1; } free(my_str); sed_cmd->delimiter = olddelimiter; return idx; }
static int ipkg_conf_parse_file(ipkg_conf_t *conf, const char *filename, pkg_src_list_t *pkg_src_list, nv_pair_list_t *tmp_dest_nv_pair_list, char **lists_dir) { int err; ipkg_option_t * options; FILE *file = fopen(filename, "r"); regex_t valid_line_re, comment_re; #define regmatch_size 12 regmatch_t regmatch[regmatch_size]; if (ipkg_init_options_array(conf, &options)<0) return ENOMEM; if (file == NULL) { fprintf(stderr, "%s: failed to open %s: %s\n", __FUNCTION__, filename, strerror(errno)); free(options); return errno; } ipkg_message(conf, IPKG_NOTICE, "loading conf file %s\n", filename); err = xregcomp(&comment_re, "^[[:space:]]*(#.*|[[:space:]]*)$", REG_EXTENDED); if (err) { free(options); return err; } err = xregcomp(&valid_line_re, "^[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))([[:space:]]+([^[:space:]]+))?[[:space:]]*$", REG_EXTENDED); if (err) { free(options); return err; } while(1) { int line_num = 0; char *line; char *type, *name, *value, *extra; line = file_read_line_alloc(file); line_num++; if (line == NULL) { break; } str_chomp(line); if (regexec(&comment_re, line, 0, 0, 0) == 0) { goto NEXT_LINE; } if (regexec(&valid_line_re, line, regmatch_size, regmatch, 0) == REG_NOMATCH) { str_chomp(line); fprintf(stderr, "%s:%d: Ignoring invalid line: `%s'\n", filename, line_num, line); goto NEXT_LINE; } /* This has to be so ugly to deal with optional quotation marks */ if (regmatch[2].rm_so > 0) { type = strndup(line + regmatch[2].rm_so, regmatch[2].rm_eo - regmatch[2].rm_so); } else { type = strndup(line + regmatch[3].rm_so, regmatch[3].rm_eo - regmatch[3].rm_so); } if (regmatch[5].rm_so > 0) { name = strndup(line + regmatch[5].rm_so, regmatch[5].rm_eo - regmatch[5].rm_so); } else { name = strndup(line + regmatch[6].rm_so, regmatch[6].rm_eo - regmatch[6].rm_so); } if (regmatch[8].rm_so > 0) { value = strndup(line + regmatch[8].rm_so, regmatch[8].rm_eo - regmatch[8].rm_so); } else { value = strndup(line + regmatch[9].rm_so, regmatch[9].rm_eo - regmatch[9].rm_so); } extra = NULL; if (regmatch[11].rm_so > 0) { extra = strndup (line + regmatch[11].rm_so, regmatch[11].rm_eo - regmatch[11].rm_so); } /* We use the tmp_dest_nv_pair_list below instead of conf->pkg_dest_list because we might encounter an offline_root option later and that would invalidate the directories we would have computed in pkg_dest_list_init. (We do a similar thing with tmp_src_nv_pair_list for sake of symmetry.) */ if (strcmp(type, "option") == 0) { ipkg_conf_set_option(options, name, value); } else if (strcmp(type, "src") == 0) { if (!nv_pair_list_find(pkg_src_list, name)) { pkg_src_list_append (pkg_src_list, name, value, extra, 0); } else { ipkg_message(conf, IPKG_ERROR, "ERROR: duplicate src declaration. Skipping:\n\t src %s %s\n", name, value); } } else if (strcmp(type, "src/gz") == 0) { if (!nv_pair_list_find(pkg_src_list, name)) { pkg_src_list_append (pkg_src_list, name, value, extra, 1); } else { ipkg_message(conf, IPKG_ERROR, "ERROR: duplicate src declaration. Skipping:\n\t src %s %s\n", name, value); } } else if (strcmp(type, "dest") == 0) { nv_pair_list_append(tmp_dest_nv_pair_list, name, value); } else if (strcmp(type, "lists_dir") == 0) { *lists_dir = realloc(*lists_dir,strlen(value)+1); if (*lists_dir == NULL) { ipkg_message(conf, IPKG_ERROR, "ERROR: Not enough memory\n"); free(options); return EINVAL; } sprintf (*lists_dir,"%s",value); } else if (strcmp(type, "arch") == 0) { ipkg_message(conf, IPKG_INFO, "supported arch %s priority (%s)\n", name, value); if (!value) { ipkg_message(conf, IPKG_NOTICE, "defaulting architecture %s priority to 10\n", name); value = strdup("10"); } nv_pair_list_append(&conf->arch_list, strdup(name), strdup(value)); } else { fprintf(stderr, "WARNING: Ignoring unknown configuration " "parameter: %s %s %s\n", type, name, value); free(options); return EINVAL; } free(type); free(name); free(value); if (extra) free (extra); NEXT_LINE: free(line); } free(options); regfree(&comment_re); regfree(&valid_line_re); fclose(file); return 0; }
int main (int argc, char *argv[]) { #ifdef HAVE_ICONV char *locale_charset; #endif int status = OK; program_name = base_name (argv[0]); if (STREQ (program_name, APROPOS_NAME)) { am_apropos = 1; argp_program_version = "apropos " PACKAGE_VERSION; } else { struct argp_option *optionp; am_apropos = 0; argp_program_version = "whatis " PACKAGE_VERSION; for (optionp = (struct argp_option *) whatis_argp.options; optionp->name || optionp->key || optionp->arg || optionp->flags || optionp->doc || optionp->group; ++optionp) { if (!optionp->name) continue; if (STREQ (optionp->name, "exact") || STREQ (optionp->name, "and")) optionp->flags |= OPTION_HIDDEN; } } init_debug (); pipeline_install_post_fork (pop_all_cleanups); init_locale (); internal_locale = setlocale (LC_MESSAGES, NULL); /* Use LANGUAGE only when LC_MESSAGES locale category is * neither "C" nor "POSIX". */ if (internal_locale && strcmp (internal_locale, "C") && strcmp (internal_locale, "POSIX")) multiple_locale = getenv ("LANGUAGE"); internal_locale = xstrdup (internal_locale ? internal_locale : "C"); if (argp_parse (am_apropos ? &apropos_argp : &whatis_argp, argc, argv, 0, 0, 0)) exit (FAIL); read_config_file (user_config_file != NULL); /* close this locale and reinitialise if a new locale was issued as an argument or in $MANOPT */ if (locale) { free (internal_locale); internal_locale = setlocale (LC_ALL, locale); if (internal_locale) internal_locale = xstrdup (internal_locale); else internal_locale = xstrdup (locale); debug ("main(): locale = %s, internal_locale = %s\n", locale, internal_locale); if (internal_locale) { setenv ("LANGUAGE", internal_locale, 1); locale_changed (); multiple_locale = NULL; } } /* sort out the internal manpath */ if (manp == NULL) manp = locale_manpath (get_manpath (alt_systems)); else free (get_manpath (NULL)); create_pathlist (manp, manpathlist); display_seen = hashtable_create (&null_hashtable_free); #ifdef HAVE_ICONV locale_charset = xasprintf ("%s//IGNORE", get_locale_charset ()); conv_to_locale = iconv_open (locale_charset, "UTF-8"); free (locale_charset); #endif /* HAVE_ICONV */ if (regex_opt) { int i; preg = XNMALLOC (num_keywords, regex_t); for (i = 0; i < num_keywords; ++i) xregcomp (&preg[i], keywords[i], REG_EXTENDED | REG_NOSUB | REG_ICASE); } if (!search ((const char **) keywords, num_keywords)) status = NOT_FOUND; if (regex_opt) { int i; for (i = 0; i < num_keywords; ++i) regfree (&preg[i]); free (preg); } #ifdef HAVE_ICONV if (conv_to_locale != (iconv_t) -1) iconv_close (conv_to_locale); #endif /* HAVE_ICONV */ hashtable_free (display_seen); free_pathlist (manpathlist); free (manp); free (internal_locale); free (program_name); exit (status); }
static int parse_subst_cmd(struct sed_cmd * const sed_cmd, const char *substr) { int oldidx, cflags = REG_NEWLINE; char *match; int idx = 0; int j; /* * the string that gets passed to this function should look like this: * s/match/replace/gIp * || | ||| * mandatory optional * * (all three of the '/' slashes are mandatory) */ /* verify that the 's' is followed by something. That something * (typically a 'slash') is now our regexp delimiter... */ if (!substr[++idx]) error_msg_and_die("bad format in substitution expression"); else sed_cmd->delimiter=substr[idx]; /* save the match string */ oldidx = idx+1; idx = index_of_next_unescaped_regexp_delim(sed_cmd, substr, ++idx); if (idx == -1) error_msg_and_die("bad format in substitution expression"); match = xstrndup(substr + oldidx, idx - oldidx); /* determine the number of back references in the match string */ /* Note: we compute this here rather than in the do_subst_command() * function to save processor time, at the expense of a little more memory * (4 bits) per sed_cmd */ /* sed_cmd->num_backrefs = 0; */ /* XXX: not needed? --apparently not */ for (j = 0; match[j]; j++) { /* GNU/POSIX sed does not save more than nine backrefs */ if (match[j] == '\\' && match[j+1] == '(' && sed_cmd->num_backrefs <= 9) sed_cmd->num_backrefs++; } /* save the replacement string */ oldidx = idx+1; idx = index_of_next_unescaped_regexp_delim(sed_cmd, substr, ++idx); if (idx == -1) error_msg_and_die("bad format in substitution expression"); sed_cmd->replace = xstrndup(substr + oldidx, idx - oldidx); /* process the flags */ while (substr[++idx]) { switch (substr[idx]) { case 'g': sed_cmd->sub_g = 1; break; case 'I': cflags |= REG_ICASE; break; case 'p': sed_cmd->sub_p = 1; break; default: /* any whitespace or semicolon trailing after a s/// is ok */ if (strchr("; \t\v\n\r", substr[idx])) goto out; /* else */ error_msg_and_die("bad option in substitution expression"); } } out: /* compile the match string into a regex */ sed_cmd->sub_match = (regex_t *)xmalloc(sizeof(regex_t)); xregcomp(sed_cmd->sub_match, match, cflags); free(match); return idx; }
int qgrep_main(int argc, char **argv) { int i; int count = 0; char *p; char do_count, do_regex, do_eclass, do_installed, do_list; char show_filename, skip_comments, invert_list, show_name; char per_file_output; FILE *fp = NULL; DIR *eclass_dir = NULL; DIR *vdb_dir = NULL; DIR *cat_dir = NULL; struct dirent *dentry; char ebuild[_Q_PATH_MAX]; char name[_Q_PATH_MAX]; char *label; int reflags = 0; char invert_match = 0; regex_t preg, skip_preg; char *skip_pattern = NULL; depend_atom** include_atoms = NULL; unsigned long int context_optarg; char num_lines_before = 0; char num_lines_after = 0; qgrep_buf_t *buf_list; int need_separator = 0; char status = 1; QGREP_STR_FUNC strfunc = strstr; do_count = do_regex = do_eclass = do_installed = do_list = 0; show_filename = skip_comments = invert_list = show_name = 0; while ((i = GETOPT_LONG(QGREP, qgrep, "")) != -1) { switch (i) { case 'I': invert_match = 1; break; case 'i': strfunc = strcasestr; reflags |= REG_ICASE; break; case 'c': do_count = 1; break; case 'l': do_list = 1; break; case 'L': do_list = invert_list = 1; break; case 'e': do_regex = 1; break; case 'x': do_regex = 1; reflags |= REG_EXTENDED; break; case 'J': do_installed = 1; break; case 'E': do_eclass = 1; break; case 'H': show_filename = 1; break; case 'N': show_name = 1; break; case 's': skip_comments = 1; break; case 'S': skip_pattern = optarg; break; case 'B': case 'A': errno = 0; context_optarg = strtol(optarg, &p, 10); if (errno != 0) errp("%s: not a valid integer", optarg); else if (p == optarg || *p != '\0') err("%s: not a valid integer", optarg); if (context_optarg > 254) err("%s: silly value!", optarg); if (i == 'B') num_lines_before = context_optarg; else num_lines_after = context_optarg; break; COMMON_GETOPTS_CASES(qgrep) } } if (argc == optind) qgrep_usage(EXIT_FAILURE); if (do_list && do_count) { warn("%s and --count are incompatible options. The former wins.", (invert_list ? "--invert-list" : "--list")); do_count = 0; } if (show_name && show_filename) { warn("--with-name and --with-filename are incompatible options. The former wins."); show_filename = 0; } if (do_list && num_lines_before) { warn("%s and --before are incompatible options. The former wins.", (invert_list ? "--invert-list" : "--list")); num_lines_before = 0; } if (do_list && num_lines_after) { warn("%s and --after are incompatible options. The former wins.", (invert_list ? "--invert-list" : "--list")); num_lines_after = 0; } if (do_count && num_lines_before) { warn("--count and --before are incompatible options. The former wins."); num_lines_before = 0; } if (do_count && num_lines_after) { warn("--count and --after are incompatible options. The former wins."); num_lines_after = 0; } if (do_installed && do_eclass) { warn("--installed and --eclass are incompatible options. The former wins."); do_eclass = 0; } /* do we report results once per file or per line ? */ per_file_output = do_count || (do_list && (!verbose || invert_list)); /* label for prefixing matching lines or listing matching files */ label = (show_name ? name : ((verbose || show_filename || do_list) ? ebuild : NULL)); if (argc > (optind + 1)) { include_atoms = xcalloc(sizeof(depend_atom*), (argc - optind - 1)); for (i = (optind + 1); i < argc; i++) if ((include_atoms[i - optind - 1] = atom_explode(argv[i])) == NULL) warn("%s: invalid atom, will be ignored", argv[i]); } /* pre-compile regexps once for all */ if (do_regex) { if (invert_match || *RED == '\0') reflags |= REG_NOSUB; xregcomp(&preg, argv[optind], reflags); reflags |= REG_NOSUB; if (skip_pattern) xregcomp(&skip_preg, skip_pattern, reflags); } /* allocate a circular buffers list for --before */ buf_list = qgrep_buf_list_alloc(num_lines_before + 1); size_t n; char *overlay; array_for_each(overlays, n, overlay) { /* go look either in ebuilds or eclasses or VDB */ if (!do_eclass && !do_installed) { fp = fopen(initialize_flat(overlay, CACHE_EBUILD, false), "re"); if (fp == NULL) continue; xchdir(overlay); } else if (do_eclass) { xchdir(overlay); if ((eclass_dir = opendir("eclass")) == NULL) { if (errno != ENOENT) warnp("opendir(\"%s/eclass\") failed", overlay); continue; } } else { /* if (do_install) */ char buf[_Q_PATH_MAX]; snprintf(buf, sizeof(buf), "%s/%s", portroot, portvdb); xchdir(buf); if ((vdb_dir = opendir(".")) == NULL) errp("could not opendir(%s/%s) for ROOT/VDB", portroot, portvdb); } /* iteration is either over ebuilds or eclasses */ while (do_eclass ? ((dentry = readdir(eclass_dir)) && snprintf(ebuild, sizeof(ebuild), "eclass/%s", dentry->d_name)) : (do_installed ? (get_next_installed_ebuild(ebuild, vdb_dir, &dentry, &cat_dir) != NULL) : (fgets(ebuild, sizeof(ebuild), fp) != NULL))) { FILE *newfp; /* filter badly named files, prepare eclass or package name, etc. */ if (do_eclass) { if ((p = strrchr(ebuild, '.')) == NULL) continue; if (strcmp(p, ".eclass")) continue; if (show_name || (include_atoms != NULL)) { /* cut ".eclass" */ *p = '\0'; /* and skip "eclass/" */ snprintf(name, sizeof(name), "%s", ebuild + 7); /* restore the filepath */ *p = '.'; } } else { if ((p = strchr(ebuild, '\n')) != NULL) *p = '\0'; if (show_name || (include_atoms != NULL)) { /* cut ".ebuild" */ if (p == NULL) p = ebuild + strlen(ebuild); *(p-7) = '\0'; /* cut "/foo/" from "cat/foo/foo-x.y" */ if ((p = strchr(ebuild, '/')) == NULL) continue; *(p++) = '\0'; /* find head of the ebuild basename */ if ((p = strchr(p, '/')) == NULL) continue; /* find start of the pkg name */ snprintf(name, sizeof(name), "%s/%s", ebuild, (p+1)); /* restore the filepath */ *p = '/'; *(p + strlen(p)) = '.'; ebuild[strlen(ebuild)] = '/'; } } /* filter the files we grep when there are extra args */ if (include_atoms != NULL) if (!qgrep_name_match(name, (argc - optind - 1), include_atoms)) continue; if ((newfp = fopen(ebuild, "r")) != NULL) { int lineno = 0; char remaining_after_context = 0; count = 0; /* if there have been some matches already, then a separator will be needed */ need_separator = (!status) && (num_lines_before || num_lines_after); /* whatever is in the circular buffers list is no more a valid context */ qgrep_buf_list_invalidate(buf_list); /* reading a new line always happen in the next buffer of the list */ while ((buf_list = buf_list->next) && (fgets(buf_list->buf, sizeof(buf_list->buf), newfp)) != NULL) { lineno++; buf_list->valid = 1; /* cleanup EOL */ if ((p = strrchr(buf_list->buf, '\n')) != NULL) *p = 0; if ((p = strrchr(buf_list->buf, '\r')) != NULL) *p = 0; if (skip_comments) { /* reject comments line ("^[ \t]*#") */ p = buf_list->buf; while (*p == ' ' || *p == '\t') p++; if (*p == '#') goto print_after_context; } if (skip_pattern) { /* reject some other lines which match an optional pattern */ if (!do_regex) { if (strfunc(buf_list->buf, skip_pattern) != NULL) goto print_after_context; } else { if (regexec(&skip_preg, buf_list->buf, 0, NULL, 0) == 0) goto print_after_context; } } /* four ways to match a line (with/without inversion and regexp) */ if (!invert_match) { if (do_regex == 0) { if (strfunc(buf_list->buf, argv[optind]) == NULL) goto print_after_context; } else { if (regexec(&preg, buf_list->buf, 0, NULL, 0) != 0) goto print_after_context; } } else { if (do_regex == 0) { if (strfunc(buf_list->buf, argv[optind]) != NULL) goto print_after_context; } else { if (regexec(&preg, buf_list->buf, 0, NULL, 0) == 0) goto print_after_context; } } count++; status = 0; /* got a match, exit status should be 0 */ if (per_file_output) continue; /* matching files are listed out of this loop */ if ((need_separator > 0) && (num_lines_before || num_lines_after)) printf("--\n"); /* "need_separator" is not a flag, but a counter, so that * adjacent contextes are not separated */ need_separator = 0 - num_lines_before; if (!do_list) { /* print the leading context */ qgrep_print_before_context(buf_list, num_lines_before, label, ((verbose > 1) ? lineno : -1)); /* print matching line */ if (invert_match || *RED == '\0') qgrep_print_matching_line_nocolor(buf_list, label, ((verbose > 1) ? lineno : -1)); else if (do_regex) qgrep_print_matching_line_regcolor(buf_list, label, ((verbose > 1) ? lineno : -1), &preg); else qgrep_print_matching_line_strcolor(buf_list, label, ((verbose > 1) ? lineno : -1), strfunc, argv[optind]); } else { /* in verbose do_list mode, list the file once per match */ printf("%s", label); if (verbose > 1) printf(":%d", lineno); putchar('\n'); } /* init count down of trailing context lines */ remaining_after_context = num_lines_after; continue; print_after_context: /* print some trailing context lines when needed */ if (!remaining_after_context) { if (!status) /* we're getting closer to the need of a separator between * current match block and the next one */ ++need_separator; } else { qgrep_print_context_line(buf_list, label, ((verbose > 1) ? lineno : -1)); --remaining_after_context; } } fclose(newfp); if (!per_file_output) continue; /* matches were already displayed, line per line */ if (do_count && count) { if (label != NULL) /* -c without -v/-N/-H only outputs * the matches count of the file */ printf("%s:", label); printf("%d\n", count); } else if ((count && !invert_list) || (!count && invert_list)) printf("%s\n", label); /* do_list == 1, or we wouldn't be here */ } } if (do_eclass) closedir(eclass_dir); else if (!do_installed) fclose(fp); if (do_installed) break; } if (do_regex) regfree(&preg); if (do_regex && skip_pattern) regfree(&skip_preg); if (include_atoms != NULL) { for (i = 0; i < (argc - optind - 1); i++) if (include_atoms[i] != NULL) atom_implode(include_atoms[i]); free(include_atoms); } qgrep_buf_list_free(buf_list); return status; }
static void grep_file(FILE *file) { char *line = NULL; int ret; int linenum = 0; int nmatches = 0; int i; #ifdef BB_FEATURE_GREP_CONTEXT int print_n_lines_after = 0; int curpos = 0; /* track where we are in the circular 'before' buffer */ int idx = 0; /* used for iteration through the circular buffer */ #endif /* BB_FEATURE_GREP_CONTEXT */ while ((line = get_line_from_file(file)) != NULL) { chomp(line); linenum++; for (i = 0; i < nregexes; i++) { /* * test for a postitive-assertion match (regexec returns success (0) * and the user did not specify invert search), or a * negative-assertion match (regexec returns failure (REG_NOMATCH) * and the user specified * invert search) */ #if defined(__UC_LIBC__) ret = regexec(regexes[i], line); if ((ret != 0 && !invert_search) || (ret == 0 && invert_search)) { #else ret = regexec(®exes[i], line, 0, NULL, 0); if ((ret == 0 && !invert_search) || (ret == REG_NOMATCH && invert_search)) { #endif /* if we found a match but were told to be quiet, stop here and * return success */ if (be_quiet) exit(0); /* keep track of matches */ nmatches++; /* if we're just printing filenames, we stop after the first match */ if (print_files_with_matches) break; /* print the matched line */ if (print_match_counts == 0) { #ifdef BB_FEATURE_GREP_CONTEXT int prevpos = (curpos == 0) ? lines_before - 1 : curpos - 1; /* if we were told to print 'before' lines and there is at least * one line in the circular buffer, print them */ if (lines_before && before_buf[prevpos] != NULL) { int first_buf_entry_line_num = linenum - lines_before; /* advance to the first entry in the circular buffer, and * figure out the line number is of the first line in the * buffer */ idx = curpos; while (before_buf[idx] == NULL) { idx = (idx + 1) % lines_before; first_buf_entry_line_num++; } /* now print each line in the buffer, clearing them as we go */ while (before_buf[idx] != NULL) { print_line(before_buf[idx], first_buf_entry_line_num, '-'); free(before_buf[idx]); before_buf[idx] = NULL; idx = (idx + 1) % lines_before; first_buf_entry_line_num++; } } /* make a note that we need to print 'after' lines */ print_n_lines_after = lines_after; #endif /* BB_FEATURE_GREP_CONTEXT */ print_line(line, linenum, ':'); } } #ifdef BB_FEATURE_GREP_CONTEXT else { /* no match */ /* Add the line to the circular 'before' buffer */ if(lines_before) { if(before_buf[curpos]) free(before_buf[curpos]); before_buf[curpos] = xstrdup(line); curpos = (curpos + 1) % lines_before; } } /* if we need to print some context lines after the last match, do so */ if (print_n_lines_after && (last_line_printed != linenum)) { print_line(line, linenum, '-'); print_n_lines_after--; } #endif /* BB_FEATURE_GREP_CONTEXT */ } /* for */ free(line); } /* special-case file post-processing for options where we don't print line * matches, just filenames and possibly match counts */ /* grep -c: print [filename:]count, even if count is zero */ if (print_match_counts) { if (print_filename) printf("%s:", cur_file); if (print_files_with_matches && nmatches > 0) printf("1\n"); else printf("%d\n", nmatches); } /* grep -l: print just the filename, but only if we grepped the line in the file */ if (print_files_with_matches && nmatches > 0) { puts(cur_file); } /* remember if we matched */ if (nmatches != 0) matched = 1; } static void add_regex(const char *restr) { int reflags; #if defined(__UC_LIBC__) reflags = 0; if (ignore_case) reflags = 1; #else reflags = REG_NOSUB; if (ignore_case) reflags |= REG_ICASE; #endif #if defined(__UC_LIBC__) regexes = xrealloc(regexes, sizeof(regexp *) * (++nregexes)); #else regexes = xrealloc(regexes, sizeof(regex_t) * (++nregexes)); #endif xregcomp(®exes[nregexes-1], restr, reflags); }
static void add_regex(const char *restr) { regexes = xrealloc(regexes, sizeof(regex_t) * (++nregexes)); xregcomp(®exes[nregexes-1], restr, reflags); }
// mknod in /dev based on a path like "/sys/block/hda/hda1" static void make_device(char *path) { char *device_name = NULL, *s, *temp; int major, minor, type, len, fd; int mode = 0660; uid_t uid = 0; gid_t gid = 0; if (path) { // Try to read major/minor string temp = strrchr(path, '/'); fd = open(path, O_RDONLY); *temp=0; temp = toybuf; len = read(fd, temp, 64); close(fd); if (len<1) return; temp[len] = 0; // Determine device type, major and minor type = path[5]=='c' ? S_IFCHR : S_IFBLK; major = minor = 0; sscanf(temp, "%u:%u", &major, &minor); } else { // if (!path), do hotplug if (!(temp = getenv("SUBSYSTEM"))) return; type = strcmp(temp, "block") ? S_IFCHR : S_IFBLK; major = minor = 0; if (!(temp = getenv("MAJOR"))) return; sscanf(temp, "%u", &major); if (!(temp = getenv("MINOR"))) return; sscanf(temp, "%u", &minor); path = getenv("DEVPATH"); device_name = getenv("DEVNAME"); if (!path) return; temp = toybuf; } if (!device_name) device_name = strrchr(path, '/') + 1; // If we have a config file, look up permissions for this device if (CFG_MDEV_CONF) { char *conf, *pos, *end; // mmap the config file if (-1!=(fd = open("/etc/mdev.conf", O_RDONLY))) { len = fdlength(fd); conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); if (conf) { int line = 0; // Loop through lines in mmaped file for (pos = conf; pos-conf<len;) { int field; char *end2; line++; // find end of this line for(end = pos; end-conf<len && *end!='\n'; end++); // Three fields: regex, uid:gid, mode for (field = 3; field; field--) { // Skip whitespace while (pos<end && isspace(*pos)) pos++; if (pos==end || *pos=='#') break; for (end2 = pos; end2<end && !isspace(*end2) && *end2!='#'; end2++); switch(field) { // Regex to match this device case 3: { char *regex = strndup(pos, end2-pos); regex_t match; regmatch_t off; int result; // Is this it? xregcomp(&match, regex, REG_EXTENDED); result=regexec(&match, device_name, 1, &off, 0); regfree(&match); free(regex); // If not this device, skip rest of line if (result || off.rm_so || off.rm_eo!=strlen(device_name)) goto end_line; break; } // uid:gid case 2: { char *s2; // Find : for(s = pos; s<end2 && *s!=':'; s++); if (s==end2) goto end_line; // Parse UID uid = strtoul(pos,&s2,10); if (s!=s2) { struct passwd *pass; char *str = strndup(pos, s-pos); pass = getpwnam(str); free(str); if (!pass) goto end_line; uid = pass->pw_uid; } s++; // parse GID gid = strtoul(s,&s2,10); if (end2!=s2) { struct group *grp; char *str = strndup(s, end2-s); grp = getgrnam(str); free(str); if (!grp) goto end_line; gid = grp->gr_gid; } break; } // mode case 1: { mode = strtoul(pos, &pos, 8); if (pos!=end2) goto end_line; goto found_device; } } pos=end2; } end_line: // Did everything parse happily? if (field && field!=3) error_exit("Bad line %d", line); // Next line pos = ++end; } found_device: munmap(conf, len); } close(fd); } } sprintf(temp, "/dev/%s", device_name); if (getenv("ACTION") && !strcmp(getenv("ACTION"), "remove")) { unlink(temp); return; } if (strchr(device_name, '/')) mkpathat(AT_FDCWD, temp, 0, 2); if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST) perror_exit("mknod %s failed", temp); if (type == S_IFBLK) close(open(temp, O_RDONLY)); // scan for partitions if (CFG_MDEV_CONF) mode=chown(temp, uid, gid); }
static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr) { int cflags = G.regex_type; char *match; int idx; /* * A substitution command should look something like this: * s/match/replace/ #giIpw * || | ||| * mandatory optional */ idx = parse_regex_delim(substr, &match, &sed_cmd->string); /* determine the number of back references in the match string */ /* Note: we compute this here rather than in the do_subst_command() * function to save processor time, at the expense of a little more memory * (4 bits) per sed_cmd */ /* process the flags */ sed_cmd->which_match = 1; dbg("s flags:'%s'", substr + idx + 1); while (substr[++idx]) { dbg("s flag:'%c'", substr[idx]); /* Parse match number */ if (isdigit(substr[idx])) { if (match[0] != '^') { /* Match 0 treated as all, multiple matches we take the last one. */ const char *pos = substr + idx; /* FIXME: error check? */ sed_cmd->which_match = (unsigned)strtol(substr+idx, (char**) &pos, 10); idx = pos - substr - 1; } continue; } /* Skip spaces */ if (isspace(substr[idx])) continue; switch (substr[idx]) { /* Replace all occurrences */ case 'g': if (match[0] != '^') sed_cmd->which_match = 0; break; /* Print pattern space */ case 'p': sed_cmd->sub_p = 1; break; /* Write to file */ case 'w': { char *fname; idx += parse_file_cmd(/*sed_cmd,*/ substr+idx+1, &fname); sed_cmd->sw_file = xfopen_for_write(fname); sed_cmd->sw_last_char = '\n'; free(fname); break; } /* Ignore case (gnu extension) */ case 'i': case 'I': cflags |= REG_ICASE; break; /* Comment */ case '#': // while (substr[++idx]) continue; idx += strlen(substr + idx); // same /* Fall through */ /* End of command */ case ';': case '}': goto out; default: dbg("s bad flags:'%s'", substr + idx); bb_error_msg_and_die("bad option in substitution expression"); } } out: /* compile the match string into a regex */ if (*match != '\0') { /* If match is empty, we use last regex used at runtime */ sed_cmd->sub_match = xzalloc(sizeof(regex_t)); dbg("xregcomp('%s',%x)", match, cflags); xregcomp(sed_cmd->sub_match, match, cflags); dbg("regcomp ok"); } free(match); return idx; }
static int grep_file(FILE *file) { char *line; invert_search_t ret; int linenum = 0; int nmatches = 0; #ifdef CONFIG_FEATURE_GREP_CONTEXT int print_n_lines_after = 0; int curpos = 0; /* track where we are in the circular 'before' buffer */ int idx = 0; /* used for iteration through the circular buffer */ #endif /* CONFIG_FEATURE_GREP_CONTEXT */ while ((line = bb_get_chomped_line_from_file(file)) != NULL) { llist_t *pattern_ptr = pattern_head; linenum++; ret = 0; while (pattern_ptr) { if (fgrep_flag) { ret = strstr(line, pattern_ptr->data) != NULL; } else { /* * test for a postitive-assertion match (regexec returns success (0) * and the user did not specify invert search), or a negative-assertion * match (regexec returns failure (REG_NOMATCH) and the user specified * invert search) */ regex_t regex; xregcomp(®ex, pattern_ptr->data, reflags); ret |= regexec(®ex, line, 0, NULL, 0) == 0; regfree(®ex); } pattern_ptr = pattern_ptr->link; } /* while (pattern_ptr) */ if ((ret ^ invert_search)) { if (print_files_with_matches || be_quiet) free(line); /* if we found a match but were told to be quiet, stop here */ if (be_quiet || print_files_without_matches) return -1; /* keep track of matches */ nmatches++; /* if we're just printing filenames, we stop after the first match */ if (print_files_with_matches) break; /* print the matched line */ if (print_match_counts == 0) { #ifdef CONFIG_FEATURE_GREP_CONTEXT int prevpos = (curpos == 0) ? lines_before - 1 : curpos - 1; /* if we were told to print 'before' lines and there is at least * one line in the circular buffer, print them */ if (lines_before && before_buf[prevpos] != NULL) { int first_buf_entry_line_num = linenum - lines_before; /* advance to the first entry in the circular buffer, and * figure out the line number is of the first line in the * buffer */ idx = curpos; while (before_buf[idx] == NULL) { idx = (idx + 1) % lines_before; first_buf_entry_line_num++; } /* now print each line in the buffer, clearing them as we go */ while (before_buf[idx] != NULL) { print_line(before_buf[idx], first_buf_entry_line_num, '-'); free(before_buf[idx]); before_buf[idx] = NULL; idx = (idx + 1) % lines_before; first_buf_entry_line_num++; } } /* make a note that we need to print 'after' lines */ print_n_lines_after = lines_after; #endif /* CONFIG_FEATURE_GREP_CONTEXT */ print_line(line, linenum, ':'); } } #ifdef CONFIG_FEATURE_GREP_CONTEXT else { /* no match */ /* Add the line to the circular 'before' buffer */ if(lines_before) { free(before_buf[curpos]); before_buf[curpos] = bb_xstrdup(line); curpos = (curpos + 1) % lines_before; } } /* if we need to print some context lines after the last match, do so */ if (print_n_lines_after && (last_line_printed != linenum)) { print_line(line, linenum, '-'); print_n_lines_after--; } #endif /* CONFIG_FEATURE_GREP_CONTEXT */ free(line); } /* special-case file post-processing for options where we don't print line * matches, just filenames and possibly match counts */ /* grep -c: print [filename:]count, even if count is zero */ if (print_match_counts) { if (print_filename > 0) printf("%s:", cur_file); printf("%d\n", nmatches); } /* grep -l: print just the filename, but only if we grepped the line in the file */ if (print_files_with_matches && nmatches > 0) { puts(cur_file); } /* grep -L: print just the filename, but only if we didn't grep the line in the file */ if (print_files_without_matches && nmatches == 0) { puts(cur_file); } return nmatches; }
static void regex_process(void) { char uncomp_regex[100]; char *current_line; int i; int j = 0; regex_t pattern; /* Get the uncompiled regular expression from the user */ clear_line(); putchar((match_backwards) ? '?' : '/'); uncomp_regex[0] = 0; fgets(uncomp_regex, sizeof(uncomp_regex), inp); if (strlen(uncomp_regex) == 1) { if (num_matches) goto_match(match_backwards ? match_pos - 1 : match_pos + 1); else buffer_print(); return; } uncomp_regex[strlen(uncomp_regex) - 1] = '\0'; /* Compile the regex and check for errors */ xregcomp(&pattern, uncomp_regex, 0); if (num_matches) { /* Get rid of all the highlights we added previously */ for (i = 0; i <= num_flines; i++) { current_line = process_regex_on_line(flines[i], &old_pattern, 0); flines[i] = bb_xstrdup(current_line); } } old_pattern = pattern; /* Reset variables */ match_lines = xrealloc(match_lines, sizeof(int)); match_lines[0] = -1; match_pos = 0; num_matches = 0; match_found = 0; /* Run the regex on each line of the current file here */ for (i = 0; i <= num_flines; i++) { current_line = process_regex_on_line(flines[i], &pattern, 1); flines[i] = bb_xstrdup(current_line); if (match_found) { match_lines = xrealloc(match_lines, (j + 1) * sizeof(int)); match_lines[j] = i; j++; } } num_matches = j; if ((match_lines[0] != -1) && (num_flines > height - 2)) { if (match_backwards) { for (i = 0; i < num_matches; i++) { if (match_lines[i] > line_pos) { match_pos = i - 1; buffer_line(match_lines[match_pos]); break; } } } else buffer_line(match_lines[0]); } else buffer_init(); }
static int grep_file(FILE *file) { char *line; byte_t ret; int linenum = 0; int nmatches = 0; regmatch_t regmatch; #if ENABLE_FEATURE_GREP_CONTEXT int print_n_lines_after = 0; int curpos = 0; /* track where we are in the circular 'before' buffer */ int idx = 0; /* used for iteration through the circular buffer */ #endif /* ENABLE_FEATURE_GREP_CONTEXT */ while ((line = xmalloc_getline(file)) != NULL) { llist_t *pattern_ptr = pattern_head; grep_list_data_t * gl; linenum++; ret = 0; while (pattern_ptr) { gl = (grep_list_data_t *)pattern_ptr->data; if (FGREP_FLAG) { ret = strstr(line, gl->pattern) != NULL; } else { /* * test for a postitive-assertion match (regexec returns success (0) * and the user did not specify invert search), or a negative-assertion * match (regexec returns failure (REG_NOMATCH) and the user specified * invert search) */ if (!(gl->flg_mem_alocated_compiled & COMPILED)) { gl->flg_mem_alocated_compiled |= COMPILED; xregcomp(&(gl->preg), gl->pattern, reflags); } regmatch.rm_so = 0; regmatch.rm_eo = 0; ret |= regexec(&(gl->preg), line, 1, ®match, 0) == 0; } pattern_ptr = pattern_ptr->link; } /* while (pattern_ptr) */ if (ret ^ invert_search) { if (PRINT_FILES_WITH_MATCHES || BE_QUIET) free(line); /* if we found a match but were told to be quiet, stop here */ if (BE_QUIET || PRINT_FILES_WITHOUT_MATCHES) return -1; /* keep track of matches */ nmatches++; /* if we're just printing filenames, we stop after the first match */ if (PRINT_FILES_WITH_MATCHES) break; /* print the matched line */ if (PRINT_MATCH_COUNTS == 0) { #if ENABLE_FEATURE_GREP_CONTEXT int prevpos = (curpos == 0) ? lines_before - 1 : curpos - 1; /* if we were told to print 'before' lines and there is at least * one line in the circular buffer, print them */ if (lines_before && before_buf[prevpos] != NULL) { int first_buf_entry_line_num = linenum - lines_before; /* advance to the first entry in the circular buffer, and * figure out the line number is of the first line in the * buffer */ idx = curpos; while (before_buf[idx] == NULL) { idx = (idx + 1) % lines_before; first_buf_entry_line_num++; } /* now print each line in the buffer, clearing them as we go */ while (before_buf[idx] != NULL) { print_line(before_buf[idx], first_buf_entry_line_num, '-'); free(before_buf[idx]); before_buf[idx] = NULL; idx = (idx + 1) % lines_before; first_buf_entry_line_num++; } } /* make a note that we need to print 'after' lines */ print_n_lines_after = lines_after; #endif if (option_mask32 & GREP_OPT_o) { line[regmatch.rm_eo] = '\0'; print_line(line + regmatch.rm_so, linenum, ':'); } else { print_line(line, linenum, ':'); } } } #if ENABLE_FEATURE_GREP_CONTEXT else { /* no match */ /* Add the line to the circular 'before' buffer */ if (lines_before) { free(before_buf[curpos]); before_buf[curpos] = xstrdup(line); curpos = (curpos + 1) % lines_before; } } /* if we need to print some context lines after the last match, do so */ if (print_n_lines_after && (last_line_printed != linenum)) { print_line(line, linenum, '-'); print_n_lines_after--; } #endif /* ENABLE_FEATURE_GREP_CONTEXT */ free(line); } /* special-case file post-processing for options where we don't print line * matches, just filenames and possibly match counts */ /* grep -c: print [filename:]count, even if count is zero */ if (PRINT_MATCH_COUNTS) { if (print_filename) printf("%s:", cur_file); printf("%d\n", nmatches); } /* grep -l: print just the filename, but only if we grepped the line in the file */ if (PRINT_FILES_WITH_MATCHES && nmatches > 0) { puts(cur_file); } /* grep -L: print just the filename, but only if we didn't grep the line in the file */ if (PRINT_FILES_WITHOUT_MATCHES && nmatches == 0) { puts(cur_file); } return nmatches; }
static int parse_subst_cmd(sed_cmd_t * const sed_cmd, char *substr) { int cflags = 0; char *match; int idx = 0; /* * A substitution command should look something like this: * s/match/replace/ #gIpw * || | ||| * mandatory optional */ idx = parse_regex_delim(substr, &match, &sed_cmd->string); /* determine the number of back references in the match string */ /* Note: we compute this here rather than in the do_subst_command() * function to save processor time, at the expense of a little more memory * (4 bits) per sed_cmd */ /* process the flags */ sed_cmd->which_match=1; while (substr[++idx]) { /* Parse match number */ if(isdigit(substr[idx])) { if(match[0]!='^') { /* Match 0 treated as all, multiple matches we take the last one. */ char *pos=substr+idx; sed_cmd->which_match=(unsigned short)strtol(substr+idx,&pos,10); idx=pos-substr; } continue; } /* Skip spaces */ if(isspace(substr[idx])) continue; switch (substr[idx]) { /* Replace all occurrences */ case 'g': if (match[0] != '^') sed_cmd->which_match = 0; break; /* Print pattern space */ case 'p': sed_cmd->sub_p = 1; break; case 'w': { char *temp; idx+=parse_file_cmd(sed_cmd,substr+idx,&temp); break; } /* Ignore case (gnu exension) */ case 'I': cflags |= REG_ICASE; break; case ';': case '}': goto out; default: bb_error_msg_and_die("bad option in substitution expression"); } } out: /* compile the match string into a regex */ if (*match != '\0') { /* If match is empty, we use last regex used at runtime */ sed_cmd->sub_match = (regex_t *) xmalloc(sizeof(regex_t)); xregcomp(sed_cmd->sub_match, match, cflags); } free(match); return idx; }
int notmuch_restore_command (unused (void *ctx), int argc, char *argv[]) { notmuch_config_t *config; notmuch_database_t *notmuch; notmuch_bool_t synchronize_flags; notmuch_bool_t accumulate = FALSE; char *input_file_name = NULL; FILE *input = stdin; char *line = NULL; size_t line_size; ssize_t line_len; regex_t regex; int rerr; int opt_index; config = notmuch_config_open (ctx, NULL, NULL); if (config == NULL) return 1; if (notmuch_database_open (notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) return 1; synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config); notmuch_opt_desc_t options[] = { { NOTMUCH_OPT_POSITION, &input_file_name, 0, 0, 0 }, { NOTMUCH_OPT_BOOLEAN, &accumulate, "accumulate", 'a', 0 }, { 0, 0, 0, 0, 0 } }; opt_index = parse_arguments (argc, argv, options, 1); if (opt_index < 0) { /* diagnostics already printed */ return 1; } if (input_file_name) { input = fopen (input_file_name, "r"); if (input == NULL) { fprintf (stderr, "Error opening %s for reading: %s\n", input_file_name, strerror (errno)); return 1; } optind++; } if (opt_index < argc) { fprintf (stderr, "Cannot read dump from more than one file: %s\n", argv[optind]); return 1; } /* Dump output is one line per message. We match a sequence of * non-space characters for the message-id, then one or more * spaces, then a list of space-separated tags as a sequence of * characters within literal '(' and ')'. */ if ( xregcomp (®ex, "^([^ ]+) \\(([^)]*)\\)$", REG_EXTENDED) ) INTERNAL_ERROR("compile time constant regex failed."); while ((line_len = getline (&line, &line_size, input)) != -1) { regmatch_t match[3]; char *message_id, *file_tags; chomp_newline (line); rerr = xregexec (®ex, line, 3, match, 0); if (rerr == REG_NOMATCH) { fprintf (stderr, "Warning: Ignoring invalid input line: %s\n", line); continue; } message_id = xstrndup (line + match[1].rm_so, match[1].rm_eo - match[1].rm_so); file_tags = xstrndup (line + match[2].rm_so, match[2].rm_eo - match[2].rm_so); tag_message (notmuch, message_id, file_tags, !accumulate, synchronize_flags); free (message_id); free (file_tags); } regfree (®ex); if (line) free (line); notmuch_database_destroy (notmuch); if (input != stdin) fclose (input); return 0; }
int pgrep_main(int argc UNUSED_PARAM, char **argv) { unsigned pid; int signo; unsigned opt; int scan_mask; int matched_pid; int sid2match, ppid2match; char *cmd_last; procps_status_t *proc; /* These are initialized to 0 */ struct { regex_t re_buffer; regmatch_t re_match[1]; } Z; #define re_buffer (Z.re_buffer) #define re_match (Z.re_match ) memset(&Z, 0, sizeof(Z)); /* Parse -SIGNAL for pkill. Must be first option, if present */ signo = SIGTERM; if (pkill && argv[1] && argv[1][0] == '-') { int temp = get_signum(argv[1]+1); if (temp != -1) { signo = temp; argv++; } } /* Parse remaining options */ ppid2match = -1; sid2match = -1; opt = getopt32(argv, "vlfxons:+P:+", &sid2match, &ppid2match); argv += optind; if (pkill && OPT_LIST) { /* -l: print the whole signal list */ print_signames(); return 0; } pid = getpid(); if (sid2match == 0) sid2match = getsid(pid); scan_mask = PSSCAN_COMM | PSSCAN_ARGV0; if (OPT_FULL) scan_mask |= PSSCAN_ARGVN; /* One pattern is required, if no -s and no -P */ if ((sid2match & ppid2match) < 0 && (!argv[0] || argv[1])) bb_show_usage(); if (argv[0]) xregcomp(&re_buffer, argv[0], OPT_ANCHOR ? REG_EXTENDED : (REG_EXTENDED|REG_NOSUB)); matched_pid = 0; cmd_last = NULL; proc = NULL; while ((proc = procps_scan(proc, scan_mask)) != NULL) { char *cmd; if (proc->pid == pid) continue; cmd = proc->argv0; if (!cmd) { cmd = proc->comm; } else { int i = proc->argv_len; while (--i >= 0) { if ((unsigned char)cmd[i] < ' ') cmd[i] = ' '; } } if (ppid2match >= 0 && ppid2match != proc->ppid) continue; if (sid2match >= 0 && sid2match != proc->sid) continue; /* NB: OPT_INVERT is always 0 or 1 */ if (!argv[0] || (regexec(&re_buffer, cmd, 1, re_match, 0) == 0 /* match found */ && (!OPT_ANCHOR || (re_match[0].rm_so == 0 && re_match[0].rm_eo == (regoff_t)strlen(cmd))) ) ^ OPT_INVERT ) { matched_pid = proc->pid; if (OPT_LAST) { free(cmd_last); cmd_last = xstrdup(cmd); continue; } act(proc->pid, cmd, signo); if (OPT_FIRST) break; } } if (cmd_last) { act(matched_pid, cmd_last, signo); if (ENABLE_FEATURE_CLEAN_UP) free(cmd_last); } return matched_pid == 0; /* return 1 if no processes listed/signaled */ }
/* mknod in /dev based on a path like "/sys/block/hda/hda1" */ static void make_device(char *path) { char *device_name,*s; int major,minor,type,len,fd; int mode=0660; uid_t uid=0; gid_t gid=0; RESERVE_CONFIG_BUFFER(temp,PATH_MAX); /* Try to read major/minor string */ snprintf(temp, PATH_MAX, "%s/dev", path); fd = open(temp, O_RDONLY); len = read(fd, temp, PATH_MAX-1); if (len<1) goto end; temp[len] = 0; close(fd); /* Determine device name, type, major and minor */ device_name = strrchr(path, '/') + 1; type = strncmp(path+5, "block/" ,6) ? S_IFCHR : S_IFBLK; major = minor = 0; for (s = temp; *s; s++) { if (*s == ':') { major = minor; minor = 0; } else { minor *= 10; minor += (*s) - '0'; } } /* If we have a config file, look up permissions for this device */ if (ENABLE_FEATURE_MDEV_CONF) { char *conf,*pos,*end; /* mmap the config file */ if (-1!=(fd=open("/etc/mdev.conf",O_RDONLY))) { len=lseek(fd,0,SEEK_END); conf=mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0); if (conf) { int line=0; /* Loop through lines in mmaped file*/ for (pos=conf;pos-conf<len;) { int field; char *end2; line++; /* find end of this line */ for(end=pos;end-conf<len && *end!='\n';end++); /* Three fields: regex, uid:gid, mode */ for (field=3;field;field--) { /* Skip whitespace */ while (pos<end && isspace(*pos)) pos++; if (pos==end || *pos=='#') break; for (end2=pos; end2<end && !isspace(*end2) && *end2!='#'; end2++); switch(field) { /* Regex to match this device */ case 3: { char *regex=strndupa(pos,end2-pos); regex_t match; regmatch_t off; int result; /* Is this it? */ xregcomp(&match,regex,REG_EXTENDED); result=regexec(&match,device_name,1,&off,0); regfree(&match); /* If not this device, skip rest of line */ if(result || off.rm_so || off.rm_eo!=strlen(device_name)) goto end_line; break; } /* uid:gid */ case 2: { char *s2; /* Find : */ for(s=pos;s<end2 && *s!=':';s++); if(s==end2) goto end_line; /* Parse UID */ uid=strtoul(pos,&s2,10); if(s!=s2) { struct passwd *pass; pass=getpwnam(strndupa(pos,s-pos)); if(!pass) goto end_line; uid=pass->pw_uid; } s++; /* parse GID */ gid=strtoul(s,&s2,10); if(end2!=s2) { struct group *grp; grp=getgrnam(strndupa(s,end2-s)); if(!grp) goto end_line; gid=grp->gr_gid; } break; } /* mode */ case 1: { mode=strtoul(pos,&pos,8); if(pos!=end2) goto end_line; goto found_device; } } pos=end2; } end_line: /* Did everything parse happily? */ if (field && field!=3) bb_error_msg_and_die("Bad line %d",line); /* Next line */ pos=++end; } found_device: munmap(conf,len); } close(fd); } } sprintf(temp, "%s/%s", DEV_PATH, device_name); umask(0); if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST) bb_perror_msg_and_die("mknod %s failed", temp); if (ENABLE_FEATURE_MDEV_CONF) chown(temp,uid,gid); end: RELEASE_CONFIG_BUFFER(temp); }
int pgrep_main(int argc UNUSED_PARAM, char **argv) { unsigned pid = getpid(); int signo = SIGTERM; unsigned opt; int scan_mask = PSSCAN_COMM; char *first_arg; int first_arg_idx; int matched_pid; char *cmd_last; procps_status_t *proc; /* These are initialized to 0 */ struct { regex_t re_buffer; regmatch_t re_match[1]; } Z; #define re_buffer (Z.re_buffer) #define re_match (Z.re_match ) memset(&Z, 0, sizeof(Z)); /* We must avoid interpreting -NUM (signal num) as an option */ first_arg_idx = 1; while (1) { first_arg = argv[first_arg_idx]; if (!first_arg) break; /* not "-<small_letter>..."? */ if (first_arg[0] != '-' || first_arg[1] < 'a' || first_arg[1] > 'z') { argv[first_arg_idx] = NULL; /* terminate argv here */ break; } first_arg_idx++; } opt = getopt32(argv, "vlfxon"); argv[first_arg_idx] = first_arg; argv += optind; //argc -= optind; - unused anyway if (OPT_FULL) scan_mask |= PSSCAN_ARGVN; if (pkill) { if (OPT_LIST) { /* -l: print the whole signal list */ print_signames(); return 0; } if (first_arg && first_arg[0] == '-') { signo = get_signum(&first_arg[1]); if (signo < 0) /* || signo > MAX_SIGNUM ? */ bb_error_msg_and_die("bad signal name '%s'", &first_arg[1]); argv++; } } /* One pattern is required */ if (!argv[0] || argv[1]) bb_show_usage(); xregcomp(&re_buffer, argv[0], 0); matched_pid = 0; cmd_last = NULL; proc = NULL; while ((proc = procps_scan(proc, scan_mask)) != NULL) { char *cmd; if (proc->pid == pid) continue; cmd = proc->argv0; if (!cmd) { cmd = proc->comm; } else { int i = proc->argv_len; while (i) { if (!cmd[i]) cmd[i] = ' '; i--; } } /* NB: OPT_INVERT is always 0 or 1 */ if ((regexec(&re_buffer, cmd, 1, re_match, 0) == 0 /* match found */ && (!OPT_ANCHOR || (re_match[0].rm_so == 0 && re_match[0].rm_eo == (regoff_t)strlen(cmd)))) ^ OPT_INVERT ) { matched_pid = proc->pid; if (OPT_LAST) { free(cmd_last); cmd_last = xstrdup(cmd); continue; } act(proc->pid, cmd, signo, opt); if (OPT_FIRST) break; } } if (cmd_last) { act(matched_pid, cmd_last, signo, opt); if (ENABLE_FEATURE_CLEAN_UP) free(cmd_last); } return matched_pid == 0; /* return 1 if no processes listed/signaled */ }
int qgrep_main(int argc, char **argv) { int i; char *p; bool do_eclass; bool do_installed; DIR *eclass_dir = NULL; struct dirent *dentry = NULL; int reflags = 0; unsigned long int context_optarg; char status = 1; size_t n; char *overlay; struct qgrep_grepargs args = { .do_count = 0, .do_regex = 0, .do_list = 0, .show_filename = 0, .show_name = 0, .skip_comments = 0, .invert_list = 0, .invert_match = 0, .skip_pattern = NULL, .num_lines_before = 0, .num_lines_after = 0, .buf_list = NULL, .query = NULL, .strfunc = strstr, .include_atoms = NULL, .portdir = NULL, }; do_eclass = do_installed = 0; while ((i = GETOPT_LONG(QGREP, qgrep, "")) != -1) { switch (i) { case 'I': args.invert_match = true; break; case 'i': args.strfunc = strcasestr; reflags |= REG_ICASE; break; case 'c': args.do_count = true; break; case 'l': args.do_list = true; break; case 'L': args.do_list = args.invert_list = true; break; case 'e': args.do_regex = true; break; case 'x': args.do_regex = true; reflags |= REG_EXTENDED; break; case 'J': do_installed = true; break; case 'E': do_eclass = true; break; case 'H': args.show_filename = true; break; case 'N': args.show_name = true; break; case 's': args.skip_comments = true; break; case 'R': args.show_repo = args.show_name = true; break; case 'S': args.skip_pattern = optarg; break; case 'B': case 'A': errno = 0; context_optarg = strtol(optarg, &p, 10); if (errno != 0) errp("%s: not a valid integer", optarg); else if (p == optarg || *p != '\0') err("%s: not a valid integer", optarg); if (context_optarg > 254) err("%s: silly value!", optarg); if (i == 'B') args.num_lines_before = context_optarg; else args.num_lines_after = context_optarg; break; COMMON_GETOPTS_CASES(qgrep) } } if (argc == optind) qgrep_usage(EXIT_FAILURE); if (args.do_list && args.do_count) { warn("%s and --count are incompatible options. The former wins.", (args.invert_list ? "--invert-list" : "--list")); args.do_count = false; } if (args.show_name && args.show_filename) { warn("--with-name and --with-filename are incompatible options. " "The former wins."); args.show_filename = false; } if (args.do_list && args.num_lines_before) { warn("%s and --before are incompatible options. The former wins.", (args.invert_list ? "--invert-list" : "--list")); args.num_lines_before = 0; } if (args.do_list && args.num_lines_after) { warn("%s and --after are incompatible options. The former wins.", (args.invert_list ? "--invert-list" : "--list")); args.num_lines_after = 0; } if (args.do_count && args.num_lines_before) { warn("--count and --before are incompatible options. The former wins."); args.num_lines_before = 0; } if (args.do_count && args.num_lines_after) { warn("--count and --after are incompatible options. The former wins."); args.num_lines_after = 0; } if (do_installed && do_eclass) { warn("--installed and --eclass are incompatible options. " "The former wins."); do_eclass = false; } if (argc > (optind + 1)) { depend_atom **d = args.include_atoms = xcalloc(sizeof(depend_atom *), (argc - optind - 1) + 1); for (i = (optind + 1); i < argc; i++) { *d = atom_explode(argv[i]); if (*d == NULL) { warn("%s: invalid atom, will be ignored", argv[i]); } else { d++; } } *d = NULL; } /* make it easier to see what needs to be printed */ if (!args.show_name && (verbose || args.do_list)) args.show_filename = true; /* pre-compile regexps once for all */ if (args.do_regex) { if (args.invert_match || *RED == '\0') reflags |= REG_NOSUB; xregcomp(&args.preg, argv[optind], reflags); reflags |= REG_NOSUB; if (args.skip_pattern) xregcomp(&args.skip_preg, args.skip_pattern, reflags); } args.query = argv[optind]; /* allocate a circular buffers list for --before */ args.buf_list = qgrep_buf_list_alloc(args.num_lines_before + 1); array_for_each(overlays, n, overlay) { args.portdir = overlay; if (do_eclass) { char buf[_Q_PATH_MAX]; char name[_Q_PATH_MAX]; char *label; int efd; snprintf(buf, sizeof(buf), "%s/%s/eclass", portroot, overlay); efd = open(buf, O_RDONLY|O_CLOEXEC); if (efd == -1 || (eclass_dir = fdopendir(efd)) == NULL) { if (errno != ENOENT) warnp("opendir(\"%s/eclass\") failed", overlay); continue; } while ((dentry = readdir(eclass_dir)) != NULL) { if (strstr(dentry->d_name, ".eclass") == NULL) continue; /* filter the files we grep when there are extra args */ if (args.include_atoms != NULL) { depend_atom **d; for (d = args.include_atoms; *d != NULL; d++) { if ((*d)->PN != NULL && strncmp(dentry->d_name, (*d)->PN, strlen((*d)->PN)) == 0) break; } if (*d == NULL) continue; } label = NULL; if (args.show_name) { snprintf(name, sizeof(name), "%s%.*s%s", BLUE, (int)(strlen(dentry->d_name) - 7), dentry->d_name, NORM); label = name; } else if (args.show_filename) { snprintf(name, sizeof(name), "eclass/%s", dentry->d_name); label = name; } status = qgrep_grepat(efd, dentry->d_name, label, &args); } closedir(eclass_dir); } else if (do_installed) { status = q_vdb_foreach_pkg(portroot, portvdb, qgrep_vdb_cb, &args, NULL); } else { /* do_ebuild */ status = cache_foreach_pkg(portroot, overlay, qgrep_cache_cb, &args, NULL); } } if (args.do_regex) regfree(&args.preg); if (args.do_regex && args.skip_pattern) regfree(&args.skip_preg); if (args.include_atoms != NULL) { for (i = 0; i < (argc - optind - 1); i++) if (args.include_atoms[i] != NULL) atom_implode(args.include_atoms[i]); free(args.include_atoms); } qgrep_buf_list_free(args.buf_list); return status; }