Annotation of 43BSD/contrib/spms/src/bin/rmproject/rmproject.c, revision 1.1.1.1

1.1       root        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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.