300 lines
7.7 KiB
C
300 lines
7.7 KiB
C
/*
|
|
* pathvisit.c
|
|
*
|
|
* *********************************************************************
|
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
|
* * Permission to use, copy, modify, and distribute this *
|
|
* * software and its documentation for any purpose and without *
|
|
* * fee is hereby granted, provided that the above copyright *
|
|
* * notice appear in all copies. The University of California *
|
|
* * makes no representations about the suitability of this *
|
|
* * software for any purpose. It is provided "as is" without *
|
|
* * express or implied warranty. Export of this software outside *
|
|
* * of the United States of America may require an export license. *
|
|
* *********************************************************************
|
|
*
|
|
* This file contains several procedures to implement a means of scanning
|
|
* all files in a search path, calling client procedures when lines match
|
|
* a specified pattern.
|
|
*/
|
|
|
|
#ifndef lint
|
|
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/pathvisit.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
|
#endif /* not lint */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "utils/magic.h"
|
|
#include "utils/hash.h"
|
|
#include "utils/malloc.h"
|
|
#include "utils/pathvisit.h"
|
|
#include "utils/utils.h"
|
|
|
|
|
|
/*
|
|
* -------------------------------------------------------------------
|
|
*
|
|
* PaVisitInit --
|
|
*
|
|
* Return a newly allocated client structure that may be passed to
|
|
* PaVisitAddClient and PaVisitFiles.
|
|
*
|
|
* Results:
|
|
* Returns a pointer to a newly allocated PaVisit struct.
|
|
*
|
|
* Side Effects:
|
|
* Allocates memory.
|
|
* PaVisitFree should be called when done.
|
|
*
|
|
* -------------------------------------------------------------------
|
|
*/
|
|
|
|
PaVisit *
|
|
PaVisitInit()
|
|
{
|
|
PaVisit *pv;
|
|
|
|
pv = (PaVisit *) mallocMagic((unsigned) (sizeof (PaVisit)));
|
|
pv->pv_first = pv->pv_last = (PaVisitClient *) NULL;
|
|
return (pv);
|
|
}
|
|
|
|
/*
|
|
* -------------------------------------------------------------------
|
|
*
|
|
* PaVisitFree --
|
|
*
|
|
* Frees all memory associated with the argument PaVisit struct.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side Effects:
|
|
* Deallocates memory.
|
|
*
|
|
* -------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
PaVisitFree(pv)
|
|
PaVisit *pv;
|
|
{
|
|
PaVisitClient *pvc;
|
|
|
|
for (pvc = pv->pv_first; pvc; pvc = pvc->pvc_next)
|
|
{
|
|
if (pvc->pvc_keyword)
|
|
freeMagic(pvc->pvc_keyword);
|
|
freeMagic((char *) pvc);
|
|
}
|
|
|
|
freeMagic((char *) pv);
|
|
}
|
|
|
|
/*
|
|
* -------------------------------------------------------------------
|
|
*
|
|
* PaVisitAddClient --
|
|
*
|
|
* Add keywords and client procedures to the list that will be applied
|
|
* by PaVisitFiles. For each line in the files found by PaVisitFiles
|
|
* that matches this keyword, we call the client procedure:
|
|
*
|
|
* (*proc)(line, cdata)
|
|
* char *line;
|
|
* ClientData cdata;
|
|
* {
|
|
* }
|
|
*
|
|
* This procedure should return 0 if PaVisitFiles should continue
|
|
* processing, 1 if PaVisitFiles should stop processing completely,
|
|
* and 2 if PaVisitFiles should stop processing just this file but
|
|
* continue to the next file in the list.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side Effects:
|
|
* Modifies the PaVisit struct pointed to by 'pv' by adding a
|
|
* new client to its list.
|
|
*
|
|
* -------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
PaVisitAddClient(pv, keyword, proc, cdata)
|
|
PaVisit *pv;
|
|
char *keyword;
|
|
int (*proc)();
|
|
ClientData cdata;
|
|
{
|
|
PaVisitClient *pvc;
|
|
|
|
pvc = (PaVisitClient *) mallocMagic((unsigned) (sizeof (PaVisitClient)));
|
|
pvc->pvc_keyword = StrDup((char **) NULL, keyword);
|
|
pvc->pvc_proc = proc;
|
|
pvc->pvc_cdata = cdata;
|
|
pvc->pvc_next = (PaVisitClient *) NULL;
|
|
if (pv->pv_last)
|
|
{
|
|
pv->pv_last->pvc_next = pvc;
|
|
pv->pv_last = pvc;
|
|
}
|
|
else
|
|
{
|
|
pv->pv_first = pv->pv_last = pvc;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* -------------------------------------------------------------------
|
|
*
|
|
* PaVisitFiles --
|
|
*
|
|
* PaVisitFiles will be used to visit all files in a search path.
|
|
* For each such file, all lines matching one of the keywords supplied
|
|
* to PaVisitAddClient will be passed along to a client procedure that
|
|
* corresponds to that keyword.
|
|
*
|
|
* Lines in each of the input files that end in a backslash have the
|
|
* following line appended to them and the backslash ignored.
|
|
*
|
|
* Results:
|
|
* Returns 0 if all files were visited. Returns 1 if some
|
|
* client aborted the search by returning 1.
|
|
*
|
|
* Side Effects:
|
|
* Applies all the client procedures in the PaVisitClient
|
|
* list of pv to each line matching one of the client patterns.
|
|
*
|
|
* -------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
PaVisitFiles(path, file, pv)
|
|
char *path; /* Colon or space separated list of directories to
|
|
* search for the file 'file'. If 'file' does not
|
|
* exist in a given directory, that directory is
|
|
* skipped.
|
|
*/
|
|
char *file; /* If 'file' exists in a directory of 'path' we
|
|
* open it and match each line against the list
|
|
* of clients pointed to by 'pv'.
|
|
*/
|
|
PaVisit *pv;
|
|
{
|
|
int paVisitFilesProc();
|
|
|
|
/* Do no work if degenerate */
|
|
if (pv->pv_first == (PaVisitClient *) NULL)
|
|
return (0);
|
|
|
|
return (PaEnum(path, file, paVisitFilesProc, (ClientData) pv));
|
|
}
|
|
|
|
/*
|
|
*
|
|
* paVisitFilesProc --
|
|
*
|
|
* Process each file in the path supplied to PaVisitFiles above.
|
|
* If the file 'name' exists, we open it and process each line
|
|
* as described in PaVisitFiles above.
|
|
*
|
|
* Results:
|
|
* Returns 0 if the file 'name' doesn't exist, or if it does
|
|
* exist and all the clients returned 0. If a client returns
|
|
* 2, we abort processing this file but still return 0. If a
|
|
* client returns 1, we abort processing and return 1 to abort
|
|
* the remainder of the path search.
|
|
*
|
|
* Side Effects:
|
|
* Applies all the client procedures in the PaVisitClient
|
|
* list of pv to each line matching one of the client patterns.
|
|
*
|
|
* -------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
paVisitFilesProc(name, pv)
|
|
char *name; /* Full filename */
|
|
PaVisit *pv; /* Points to list of clients */
|
|
{
|
|
char *lp;
|
|
char line[BUFSIZ+2];
|
|
int code = 0;
|
|
FILE *f;
|
|
|
|
f = fopen(name, "r");
|
|
if (f == NULL)
|
|
return (0);
|
|
|
|
lp = line;
|
|
while (fgets(lp, BUFSIZ - (lp - line), f))
|
|
{
|
|
while (*lp && *lp != '\n')
|
|
{
|
|
if (*lp++ == '\\' && *lp == '\n')
|
|
{
|
|
*--lp = '\0';
|
|
goto next;
|
|
}
|
|
}
|
|
*lp = '\0';
|
|
if (code = paVisitProcess(lp = line, pv))
|
|
break;
|
|
next: ;
|
|
}
|
|
|
|
if (lp != line)
|
|
code = paVisitProcess(line, pv);
|
|
|
|
(void) fclose(f);
|
|
if (code == 1)
|
|
return (1);
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* -------------------------------------------------------------------
|
|
*
|
|
* paVisitProcess --
|
|
*
|
|
* Process an extended line from an input file. If the initial part
|
|
* (up to the first white space) matches one of the keywords in the
|
|
* client list pv->pv_first, we apply the associated procedure.
|
|
*
|
|
* Results:
|
|
* Returns the result of applying the first client procedure
|
|
* that returns a non-zero result, or zero if all clients
|
|
* return zero. If there is no match, we return 0.
|
|
*
|
|
* Side Effects:
|
|
* Applies all the client procedures in the PaVisitClient
|
|
* whose keywords match 'line'.
|
|
*
|
|
* -------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
paVisitProcess(line, pv)
|
|
char *line;
|
|
PaVisit *pv;
|
|
{
|
|
PaVisitClient *pvc;
|
|
char *cp;
|
|
int code = 0, len;
|
|
|
|
for (cp = line; *cp && !isspace(*cp); cp++)
|
|
/* Nothing */;
|
|
len = cp - line;
|
|
|
|
for (pvc = pv->pv_first; pvc; pvc = pvc->pvc_next)
|
|
if (len > 0 && strncmp(line, pvc->pvc_keyword, len) == 0)
|
|
if (code = (*pvc->pvc_proc)(line, pvc->pvc_cdata))
|
|
break;
|
|
|
|
return (code);
|
|
}
|