Example #1
0
/*
 * 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;
}
Example #2
0
/*
 * 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;
}
Example #3
0
/*
 * 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;
}
Example #4
0
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;
}
Example #5
0
/*
 * 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;
}
Example #6
0
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;
}
Example #7
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);
}
Example #8
0
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;
}
Example #9
0
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;
}
Example #10
0
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(&regexes[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(&regexes[nregexes-1], restr, reflags);
}
Example #11
0
static void add_regex(const char *restr)
{
	regexes = xrealloc(regexes, sizeof(regex_t) * (++nregexes));
	xregcomp(&regexes[nregexes-1], restr, reflags);
}
Example #12
0
// 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);
}
Example #13
0
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;
}
Example #14
0
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(&regex, pattern_ptr->data, reflags);
				ret |= regexec(&regex, line, 0, NULL, 0) == 0;
				regfree(&regex);
			}
			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;
}
Example #15
0
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();
}
Example #16
0
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, &regmatch, 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;
}
Example #17
0
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;
}
Example #18
0
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, &notmuch))
	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 (&regex,
		   "^([^ ]+) \\(([^)]*)\\)$",
		   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 (&regex, 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 (&regex);

    if (line)
	free (line);

    notmuch_database_destroy (notmuch);
    if (input != stdin)
	fclose (input);

    return 0;
}
Example #19
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 */
}
Example #20
0
/* 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);
}
Example #21
0
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 */
}
Example #22
0
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;
}