1: static char *rcsid = "$Header$";
   2: /*
   3:  * rmproject - remove a project root directory
   4:  *
   5:  * Author: Peter J. Nicklin
   6:  */
   7: #include <sys/param.h>
   8: #include <signal.h>
   9: #include <stdio.h>
  10: #include "getarg.h"
  11: #include "macro.h"
  12: #include "null.h"
  13: #include "path.h"
  14: #include "pdb.h"
  15: #include "pld.h"
  16: #include "slist.h"
  17: #include "spms.h"
  18: #include "system.h"
  19: #include "yesno.h"
  20: 
  21: char CWD[PATHSIZE];         /* current working directory */
  22: char *CWP;              /* current working project */
  23: char *PGN = "rmproject";        /* program name */
  24: char *RMFLAG = "";          /* rm "-f" flag */
  25: int FORCE = 0;              /* brute force remove or undefine */
  26: int RECURSIVE = 0;          /* remove project dirs recursively */
  27: int UNDEFINE = 0;           /* remove proj dir definitions only */
  28: int WANT_TO_EXIT = 0;           /* advisory exit flag */
  29: 
  30: main(argc, argv)
  31:     int argc;
  32:     char **argv;
  33: {
  34:     extern int PPDEBUG;     /* project pathname debug flag */
  35:     char *getcwp();         /* get current working project */
  36:     char *getwd();          /* get current working directory */
  37:     int isfg();         /* is process in foreground? */
  38:     int onintr();           /* process signals */
  39:     int rmproject();        /* remove a project root directory */
  40:     int rmtyp();            /* remove project dir type labels */
  41:     int status = 0;         /* exit status */
  42:     int unproject();        /* undefine project root directory */
  43:     int xppath();           /* expand project pathname */
  44:     PATH pathbuf;           /* pathname struct buffer */
  45:     SLIST *pdirtyp;         /* project directory type labels list */
  46:     SLIST *slinit();        /* initialize singly-linked list */
  47:     void typargtolist();        /* type labels -> pdirtyp list */
  48: 
  49:     pdirtyp = slinit();
  50:     {
  51:     register char *s;       /* option pointer */
  52:     while (--argc > 0 && **++argv == '-')
  53:         {
  54:         for (s = argv[0]+1; *s != '\0'; s++)
  55:             switch (*s)
  56:                 {
  57:                 case 'D':
  58:                     PPDEBUG = YES;
  59:                     break;
  60:                 case 'F':
  61:                     /*
  62: 					 * 'F' option is mentioned in
  63: 					 * rmproject() and unproject()
  64: 					 */
  65:                     FORCE++;
  66:                     break;
  67:                 case 'T':
  68:                     typargtolist(GETARG(s), pdirtyp);
  69:                     if (*s == '\0')
  70:                         status = 1;
  71:                     goto endfor;
  72:                 case 'f':
  73:                     RMFLAG = "-f";
  74:                     break;
  75:                 case 'r':
  76:                     RECURSIVE++;
  77:                     break;
  78:                 case 'u':
  79:                     UNDEFINE++;
  80:                     break;
  81:                 default:
  82:                     warn("bad option -%c", *s);
  83:                     status = 1;
  84:                     goto endfor;
  85:                 }
  86:         endfor: continue;
  87:         }
  88:     }
  89:     if (status == 1 || argc < 1)
  90:         fatal("usage: rmproject [-fru] [-T type[,type...]] projectname ...");
  91: 
  92:     if ((CWP = getcwp()) == NULL)
  93:         fatal("no project environment");
  94:     if (getwd(CWD) == NULL)
  95:         fatal("can't find current working directory");
  96:     if (isfg() == YES)
  97:         {
  98:         signal(SIGINT, onintr);
  99:         signal(SIGQUIT, onintr);
 100:         signal(SIGHUP, onintr);
 101:         }
 102: 
 103:     for (; argc > 0; ++argv, --argc)
 104:         {
 105:         if (xppath(*argv, &pathbuf) == -1)
 106:             {
 107:             patherr(*argv);
 108:             status = 1;
 109:             continue;
 110:             }
 111:         switch (pathbuf.p_mode & P_IFMT)
 112:             {
 113:             case P_IFHOME:
 114:             case P_IFPROOT:
 115:                 if (SLNUM(pdirtyp) > 0)
 116:                     status |= rmtyp(*argv, pdirtyp, &pathbuf);
 117:                 else if (UNDEFINE)
 118:                     status |= unproject(*argv, &pathbuf);
 119:                 else
 120:                     status |= rmproject(*argv, &pathbuf);
 121:                 break;
 122:             case P_IFPDIR:
 123:                 warn("%s is a project directory", *argv);
 124:                 status = 1;
 125:                 break;
 126:             case P_IFNEW:
 127:             case P_IFREG:
 128:                 warn("%s: no such project", *argv);
 129:                 status = 1;
 130:                 break;
 131:             }
 132:         if (WANT_TO_EXIT)
 133:             exit(1);
 134:         }
 135:     exit(status);
 136: }
 137: 
 138: 
 139: 
 140: /*
 141:  * onintr() resets interrupt, quit, and hangup signals, and sets a flag
 142:  * which advises the process to exit at the first opportunity.
 143:  */
 144: onintr()
 145: {
 146:     signal(SIGINT, onintr);
 147:     signal(SIGQUIT, onintr);
 148:     signal(SIGHUP, onintr);
 149: 
 150:     WANT_TO_EXIT = 1;
 151: }
 152: 
 153: 
 154: 
 155: /*
 156:  * pbrmtyp() removes type labels from database buffer.
 157:  */
 158: void
 159: pbrmtyp(ppathname, typlist)
 160:     char *ppathname;        /* project pathname */
 161:     SLIST *typlist;         /* type labels list */
 162: {
 163:     char *pbgetstring();        /* get specified string field */
 164:     char *pdtfind();        /* find type label in buffer */
 165:     char *slget();          /* get next key from list */
 166:     char *tp;           /* pointer to type label */
 167:     char typbuf[TYPBUFSIZE];    /* project directory types buffer */
 168:     int pbaddstring();      /* add string field */
 169:     int strlen();           /* string length */
 170:     void slrewind();        /* rewind list */
 171:     void pdtrm();           /* remove type label */
 172: 
 173:     pbgetstring(PDIRTYPE, typbuf);
 174:     slrewind(typlist);
 175:     while ((tp = slget(typlist)) != NULL)
 176:         {
 177:         if (pdtfind(tp, typbuf) != NULL)
 178:             pdtrm(tp, typbuf);
 179:         else
 180:             warn("%s: \"%s\" type label not found", ppathname, tp);
 181:         }
 182:     pbaddstring(PDIRTYPE, typbuf);
 183: }
 184: 
 185: 
 186: 
 187: /*
 188:  * rmd() removes a project directory. rmd() returns the status of the rm
 189:  * command or 1 if the user decides not to remove a project directory.
 190:  * Before removing a directory the project link directory is moved to
 191:  * safe place. If the directory is removed successfully, the project link
 192:  * directory is removed.
 193:  */
 194: rmd(pathname)
 195:     char *pathname;         /* full pathname of directory */
 196: {
 197:     char cmdbuf[PATHSIZE+9];    /* command buffer */
 198:     int rmpld();            /* remove project link directory */
 199:     int savepld();          /* save project link directory */
 200:     int status;         /* return status */
 201:     int yes();          /* is reply yes? */
 202:     void restorpld();       /* restore project link directory */
 203:     void unsavepld();       /* remove saved project link dir */
 204: 
 205:     if (RECURSIVE)
 206:         {
 207:         sprintf(cmdbuf, "rm %s -r %s", RMFLAG, pathname);
 208:         printf("%s? [yn](n): ", cmdbuf);
 209:         if (!yes())
 210:             return(1);
 211:         status = system(cmdbuf);
 212:         status >>= NBBY;
 213:         status &= 0xff;
 214:         }
 215:     else    {
 216:         if ((status = savepld(pathname)) == 0)
 217:             if ((status = rmpld(pathname)) == 0)
 218:                 if ((status = RM_DIR(pathname)) != 0)
 219:                     restorpld(pathname);
 220:                 else
 221:                     unsavepld();
 222:         }
 223:     return(status);
 224: }
 225: 
 226: 
 227: 
 228: /*
 229:  * rmpld() removes a project link directory. Returns 1 if file not
 230:  * removed, otherwise zero.
 231:  */
 232: rmpld(pathname)
 233:     char *pathname;         /* project root directory pathname */
 234: {
 235:     char *pathcat();        /* pathname concatenation */
 236:     char pldpathname[PATHSIZE]; /* project link directory pathname */
 237: 
 238:     if (unlink(pathcat(pldpathname, pathname, PLDNAME)) != 0)
 239:         if (!FORCE)
 240:             {
 241:             pperror(pldpathname);
 242:             return(1);
 243:             }
 244:     return(0);
 245: }
 246: 
 247: 
 248: 
 249: /*
 250:  * rmproject() removes a project root directory. Returns 0 is successful,
 251:  * otherwise 1.
 252:  */
 253: rmproject(ppathname, pb)
 254:     char *ppathname;        /* project root directory pathname */
 255:     PATH *pb;           /* pathname struct buffer */
 256: {
 257:     char *ppathcat();       /* project pathname concatenation */
 258:     char *ppathhead();      /* remove tail of project pathname */
 259:     char pppathname[PPATHSIZE]; /* parent project pathname */
 260:     char *strcpy();         /* string copy */
 261:     int _closepdb();        /* close database without updating */
 262:     int closepdb();         /* close database */
 263:     int errpdb();           /* print database error */
 264:     int plen;           /* length of regular pathname */
 265:     int pputent();          /* write buffer to database */
 266:     int pstatus = 0;        /* project status */
 267:     int strlen();           /* string length */
 268:     int strncmp();          /* compare n characters */
 269:     int subprojects();      /* check for subprojects */
 270:     int xppath();           /* expand project pathname */
 271:     PATH *pd;           /* pathname struct pointer */
 272:     PATH ppathbuf;          /* parent project pathname struct buf */
 273:     PATH *readpld();        /* read project link directory entry */
 274:     PDB *openpdb();         /* open database */
 275:     PDB *pldp;          /* project link directory stream */
 276:     void resetpdb();        /* reset current database pointer */
 277: 
 278:     if (EQUAL(ppathname, CURPROJECT))
 279:         {
 280:         warn("%s: can't remove current project", ppathname);
 281:         return(1);
 282:         }
 283:     plen = strlen(pb->p_path);
 284:     if (strncmp(pb->p_path, CWD, plen) == 0)
 285:         {
 286:         warn("can't remove %s from current directory", ppathname);
 287:         return(1);
 288:         }
 289:     if (FORCE)
 290:         {
 291:         if (*ppathname != _PDIRC && *ppathname != _HDIRC)
 292:             {
 293:             warn("%s must an absolute project pathname", ppathname);
 294:             return(1);
 295:             }
 296:         ppathhead(strcpy(pppathname, ppathname));
 297:         }
 298:     else    {
 299:         ppathcat(pppathname, ppathname, PARENTPROJECT);
 300:         }
 301:     if (xppath(pppathname, &ppathbuf) == -1)
 302:         {
 303:         patherr("");
 304:         warn("force removal by typing `rmproject -F projectname'");
 305:         return(1);
 306:         }
 307:     if ((pldp = openpdb(PLDNAME, ppathbuf.p_path, "rw")) == NULL)
 308:         return(errpdb((PDB *) NULL));
 309:     while ((pd = readpld(pldp)) != NULL)
 310:         if (EQUAL(pb->p_alias, pd->p_alias))
 311:             {
 312:             pstatus = subprojects(pb->p_path);
 313:             if (pstatus == 1)
 314:                 {
 315:                 warn("%s: project not empty", ppathname);
 316:                 resetpdb(pldp);
 317:                 break;
 318:                 }
 319:             else if (pstatus == 2)
 320:                 {
 321:                 warn("can't remove %s because subprojects exist",
 322:                      ppathname);
 323:                 resetpdb(pldp);
 324:                 break;
 325:                 }
 326:             else if (pstatus == 3)
 327:                 {
 328:                 resetpdb(pldp);
 329:                 break;
 330:                 }
 331:             resetpdb(pldp);
 332:             }
 333:         else if (strncmp(pb->p_path, pd->p_path, plen) == 0)
 334:             {       /* don't clobber nested projects */
 335:             if (pd->p_mode == P_IFPROOT)
 336:                 {
 337:                 warnexist(ppathname, pd->p_alias);
 338:                 pstatus = 4;
 339:                 break;
 340:                 }
 341:             }
 342:         else    {
 343:             pputent(pldp);
 344:             }
 345:     if (pstatus != 0)
 346:         _closepdb(pldp);
 347:     else if ((pstatus = rmd(pb->p_path)) != 0)
 348:         _closepdb(pldp);
 349:     else
 350:         pstatus = closepdb(pldp);
 351:     return(pstatus != 0);
 352: }
 353: 
 354: 
 355: 
 356: /*
 357:  * rmtyp() removes type labels from an existing project directory.
 358:  */
 359: rmtyp(ppathname, pdirtyp, pb)
 360:     char *ppathname;        /* project directory pathname */
 361:     SLIST *pdirtyp;         /* project directory type labels list */
 362:     PATH *pb;           /* pathname struct buffer */
 363: {
 364:     char *pbfndkey();       /* find key */
 365:     int closepdb();         /* close database */
 366:     int errpdb();           /* print database error */
 367:     int pgetent();          /* load next entry into buffer */
 368:     int pputent();          /* write buffer to database */
 369:     int status = 0;         /* return status */
 370:     PDB *openpdb();         /* open database */
 371:     PDB *pldp;          /* project link directory stream */
 372:     void pbrmtyp();         /* remove type labels from buffer */
 373: 
 374:     if ((pldp = openpdb(PLDNAME, pb->p_project, "rw")) == NULL)
 375:         return(errpdb((PDB *) NULL));
 376:     while (pgetent(pldp) != EOF)
 377:         {
 378:         if (pbfndkey(CURPROJECT) != NULL)
 379:             pbrmtyp(ppathname, pdirtyp);
 380:         pputent(pldp);
 381:         }
 382:     status = closepdb(pldp);
 383:     return(status);
 384: }
 385: 
 386: 
 387: 
 388: /*
 389:  * subprojects() returns 1 if a project has project directories, 2 if any
 390:  * of these are subprojects, and zero otherwise.
 391:  */
 392: subprojects(pathname)
 393:     char *pathname;         /* project root directory pathname */
 394: {
 395:     char *pbfndkey();       /* find key */
 396:     int closepdb();         /* close database */
 397:     int errpdb();           /* print database error */
 398:     int pbfndflag();        /* find flag field */
 399:     int pgetent();          /* load next entry into buffer */
 400:     int status = 0;         /* return status */
 401:     PDB *openpdb();         /* open database */
 402:     PDB *pldp;          /* project link directory stream */
 403: 
 404:     if ((pldp = openpdb(PLDNAME, pathname, "r")) == NULL)
 405:         {
 406:         if (!FORCE) return(errpdb((PDB *) NULL));
 407:         return(status);
 408:         }
 409:     while (pgetent(pldp) != EOF)
 410:         if (pbfndkey(CURPROJECT) == NULL &&
 411:             pbfndkey(PARENTPROJECT) == NULL)
 412:             {
 413:             if (!RECURSIVE) status = 1;
 414:             if (pbfndflag(PROOTDIR) == YES)
 415:                 {
 416:                 status = 2;
 417:                 break;
 418:                 }
 419:             }
 420:     closepdb(pldp);
 421:     return(status);
 422: }
 423: 
 424: 
 425: 
 426: /*
 427:  * typargtolist() prepends comma-separated type labels specified in typarg
 428:  * to typlist.
 429:  */
 430: void
 431: typargtolist(typarg, typlist)
 432:     register char *typarg;      /* type labels argument */
 433:     SLIST *typlist;         /* type labels list */
 434: {
 435:     register char *t;       /* type label argument pointer */
 436:     char *slprepend();      /* prepend singly-linked list key */
 437: 
 438:     for (t = typarg; *t != '\0'; t++)
 439:         continue;
 440:     for (; t >= typarg; t--)
 441:         if (t[0] == ',')
 442:             {
 443:             if (t[1] != '\0')
 444:                 slprepend(t+1, typlist);
 445:             t[0] = '\0';
 446:             }
 447:     slprepend(typarg, typlist);
 448: }
 449: 
 450: 
 451: 
 452: /*
 453:  * unproject() undefines a project root directory. Returns 0 is successful,
 454:  * otherwise 1.
 455:  */
 456: unproject(ppathname, pb)
 457:     char *ppathname;        /* project root directory pathname */
 458:     PATH *pb;           /* pathname struct buffer */
 459: {
 460:     char *ppathcat();       /* project pathname concatenation */
 461:     char *ppathhead();      /* remove tail of project pathname */
 462:     char pppathname[PPATHSIZE]; /* parent project pathname */
 463:     char *strcpy();         /* string copy */
 464:     int _closepdb();        /* close database without updating */
 465:     int closepdb();         /* close database */
 466:     int errpdb();           /* print database error */
 467:     int pputent();          /* write buffer to database */
 468:     int pstatus = 0;        /* project status */
 469:     int rmpld();            /* remove project link directory */
 470:     int subprojects();      /* check for subprojects */
 471:     int xppath();           /* expand project pathname */
 472:     PATH *pd;           /* pathname struct pointer */
 473:     PATH ppathbuf;          /* parent project pathname struct buf */
 474:     PATH *readpld();        /* read project link directory entry */
 475:     PDB *openpdb();         /* open database */
 476:     PDB *pldp;          /* project link directory stream */
 477:     void resetpdb();        /* reset current database pointer */
 478: 
 479:     if (EQUAL(ppathname, CURPROJECT))
 480:         {
 481:         warn("%s: can't undefine current project", ppathname);
 482:         return(1);
 483:         }
 484:     if (FORCE)
 485:         {
 486:         if (*ppathname != _PDIRC && *ppathname != _HDIRC)
 487:             {
 488:             warn("%s must an absolute project pathname", ppathname);
 489:             return(1);
 490:             }
 491:         ppathhead(strcpy(pppathname, ppathname));
 492:         }
 493:     else    {
 494:         ppathcat(pppathname, ppathname, PARENTPROJECT);
 495:         }
 496:     if (xppath(pppathname, &ppathbuf) == -1)
 497:         {
 498:         patherr("");
 499:         warn("force conversion by typing `rmproject -uF projectname'");
 500:         return(1);
 501:         }
 502:     if ((pldp = openpdb(PLDNAME, ppathbuf.p_path, "rw")) == NULL)
 503:         return(errpdb((PDB *) NULL));
 504:     while ((pd = readpld(pldp)) != NULL)
 505:         if (EQUAL(pb->p_alias, pd->p_alias))
 506:             {
 507:             pstatus = subprojects(pb->p_path);
 508:             if (pstatus == 1)
 509:                 {
 510:                 warn("can't undefine %s: project not empty",
 511:                      ppathname);
 512:                 resetpdb(pldp);
 513:                 break;
 514:                 }
 515:             else if (pstatus == 2)
 516:                 {
 517:                 warn("can't undefine %s because subprojects exist",
 518:                      ppathname);
 519:                 resetpdb(pldp);
 520:                 break;
 521:                 }
 522:             else if (pstatus == 3)
 523:                 {
 524:                 resetpdb(pldp);
 525:                 break;
 526:                 }
 527:             resetpdb(pldp);
 528:             }
 529:         else    {
 530:             pputent(pldp);
 531:             }
 532:     if (pstatus != 0)
 533:         _closepdb(pldp);
 534:     else if ((pstatus = rmpld(pb->p_path)) != 0)
 535:         _closepdb(pldp);
 536:     else
 537:         pstatus = closepdb(pldp);
 538:     return(pstatus != 0);
 539: }
 540: 
 541: 
 542: 
 543: /*
 544:  * warnexist() warns of nested or duplicate projects.
 545:  */
 546: warnexist(ppathname, alias)
 547:     char *ppathname;        /* project to be removed */
 548:     char *alias;            /* nested or duplicate project alias */
 549: {
 550:     char npathname[PPATHSIZE];  /* nested project pathname */
 551:     char *p;            /* nested project pathname pointer */
 552:     char *strpcpy();        /* string copy and update pointer */
 553: 
 554:     p = strpcpy(npathname, ppathname);
 555:     while (p > npathname && p[-1] != _PPSC)
 556:         p--;
 557:     *p = '\0';
 558:     warn("can't remove %s because project %s%s exists", ppathname,
 559:          npathname, alias);
 560: }

Defined functions

main defined in line 30; never used
onintr defined in line 144; used 7 times
pbrmtyp defined in line 158; used 2 times
rmd defined in line 194; used 1 times
rmpld defined in line 232; used 4 times
rmproject defined in line 253; used 2 times
rmtyp defined in line 359; used 2 times
subprojects defined in line 392; used 4 times
typargtolist defined in line 430; used 2 times
unproject defined in line 456; used 2 times
warnexist defined in line 546; used 1 times

Defined variables

CWD defined in line 21; used 2 times
CWP defined in line 22; used 1 times
  • in line 92
FORCE defined in line 25; used 8 times
PGN defined in line 23; never used
RECURSIVE defined in line 26; used 3 times
RMFLAG defined in line 24; used 2 times
UNDEFINE defined in line 27; used 2 times
WANT_TO_EXIT defined in line 28; used 2 times
rcsid defined in line 1; never used
Last modified: 1985-07-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2062
Valid CSS Valid XHTML 1.0 Strict