⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcregrep.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
字号:
/**************************************************               pcregrep program                 **************************************************//* This is a grep program that uses the PCRE regular expression library to doits pattern matching. On a Unix system it can recurse into directories. */#include <ctype.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include "config.h"#include "pcre.h"#define FALSE 0#define TRUE 1typedef int BOOL;#define VERSION "2.0 01-Aug-2001"#define MAX_PATTERN_COUNT 100/**************************************************               Global variables                 **************************************************/static char *pattern_filename = NULL;static int  pattern_count = 0;static pcre **pattern_list;static pcre_extra **hints_list;static BOOL count_only = FALSE;static BOOL filenames = TRUE;static BOOL filenames_only = FALSE;static BOOL invert = FALSE;static BOOL number = FALSE;static BOOL recurse = FALSE;static BOOL silent = FALSE;static BOOL whole_lines = FALSE;/* Structure for options and list of them */typedef struct option_item {  int one_char;  char *long_name;  char *help_text;} option_item;static option_item optionlist[] = {  { -1,  "help",         "display this help and exit" },  { 'c', "count",        "print only a count of matching lines per FILE" },  { 'h', "no-filename",  "suppress the prefixing filename on output" },  { 'i', "ignore-case",  "ignore case distinctions" },  { 'l', "files-with-matches", "print only FILE names containing matches" },  { 'n', "line-number",  "print line number with output lines" },  { 'r', "recursive",    "recursively scan sub-directories" },  { 's', "no-messages",  "suppress error messages" },  { 'V', "version",      "print version information and exit" },  { 'v', "invert-match", "select non-matching lines" },  { 'x', "line-regex",   "force PATTERN to match only whole lines" },  { 'x', "line-regexp",  "force PATTERN to match only whole lines" },  { 0,    NULL,           NULL }};/**************************************************       Functions for directory scanning         **************************************************//* These functions are defined so that they can be made system specific,although at present the only ones are for Unix, and for "no directory recursionsupport". *//************* Directory scanning in Unix ***********/#if IS_UNIX#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>typedef DIR directory_type;intisdirectory(char *filename){struct stat statbuf;if (stat(filename, &statbuf) < 0)  return 0;        /* In the expectation that opening as a file will fail */return ((statbuf.st_mode & S_IFMT) == S_IFDIR)? '/' : 0;}directory_type *opendirectory(char *filename){return opendir(filename);}char *readdirectory(directory_type *dir){for (;;)  {  struct dirent *dent = readdir(dir);  if (dent == NULL) return NULL;  if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0)    return dent->d_name;  }return NULL;   /* Keep compiler happy; never executed */}voidclosedirectory(directory_type *dir){closedir(dir);}#else/************* Directory scanning when we can't do it ***********//* The type is void, and apart from isdirectory(), the functions do nothing. */typedef void directory_type;int isdirectory(char *filename) { return FALSE; }directory_type * opendirectory(char *filename) {}char *readdirectory(directory_type *dir) {}void closedirectory(directory_type *dir) {}#endif#if ! HAVE_STRERROR/**************************************************     Provide strerror() for non-ANSI libraries  **************************************************//* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror()in their libraries, but can provide the same facility by this simplealternative function. */extern int   sys_nerr;extern char *sys_errlist[];char *strerror(int n){if (n < 0 || n >= sys_nerr) return "unknown error number";return sys_errlist[n];}#endif /* HAVE_STRERROR *//**************************************************              Grep an individual file           **************************************************/static intpcregrep(FILE *in, char *name){int rc = 1;int linenumber = 0;int count = 0;int offsets[99];char buffer[BUFSIZ];while (fgets(buffer, sizeof(buffer), in) != NULL)  {  BOOL match = FALSE;  int i;  int length = (int)strlen(buffer);  if (length > 0 && buffer[length-1] == '\n') buffer[--length] = 0;  linenumber++;  for (i = 0; !match && i < pattern_count; i++)    {    match = pcre_exec(pattern_list[i], hints_list[i], buffer, length, 0, 0,      offsets, 99) >= 0;    if (match && whole_lines && offsets[1] != length) match = FALSE;    }  if (match != invert)    {    if (count_only) count++;    else if (filenames_only)      {      fprintf(stdout, "%s\n", (name == NULL)? "<stdin>" : name);      return 0;      }    else if (silent) return 0;    else      {      if (name != NULL) fprintf(stdout, "%s:", name);      if (number) fprintf(stdout, "%d:", linenumber);      fprintf(stdout, "%s\n", buffer);      }    rc = 0;    }  }if (count_only)  {  if (name != NULL) fprintf(stdout, "%s:", name);  fprintf(stdout, "%d\n", count);  }return rc;}/**************************************************     Grep a file or recurse into a directory    **************************************************/static intgrep_or_recurse(char *filename, BOOL recurse, BOOL show_filenames,  BOOL only_one_at_top){int rc = 1;int sep;FILE *in;/* If the file is a directory and we are recursing, scan each file within it.The scanning code is localized so it can be made system-specific. */if ((sep = isdirectory(filename)) != 0 && recurse)  {  char buffer[1024];  char *nextfile;  directory_type *dir = opendirectory(filename);  if (dir == NULL)    {    fprintf(stderr, "pcregrep: Failed to open directory %s: %s\n", filename,      strerror(errno));    return 2;    }  while ((nextfile = readdirectory(dir)) != NULL)    {    int frc;    sprintf(buffer, "%.512s%c%.128s", filename, sep, nextfile);    frc = grep_or_recurse(buffer, recurse, TRUE, FALSE);    if (frc == 0 && rc == 1) rc = 0;    }  closedirectory(dir);  return rc;  }/* If the file is not a directory, or we are not recursing, scan it. If this isthe first and only argument at top level, we don't show the file name.Otherwise, control is via the show_filenames variable. */in = fopen(filename, "r");if (in == NULL)  {  fprintf(stderr, "pcregrep: Failed to open %s: %s\n", filename, strerror(errno));  return 2;  }rc = pcregrep(in, (show_filenames && !only_one_at_top)? filename : NULL);fclose(in);return rc;}/**************************************************                Usage function                  **************************************************/static intusage(int rc){fprintf(stderr, "Usage: pcregrep [-Vcfhilnrsvx] [long-options] pattern [file] ...\n");fprintf(stderr, "Type `pcregrep --help' for more information.\n");return rc;}/**************************************************                Help function                   **************************************************/static voidhelp(void){option_item *op;printf("Usage: pcregrep [OPTION]... PATTERN [FILE] ...\n");printf("Search for PATTERN in each FILE or standard input.\n");printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");printf("Options:\n");for (op = optionlist; op->one_char != 0; op++)  {  int n;  char s[4];  if (op->one_char > 0) sprintf(s, "-%c,", op->one_char); else strcpy(s, "   ");  printf("  %s --%s%n", s, op->long_name, &n);  n = 30 - n;  if (n < 1) n = 1;  printf("%.*s%s\n", n, "                    ", op->help_text);  }printf("\n  -f<filename>  or  --file=<filename>\n");printf("    Read patterns from <filename> instead of using a command line option.\n");printf("    Trailing white space is removed; blanks lines are ignored.\n");printf("    There is a maximum of %d patterns.\n", MAX_PATTERN_COUNT);printf("\nWith no FILE, read standard input. If fewer than two FILEs given, assume -h.\n");printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n");}/**************************************************                Handle an option                **************************************************/static inthandle_option(int letter, int options){switch(letter)  {  case -1:  help(); exit(0);  case 'c': count_only = TRUE; break;  case 'h': filenames = FALSE; break;  case 'i': options |= PCRE_CASELESS; break;  case 'l': filenames_only = TRUE;  case 'n': number = TRUE; break;  case 'r': recurse = TRUE; break;  case 's': silent = TRUE; break;  case 'v': invert = TRUE; break;  case 'x': whole_lines = TRUE; options |= PCRE_ANCHORED; break;  case 'V':  fprintf(stderr, "pcregrep version %s using ", VERSION);  fprintf(stderr, "PCRE version %s\n", pcre_version());  exit(0);  break;  default:  fprintf(stderr, "pcregrep: Unknown option -%c\n", letter);  exit(usage(2));  }return options;}/**************************************************                Main program                    **************************************************/intmain(int argc, char **argv){int i, j;int rc = 1;int options = 0;int errptr;const char *error;BOOL only_one_at_top;/* Process the options */for (i = 1; i < argc; i++)  {  if (argv[i][0] != '-') break;  /* Long name options */  if (argv[i][1] == '-')    {    option_item *op;    if (strncmp(argv[i]+2, "file=", 5) == 0)      {      pattern_filename = argv[i] + 7;      continue;      }    for (op = optionlist; op->one_char != 0; op++)      {      if (strcmp(argv[i]+2, op->long_name) == 0)        {        options = handle_option(op->one_char, options);        break;        }      }    if (op->one_char == 0)      {      fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]);      exit(usage(2));      }    }  /* One-char options */  else    {    char *s = argv[i] + 1;    while (*s != 0)      {      if (*s == 'f')        {        pattern_filename = s + 1;        if (pattern_filename[0] == 0)          {          if (i >= argc - 1)            {            fprintf(stderr, "pcregrep: File name missing after -f\n");            exit(usage(2));            }          pattern_filename = argv[++i];          }        break;        }      else options = handle_option(*s++, options);      }    }  }pattern_list = malloc(MAX_PATTERN_COUNT * sizeof(pcre *));hints_list = malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *));if (pattern_list == NULL || hints_list == NULL)  {  fprintf(stderr, "pcregrep: malloc failed\n");  return 2;  }/* Compile the regular expression(s). */if (pattern_filename != NULL)  {  FILE *f = fopen(pattern_filename, "r");  char buffer[BUFSIZ];  if (f == NULL)    {    fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename,      strerror(errno));    return 2;    }  while (fgets(buffer, sizeof(buffer), f) != NULL)    {    char *s = buffer + (int)strlen(buffer);    if (pattern_count >= MAX_PATTERN_COUNT)      {      fprintf(stderr, "pcregrep: Too many patterns in file (max %d)\n",        MAX_PATTERN_COUNT);      return 2;      }    while (s > buffer && isspace((unsigned char)(s[-1]))) s--;    if (s == buffer) continue;    *s = 0;    pattern_list[pattern_count] = pcre_compile(buffer, options, &error,      &errptr, NULL);    if (pattern_list[pattern_count++] == NULL)      {      fprintf(stderr, "pcregrep: Error in regex number %d at offset %d: %s\n",        pattern_count, errptr, error);      return 2;      }    }  fclose(f);  }/* If no file name, a single regex must be given inline */else  {  if (i >= argc) return usage(0);  pattern_list[0] = pcre_compile(argv[i++], options, &error, &errptr, NULL);  if (pattern_list[0] == NULL)    {    fprintf(stderr, "pcregrep: Error in regex at offset %d: %s\n", errptr,      error);    return 2;    }  pattern_count++;  }/* Study the regular expressions, as we will be running them may times */for (j = 0; j < pattern_count; j++)  {  hints_list[j] = pcre_study(pattern_list[j], 0, &error);  if (error != NULL)    {    char s[16];    if (pattern_count == 1) s[0] = 0; else sprintf(s, " number %d", j);    fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error);    return 2;    }  }/* If there are no further arguments, do the business on stdin and exit */if (i >= argc) return pcregrep(stdin, NULL);/* Otherwise, work through the remaining arguments as files or directories.Pass in the fact that there is only one argument at top level - this suppressesthe file name if the argument is not a directory. */only_one_at_top = (i == argc - 1);if (filenames_only) filenames = TRUE;for (; i < argc; i++)  {  int frc = grep_or_recurse(argv[i], recurse, filenames, only_one_at_top);  if (frc == 0 && rc == 1) rc = 0;  }return rc;}/* End */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -