|
|
BSD 4.3
static char *rcsid = "$Header: /var/lib/cvsd/repos/CSRG/43BSD/contrib/spms/src/bin/pdiff/pdiff.c,v 1.1.1.1 2018/04/24 16:12:55 root Exp $";
/*
* pdiff - differential project comparator
*
* Author: Peter J. Nicklin
*/
#include <stdio.h>
#include "getarg.h"
#include "macro.h"
#include "null.h"
#include "path.h"
#include "pdb.h"
#include "pdtyp.h"
#include "pld.h"
#include "ptree.h"
#include "spms.h"
#include "yesno.h"
char **NARGV; /* new argument list */
char *PGN = "pdiff"; /* program name */
int EXECUTE = YES; /* execute command? */
int NARGI = 0; /* new argument list index */
int RECURSIVE = 0; /* recursively compare projects */
PDTYP PDIRTYP; /* project directory type labels list */
main(argc, argv)
int argc;
char **argv;
{
extern int PPDEBUG; /* project pathname debug flag */
char p1[PPATHSIZE]; /* project pathname buffer */
char p2[PPATHSIZE]; /* project pathname buffer */
char *strcpy(); /* string copy */
int balance(); /* balance PDIR structs */
int diffdir(); /* compare directories or files */
int diffproject(); /* compare projects */
int pdtparse(); /* parse boolean type label expr */
int read_path(); /* read project or regular pathname */
int status = 0; /* exit status */
PATH pb1; /* pathname struct buffer 1 */
PATH pb2; /* pathname struct buffer 2 */
unsigned long pathtyp1; /* type of pathname 1 */
unsigned long pathtyp2; /* type of pathname 2 */
NARGV = argv;
NARGV[NARGI++] = "diff";
{
register char *s; /* option pointer */
while (--argc > 0 && **++argv == '-')
{
for (s = argv[0]+1; *s != '\0'; s++)
switch (*s)
{
case 'D':
PPDEBUG = YES;
break;
case 'T':
if (pdtparse(GETARG(s), &PDIRTYP) == NO)
status = 1;
goto endfor;
case 'r':
RECURSIVE++;
break;
case 'x':
EXECUTE = NO;
break;
default:
NARGV[NARGI++] = *argv;
break;
}
endfor: continue;
}
}
if (status == 1 || argc < 2)
{
warn("usage: pdiff [-rx] [-T typexpr] [diff options] p1 p2");
exit(2);
}
strcpy(p1, argv[0]);
strcpy(p2, argv[1]);
NARGV[NARGI+2] = NULL;
if (read_path(p1, &pb1) == NO || read_path(p2, &pb2) == NO)
exit(2);
pathtyp1 = (pb1.p_mode & P_IFMT);
pathtyp2 = (pb2.p_mode & P_IFMT);
if (pathtyp1 == P_IFPROOT || pathtyp1 == P_IFHOME)
{
if (pathtyp2 == P_IFPROOT || pathtyp2 == P_IFHOME)
status = diffproject(p1, pb1.p_path, p2, pb2.p_path);
else if (balance(p1, &pb1, &pb2) == NO)
exit(2);
else
status = diffdir(p1, pb1.p_path, p2, pb2.p_path);
}
else if (pathtyp2 == P_IFPROOT || pathtyp2 == P_IFHOME)
{
if (balance(p2, &pb2, &pb1) == NO)
exit(2);
else
status = diffdir(p1, pb1.p_path, p2, pb2.p_path);
}
else {
status = diffdir(p1, pb1.p_path, p2, pb2.p_path);
}
if (status > 1)
status = 2;
exit(status);
}
/*
* balance() balances a PATH struct given a project and a directory or file.
* If a regular directory or file, then it is assumed to be relative to the
* current working project directory. Returns NO if balancing fails, otherwise
* YES. The project pathname p1 is updated to reflect the balancing.
*/
balance(p1, pb1, pb2)
char *p1; /* we know this is a project root dir */
PATH *pb1; /* project root directory buffer */
PATH *pb2; /* (project) directory or file buffer */
{
char *pathcat(); /* regular pathname concatenation */
char *ppathcat(); /* project pathname concatenation */
int getcpd(); /* get current working project dir */
int read_path(); /* read project or regular pathname */
PATH cpathbuf; /* current pathname struct buffer */
if ((pb2->p_mode&P_IFMT) == P_IFPDIR)
{
ppathcat(p1, p1, pb2->p_alias);
return(read_path(p1, pb1));
}
else if (*pb2->p_path == _RDIRC || getcpd(&cpathbuf) != 1)
{
warn("don't know which project directory to use in %s", p1);
return(NO);
}
else {
ppathcat(p1, p1, cpathbuf.p_alias);
pathcat(p1, p1, pb2->p_path);
return(read_path(p1, pb1));
}
}
/*
* diffdir() compares two directories or files. Returns whatever diff()
* returns.
*/
diffdir(pp1, d1, pp2, d2)
char *pp1; /* project pathname */
char *d1; /* directory or file pathname */
char *pp2; /* project pathname */
char *d2; /* directory or file pathname */
{
static int have_printed; /* has printing already been done? */
int diff(); /* fork diff program */
int iargi; /* argument index */
if (have_printed)
putchar('\n');
have_printed = 1;
printf("==> ");
for (iargi = 0; iargi < NARGI; iargi++)
printf("%s ", NARGV[iargi]);
printf("%s %s <==\n", pp1, pp2);
fflush(stdout);
if (EXECUTE == NO)
return(0);
NARGV[NARGI] = d1;
NARGV[NARGI+1] = d2;
return(diff(NARGV));
}
/*
* diffproject() compares two projects, recursively if necessary. Returns
* 0 if no differences, 1 if some, 2 if trouble.
*/
diffproject(pp1, p1, pp2, p2)
char *pp1; /* project pathname */
char *p1; /* project root directory pathname */
char *pp2; /* project pathname */
char *p2; /* project root directory pathname */
{
int closepdb(); /* close database */
int diffpdtree(); /* diff project directory tree */
int diffptree(); /* diff tree of projects */
int errpdb(); /* print database error message */
int pdtmatch(); /* match project dir type label expr */
int status = 0; /* return status */
PATH *pd; /* pathname struct pointer */
PATH *readpld(); /* read project link directory entry */
PDB *openpdb(); /* open database */
PDB *pldp; /* project link directory stream */
PTREE *proot; /* root of project tree */
PTREE *pdroot; /* root of project directory tree */
PTREE *ptree(); /* search and insert in proj dir tree */
void ptreerm(); /* remove project directory tree */
proot = NULL;
pdroot = NULL;
/* read PLDNAME project link directory belonging to p1 */
if ((pldp = openpdb(PLDNAME, p1, "r")) == NULL)
{
errpdb((PDB *) NULL);
return(2);
}
while ((pd = readpld(pldp)) != NULL)
{
if (EQUAL(pd->p_alias, PARENTPROJECT))
continue;
else if (EQUAL(pd->p_alias, CURPROJECT))
{
if (PDIRTYP.pfxsize==0 || pdtmatch(&PDIRTYP,pd->p_type)==YES)
pdroot = ptree(pdroot, "", pd->p_path, CNULL);
}
else if (pd->p_mode == P_IFPROOT)
{
if (RECURSIVE)
proot = ptree(proot, pd->p_alias, pd->p_path, CNULL);
}
else if (PDIRTYP.pfxsize==0 || pdtmatch(&PDIRTYP,pd->p_type)==YES)
pdroot = ptree(pdroot, pd->p_alias, pd->p_path, CNULL);
}
closepdb(pldp);
/* read PLDNAME project link directory belonging to p2 */
if ((pldp = openpdb(PLDNAME, p2, "r")) == NULL)
{
errpdb((PDB *) NULL);
return(2);
}
while ((pd = readpld(pldp)) != NULL)
{
if (EQUAL(pd->p_alias, PARENTPROJECT))
continue;
else if (EQUAL(pd->p_alias, CURPROJECT))
{
if (PDIRTYP.pfxsize==0 || pdtmatch(&PDIRTYP,pd->p_type)==YES)
pdroot = ptree(pdroot, "", CNULL, pd->p_path);
}
else if (pd->p_mode == P_IFPROOT)
{
if (RECURSIVE)
proot = ptree(proot, pd->p_alias, CNULL, pd->p_path);
}
else if (PDIRTYP.pfxsize==0 || pdtmatch(&PDIRTYP,pd->p_type)==YES)
pdroot = ptree(pdroot, pd->p_alias, CNULL, pd->p_path);
}
closepdb(pldp);
/* diff project directory tree */
status |= diffpdtree(pdroot, pp1, pp2);
ptreerm(pdroot);
/* diff subprojects */
status |= diffptree(proot, pp1, pp2);
ptreerm(proot);
return(status);
}
/*
* diffpdtree() compares project directories in a project directory tree.
*/
diffpdtree(p, pp1, pp2)
PTREE *p; /* current node in project dir tree */
char *pp1; /* project pathname */
char *pp2; /* project pathname */
{
char ppathbuf1[PPATHSIZE]; /* project pathname buffer */
char ppathbuf2[PPATHSIZE]; /* project pathname buffer */
char *ppathcat(); /* project pathname concantenation */
int diffdir(); /* compare directories or files */
int status = 0; /* return status */
void printonly(); /* print "only in project ..." mesg */
if (p == NULL)
return(0);
status |= diffpdtree(p->left, pp1, pp2);
if (p->pd1 == NULL)
printonly(pp2, p->alias);
else if (p->pd2 == NULL)
printonly(pp1, p->alias);
else {
ppathcat(ppathbuf1, pp1, p->alias);
ppathcat(ppathbuf2, pp2, p->alias);
status |= diffdir(ppathbuf1, p->pd1, ppathbuf2, p->pd2);
}
status |= diffpdtree(p->right, pp1, pp2);
return(status);
}
/*
* diffptree() compares projects in a project tree.
*/
diffptree(p, pp1, pp2)
PTREE *p; /* current node in project tree */
char *pp1; /* project pathname */
char *pp2; /* project pathname */
{
char ppathbuf1[PPATHSIZE]; /* project pathname buffer */
char ppathbuf2[PPATHSIZE]; /* project pathname buffer */
char *ppathcat(); /* project pathname concantenation */
int diffproject(); /* compare projects */
int status = 0; /* return status */
void printonly(); /* print "only in project ..." mesg */
if (p == NULL)
return(0);
status |= diffptree(p->left, pp1, pp2);
if (p->pd1 == NULL)
printonly(pp2, p->alias);
else if (p->pd2 == NULL)
printonly(pp1, p->alias);
else {
ppathcat(ppathbuf1, pp1, p->alias);
ppathcat(ppathbuf2, pp2, p->alias);
status |= diffproject(ppathbuf1, p->pd1, ppathbuf2, p->pd2);
}
status |= diffptree(p->right, pp1, pp2);
return(status);
}
/*
* printonly() prints "only in project ..." message.
*/
void
printonly(project, pdirname)
char *project; /* project pathname */
char *pdirname; /* unique project directory */
{
printf("Only in project %s: %s\n", project,
(*pdirname == '\0') ? CURPROJECT : pdirname);
fflush(stdout);
}
/*
* read_path() loads a PATH struct given a regular or project pathname.
* Returns integer NO if an invalid pathname or non-existent target,
* otherwise YES.
*/
read_path(pathname, pb)
char *pathname; /* regular or project pathname */
PATH *pb; /* pathname struct buffer */
{
int readpath(); /* read project or regular pathname */
if (readpath(pathname, pb) == -1 || (pb->p_mode & P_IFMT) == P_IFNEW)
{
patherr(pathname);
return(NO);
}
return(YES);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.