Annotation of 43BSD/contrib/spms/src/bin/rmproject/rmproject.c, revision 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.