static char *rcsid = "$Header$"; /* * prmdir - remove a project directory * * Author: Peter J. Nicklin */ #include #include #include #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 *RMFLAG = ""; /* rm "-f" flag */ char *PGN = "prmdir"; /* program name */ 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 rmpdir(); /* remove a project directory */ int rmtyp(); /* remove project dir type labels */ int unpdir(); /* undefine project directory */ int status = 0; /* exit status */ 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 '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: prmdir [-fru] [-T type[,type...]] pdirname ..."); if ((CWP = getcwp()) == NULL) fatal("no project environment"); if (getwd(CWD) == NULL) fatal("can't find current working directory"); if (isfg() == YES) { signal(SIGHUP, onintr); signal(SIGINT, onintr); signal(SIGQUIT, onintr); } for (; argc > 0; ++argv, --argc) { if (xppath(*argv, &pathbuf) == -1) { patherr(*argv); status = 1; continue; } switch (pathbuf.p_mode & P_IFMT) { case P_IFPDIR: if (SLNUM(pdirtyp) > 0) status |= rmtyp(*argv, pdirtyp, &pathbuf); else if (UNDEFINE) status |= unpdir(&pathbuf); else status |= rmpdir(*argv, &pathbuf); break; case P_IFHOME: case P_IFPROOT: warn("%s is a project root directory", *argv); status = 1; break; case P_IFNEW: case P_IFREG: warn("%s: no such project directory", *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. */ rmd(pathname) char *pathname; /* full pathname of directory */ { char cmdbuf[PATHSIZE+9]; /* command buffer */ char *sprintf(); /* print output to string */ int status; /* return status */ int yes(); /* is reply yes? */ 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 { status = RM_DIR(pathname); } return(status); } /* * rmpdir() removes a project directory. Returns 0 is successful, otherwise 1. */ rmpdir(ppathname, pb) char *ppathname; /* project directory pathname */ PATH *pb; /* pathname struct buffer */ { 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 status = 0; /* return status */ int strlen(); /* string length */ int strncmp(); /* compare n characters */ PATH *pd; /* pathname struct pointer */ PATH *readpld(); /* read project link directory entry */ PDB *openpdb(); /* open database */ PDB *pldp; /* project link directory stream */ 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 ((pldp = openpdb(PLDNAME, pb->p_project, "rw")) == NULL) return(errpdb((PDB *) NULL)); while ((pd = readpld(pldp)) != NULL) if (EQUAL(pb->p_alias, pd->p_alias)) continue; /* the directory itself */ else if (strncmp(pb->p_path, pd->p_path, plen) == 0) { /* nest project directories */ if (pd->p_mode == P_IFPROOT) { /* don't clobber projects */ warn("can't remove %s because project %s exists", ppathname, pd->p_path); status = 1; break; } } else { pputent(pldp); } if (status == 1) _closepdb(pldp); else { if ((status = rmd(pb->p_path)) != 0) _closepdb(pldp); else status = closepdb(pldp); } return(status); } /* * 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(pb->p_alias) != NULL) pbrmtyp(ppathname, pdirtyp); pputent(pldp); } status = 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); } /* * unpdir() undefines a project directory. Returns 0 is successful, otherwise 1. */ unpdir(pb) PATH *pb; /* pathname struct buffer */ { int closepdb(); /* close database */ int errpdb(); /* print database error */ int pputent(); /* write buffer to database */ PATH *pd; /* pathname struct pointer */ PATH *readpld(); /* read project link directory entry */ PDB *openpdb(); /* open database */ PDB *pldp; /* project link directory stream */ if ((pldp = openpdb(PLDNAME, pb->p_project, "rw")) == NULL) return(errpdb((PDB *) NULL)); while ((pd = readpld(pldp)) != NULL) if (EQUAL(pb->p_alias, pd->p_alias)) continue; else pputent(pldp); return(closepdb(pldp)); }