|
|
BSD 4.3
static char *rcsid = "$Header: /var/lib/cvsd/repos/CSRG/43BSD/contrib/spms/src/bin/rmproject/rmproject.c,v 1.1.1.1 2018/04/24 16:12:55 root Exp $";
/*
* rmproject - remove a project root directory
*
* Author: Peter J. Nicklin
*/
#include <sys/param.h>
#include <signal.h>
#include <stdio.h>
#include "getarg.h"
#include "macro.h"
#include "null.h"
#include "path.h"
#include "pdb.h"
#include "pld.h"
#include "slist.h"
#include "spms.h"
#include "system.h"
#include "yesno.h"
char CWD[PATHSIZE]; /* current working directory */
char *CWP; /* current working project */
char *PGN = "rmproject"; /* program name */
char *RMFLAG = ""; /* rm "-f" flag */
int FORCE = 0; /* brute force remove or undefine */
int RECURSIVE = 0; /* remove project dirs recursively */
int UNDEFINE = 0; /* remove proj dir definitions only */
int WANT_TO_EXIT = 0; /* advisory exit flag */
main(argc, argv)
int argc;
char **argv;
{
extern int PPDEBUG; /* project pathname debug flag */
char *getcwp(); /* get current working project */
char *getwd(); /* get current working directory */
int isfg(); /* is process in foreground? */
int onintr(); /* process signals */
int rmproject(); /* remove a project root directory */
int rmtyp(); /* remove project dir type labels */
int status = 0; /* exit status */
int unproject(); /* undefine project root directory */
int xppath(); /* expand project pathname */
PATH pathbuf; /* pathname struct buffer */
SLIST *pdirtyp; /* project directory type labels list */
SLIST *slinit(); /* initialize singly-linked list */
void typargtolist(); /* type labels -> pdirtyp list */
pdirtyp = slinit();
{
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 'F':
/*
* 'F' option is mentioned in
* rmproject() and unproject()
*/
FORCE++;
break;
case 'T':
typargtolist(GETARG(s), pdirtyp);
if (*s == '\0')
status = 1;
goto endfor;
case 'f':
RMFLAG = "-f";
break;
case 'r':
RECURSIVE++;
break;
case 'u':
UNDEFINE++;
break;
default:
warn("bad option -%c", *s);
status = 1;
goto endfor;
}
endfor: continue;
}
}
if (status == 1 || argc < 1)
fatal("usage: rmproject [-fru] [-T type[,type...]] projectname ...");
if ((CWP = getcwp()) == NULL)
fatal("no project environment");
if (getwd(CWD) == NULL)
fatal("can't find current working directory");
if (isfg() == YES)
{
signal(SIGINT, onintr);
signal(SIGQUIT, onintr);
signal(SIGHUP, onintr);
}
for (; argc > 0; ++argv, --argc)
{
if (xppath(*argv, &pathbuf) == -1)
{
patherr(*argv);
status = 1;
continue;
}
switch (pathbuf.p_mode & P_IFMT)
{
case P_IFHOME:
case P_IFPROOT:
if (SLNUM(pdirtyp) > 0)
status |= rmtyp(*argv, pdirtyp, &pathbuf);
else if (UNDEFINE)
status |= unproject(*argv, &pathbuf);
else
status |= rmproject(*argv, &pathbuf);
break;
case P_IFPDIR:
warn("%s is a project directory", *argv);
status = 1;
break;
case P_IFNEW:
case P_IFREG:
warn("%s: no such project", *argv);
status = 1;
break;
}
if (WANT_TO_EXIT)
exit(1);
}
exit(status);
}
/*
* onintr() resets interrupt, quit, and hangup signals, and sets a flag
* which advises the process to exit at the first opportunity.
*/
onintr()
{
signal(SIGINT, onintr);
signal(SIGQUIT, onintr);
signal(SIGHUP, onintr);
WANT_TO_EXIT = 1;
}
/*
* pbrmtyp() removes type labels from database buffer.
*/
void
pbrmtyp(ppathname, typlist)
char *ppathname; /* project pathname */
SLIST *typlist; /* type labels list */
{
char *pbgetstring(); /* get specified string field */
char *pdtfind(); /* find type label in buffer */
char *slget(); /* get next key from list */
char *tp; /* pointer to type label */
char typbuf[TYPBUFSIZE]; /* project directory types buffer */
int pbaddstring(); /* add string field */
int strlen(); /* string length */
void slrewind(); /* rewind list */
void pdtrm(); /* remove type label */
pbgetstring(PDIRTYPE, typbuf);
slrewind(typlist);
while ((tp = slget(typlist)) != NULL)
{
if (pdtfind(tp, typbuf) != NULL)
pdtrm(tp, typbuf);
else
warn("%s: \"%s\" type label not found", ppathname, tp);
}
pbaddstring(PDIRTYPE, typbuf);
}
/*
* rmd() removes a project directory. rmd() returns the status of the rm
* command or 1 if the user decides not to remove a project directory.
* Before removing a directory the project link directory is moved to
* safe place. If the directory is removed successfully, the project link
* directory is removed.
*/
rmd(pathname)
char *pathname; /* full pathname of directory */
{
char cmdbuf[PATHSIZE+9]; /* command buffer */
int rmpld(); /* remove project link directory */
int savepld(); /* save project link directory */
int status; /* return status */
int yes(); /* is reply yes? */
void restorpld(); /* restore project link directory */
void unsavepld(); /* remove saved project link dir */
if (RECURSIVE)
{
sprintf(cmdbuf, "rm %s -r %s", RMFLAG, pathname);
printf("%s? [yn](n): ", cmdbuf);
if (!yes())
return(1);
status = system(cmdbuf);
status >>= NBBY;
status &= 0xff;
}
else {
if ((status = savepld(pathname)) == 0)
if ((status = rmpld(pathname)) == 0)
if ((status = RM_DIR(pathname)) != 0)
restorpld(pathname);
else
unsavepld();
}
return(status);
}
/*
* rmpld() removes a project link directory. Returns 1 if file not
* removed, otherwise zero.
*/
rmpld(pathname)
char *pathname; /* project root directory pathname */
{
char *pathcat(); /* pathname concatenation */
char pldpathname[PATHSIZE]; /* project link directory pathname */
if (unlink(pathcat(pldpathname, pathname, PLDNAME)) != 0)
if (!FORCE)
{
pperror(pldpathname);
return(1);
}
return(0);
}
/*
* rmproject() removes a project root directory. Returns 0 is successful,
* otherwise 1.
*/
rmproject(ppathname, pb)
char *ppathname; /* project root directory pathname */
PATH *pb; /* pathname struct buffer */
{
char *ppathcat(); /* project pathname concatenation */
char *ppathhead(); /* remove tail of project pathname */
char pppathname[PPATHSIZE]; /* parent project pathname */
char *strcpy(); /* string copy */
int _closepdb(); /* close database without updating */
int closepdb(); /* close database */
int errpdb(); /* print database error */
int plen; /* length of regular pathname */
int pputent(); /* write buffer to database */
int pstatus = 0; /* project status */
int strlen(); /* string length */
int strncmp(); /* compare n characters */
int subprojects(); /* check for subprojects */
int xppath(); /* expand project pathname */
PATH *pd; /* pathname struct pointer */
PATH ppathbuf; /* parent project pathname struct buf */
PATH *readpld(); /* read project link directory entry */
PDB *openpdb(); /* open database */
PDB *pldp; /* project link directory stream */
void resetpdb(); /* reset current database pointer */
if (EQUAL(ppathname, CURPROJECT))
{
warn("%s: can't remove current project", ppathname);
return(1);
}
plen = strlen(pb->p_path);
if (strncmp(pb->p_path, CWD, plen) == 0)
{
warn("can't remove %s from current directory", ppathname);
return(1);
}
if (FORCE)
{
if (*ppathname != _PDIRC && *ppathname != _HDIRC)
{
warn("%s must an absolute project pathname", ppathname);
return(1);
}
ppathhead(strcpy(pppathname, ppathname));
}
else {
ppathcat(pppathname, ppathname, PARENTPROJECT);
}
if (xppath(pppathname, &ppathbuf) == -1)
{
patherr("");
warn("force removal by typing `rmproject -F projectname'");
return(1);
}
if ((pldp = openpdb(PLDNAME, ppathbuf.p_path, "rw")) == NULL)
return(errpdb((PDB *) NULL));
while ((pd = readpld(pldp)) != NULL)
if (EQUAL(pb->p_alias, pd->p_alias))
{
pstatus = subprojects(pb->p_path);
if (pstatus == 1)
{
warn("%s: project not empty", ppathname);
resetpdb(pldp);
break;
}
else if (pstatus == 2)
{
warn("can't remove %s because subprojects exist",
ppathname);
resetpdb(pldp);
break;
}
else if (pstatus == 3)
{
resetpdb(pldp);
break;
}
resetpdb(pldp);
}
else if (strncmp(pb->p_path, pd->p_path, plen) == 0)
{ /* don't clobber nested projects */
if (pd->p_mode == P_IFPROOT)
{
warnexist(ppathname, pd->p_alias);
pstatus = 4;
break;
}
}
else {
pputent(pldp);
}
if (pstatus != 0)
_closepdb(pldp);
else if ((pstatus = rmd(pb->p_path)) != 0)
_closepdb(pldp);
else
pstatus = closepdb(pldp);
return(pstatus != 0);
}
/*
* rmtyp() removes type labels from an existing project directory.
*/
rmtyp(ppathname, pdirtyp, pb)
char *ppathname; /* project directory pathname */
SLIST *pdirtyp; /* project directory type labels list */
PATH *pb; /* pathname struct buffer */
{
char *pbfndkey(); /* find key */
int closepdb(); /* close database */
int errpdb(); /* print database error */
int pgetent(); /* load next entry into buffer */
int pputent(); /* write buffer to database */
int status = 0; /* return status */
PDB *openpdb(); /* open database */
PDB *pldp; /* project link directory stream */
void pbrmtyp(); /* remove type labels from buffer */
if ((pldp = openpdb(PLDNAME, pb->p_project, "rw")) == NULL)
return(errpdb((PDB *) NULL));
while (pgetent(pldp) != EOF)
{
if (pbfndkey(CURPROJECT) != NULL)
pbrmtyp(ppathname, pdirtyp);
pputent(pldp);
}
status = closepdb(pldp);
return(status);
}
/*
* subprojects() returns 1 if a project has project directories, 2 if any
* of these are subprojects, and zero otherwise.
*/
subprojects(pathname)
char *pathname; /* project root directory pathname */
{
char *pbfndkey(); /* find key */
int closepdb(); /* close database */
int errpdb(); /* print database error */
int pbfndflag(); /* find flag field */
int pgetent(); /* load next entry into buffer */
int status = 0; /* return status */
PDB *openpdb(); /* open database */
PDB *pldp; /* project link directory stream */
if ((pldp = openpdb(PLDNAME, pathname, "r")) == NULL)
{
if (!FORCE) return(errpdb((PDB *) NULL));
return(status);
}
while (pgetent(pldp) != EOF)
if (pbfndkey(CURPROJECT) == NULL &&
pbfndkey(PARENTPROJECT) == NULL)
{
if (!RECURSIVE) status = 1;
if (pbfndflag(PROOTDIR) == YES)
{
status = 2;
break;
}
}
closepdb(pldp);
return(status);
}
/*
* typargtolist() prepends comma-separated type labels specified in typarg
* to typlist.
*/
void
typargtolist(typarg, typlist)
register char *typarg; /* type labels argument */
SLIST *typlist; /* type labels list */
{
register char *t; /* type label argument pointer */
char *slprepend(); /* prepend singly-linked list key */
for (t = typarg; *t != '\0'; t++)
continue;
for (; t >= typarg; t--)
if (t[0] == ',')
{
if (t[1] != '\0')
slprepend(t+1, typlist);
t[0] = '\0';
}
slprepend(typarg, typlist);
}
/*
* unproject() undefines a project root directory. Returns 0 is successful,
* otherwise 1.
*/
unproject(ppathname, pb)
char *ppathname; /* project root directory pathname */
PATH *pb; /* pathname struct buffer */
{
char *ppathcat(); /* project pathname concatenation */
char *ppathhead(); /* remove tail of project pathname */
char pppathname[PPATHSIZE]; /* parent project pathname */
char *strcpy(); /* string copy */
int _closepdb(); /* close database without updating */
int closepdb(); /* close database */
int errpdb(); /* print database error */
int pputent(); /* write buffer to database */
int pstatus = 0; /* project status */
int rmpld(); /* remove project link directory */
int subprojects(); /* check for subprojects */
int xppath(); /* expand project pathname */
PATH *pd; /* pathname struct pointer */
PATH ppathbuf; /* parent project pathname struct buf */
PATH *readpld(); /* read project link directory entry */
PDB *openpdb(); /* open database */
PDB *pldp; /* project link directory stream */
void resetpdb(); /* reset current database pointer */
if (EQUAL(ppathname, CURPROJECT))
{
warn("%s: can't undefine current project", ppathname);
return(1);
}
if (FORCE)
{
if (*ppathname != _PDIRC && *ppathname != _HDIRC)
{
warn("%s must an absolute project pathname", ppathname);
return(1);
}
ppathhead(strcpy(pppathname, ppathname));
}
else {
ppathcat(pppathname, ppathname, PARENTPROJECT);
}
if (xppath(pppathname, &ppathbuf) == -1)
{
patherr("");
warn("force conversion by typing `rmproject -uF projectname'");
return(1);
}
if ((pldp = openpdb(PLDNAME, ppathbuf.p_path, "rw")) == NULL)
return(errpdb((PDB *) NULL));
while ((pd = readpld(pldp)) != NULL)
if (EQUAL(pb->p_alias, pd->p_alias))
{
pstatus = subprojects(pb->p_path);
if (pstatus == 1)
{
warn("can't undefine %s: project not empty",
ppathname);
resetpdb(pldp);
break;
}
else if (pstatus == 2)
{
warn("can't undefine %s because subprojects exist",
ppathname);
resetpdb(pldp);
break;
}
else if (pstatus == 3)
{
resetpdb(pldp);
break;
}
resetpdb(pldp);
}
else {
pputent(pldp);
}
if (pstatus != 0)
_closepdb(pldp);
else if ((pstatus = rmpld(pb->p_path)) != 0)
_closepdb(pldp);
else
pstatus = closepdb(pldp);
return(pstatus != 0);
}
/*
* warnexist() warns of nested or duplicate projects.
*/
warnexist(ppathname, alias)
char *ppathname; /* project to be removed */
char *alias; /* nested or duplicate project alias */
{
char npathname[PPATHSIZE]; /* nested project pathname */
char *p; /* nested project pathname pointer */
char *strpcpy(); /* string copy and update pointer */
p = strpcpy(npathname, ppathname);
while (p > npathname && p[-1] != _PPSC)
p--;
*p = '\0';
warn("can't remove %s because project %s%s exists", ppathname,
npathname, alias);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.