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);
|
||
}
|