|
|
1.1 ! root 1: static char *rcsid = "$Header"; ! 2: /* ! 3: * mkproject - make a project root directory ! 4: * ! 5: * Author: Peter J. Nicklin ! 6: */ ! 7: #include <signal.h> ! 8: #include <stdio.h> ! 9: #include <sys/types.h> ! 10: #include <sys/stat.h> ! 11: #include "getarg.h" ! 12: #include "macro.h" ! 13: #include "null.h" ! 14: #include "path.h" ! 15: #include "pdb.h" ! 16: #include "pld.h" ! 17: #include "slist.h" ! 18: #include "spms.h" ! 19: #include "system.h" ! 20: #include "yesno.h" ! 21: ! 22: char CWD[PATHSIZE]; /* current working directory */ ! 23: char *CWP; /* current working project */ ! 24: char *PGN = "mkproject"; /* program name */ ! 25: int WANT_TO_EXIT = 0; /* advisory exit flag */ ! 26: ! 27: main(argc, argv) ! 28: int argc; ! 29: char **argv; ! 30: { ! 31: extern int PPDEBUG; /* project pathname debug flag */ ! 32: char *alias = NULL; /* alternative project directory name */ ! 33: char *getcwp(); /* get current working project */ ! 34: char *getwd(); /* get current working directory */ ! 35: int addtyp(); /* make project directory type labels */ ! 36: int chalias(); /* change project directory alias */ ! 37: int chdesc(); /* change project directory descrip */ ! 38: int isfg(); /* is process in foreground? */ ! 39: int minusdflag = YES; /* project directory description flag */ ! 40: int mkproject(); /* make a project root directory */ ! 41: int mustexist = 0; /* existing directories flag */ ! 42: int plusdflag = NO; /* project directory description flag */ ! 43: int typargtolist(); /* type labels -> pdirtyp list */ ! 44: int xppath(); /* expand project pathname */ ! 45: PATH pathbuf; /* pathname struct buffer */ ! 46: SLIST *pdirtyp; /* project directory type labels list */ ! 47: SLIST *slinit(); /* initialize singly-linked list */ ! 48: int onintr(); /* process signals */ ! 49: int status = 0; /* exit status */ ! 50: ! 51: pdirtyp = slinit(); ! 52: { ! 53: register char *s; /* option pointer */ ! 54: while (--argc > 0 && (**++argv == '-' || **argv == '+')) ! 55: { ! 56: if (**argv == '-') ! 57: { ! 58: for (s = argv[0]+1; *s != '\0'; s++) ! 59: switch (*s) ! 60: { ! 61: case 'D': ! 62: PPDEBUG = YES; ! 63: break; ! 64: case 'N': ! 65: alias = GETARG(s); ! 66: if (*alias == '\0') ! 67: status = 1; ! 68: goto endif; ! 69: case 'T': ! 70: if (typargtolist(GETARG(s),pdirtyp)==NO) ! 71: status = 1; ! 72: else if (*s == '\0') ! 73: status = 1; ! 74: goto endif; ! 75: case 'd': ! 76: minusdflag = NO; ! 77: break; ! 78: default: ! 79: warn("bad option -%c", *s); ! 80: status = 1; ! 81: goto endif; ! 82: } ! 83: } ! 84: else { ! 85: mustexist = 1; ! 86: for (s = argv[0]+1; *s != '\0'; s++) ! 87: switch (*s) ! 88: { ! 89: case 'N': ! 90: alias = GETARG(s); ! 91: if (*alias == '\0') ! 92: status = 1; ! 93: goto endif; ! 94: case 'T': ! 95: if (typargtolist(GETARG(s),pdirtyp)==NO) ! 96: status = 1; ! 97: else if (*s == '\0') ! 98: status = 1; ! 99: goto endif; ! 100: case 'd': ! 101: plusdflag = YES; ! 102: break; ! 103: default: ! 104: warn("bad option +%c", *s); ! 105: status = 1; ! 106: goto endif; ! 107: } ! 108: } ! 109: endif: continue; ! 110: } ! 111: if (status == 1 || argc < 1) ! 112: fatal("usage: mkproject [{+-}d] [{+-}N alias] %s", ! 113: "[{+-}T type[,type...]]\n projectname ..."); ! 114: } ! 115: ! 116: if (getwd(CWD) == NULL) ! 117: fatal("can't find current working directory"); ! 118: CWP = getcwp(); ! 119: if (isfg() == YES) ! 120: { ! 121: signal(SIGINT, onintr); ! 122: signal(SIGQUIT, onintr); ! 123: signal(SIGHUP, onintr); ! 124: } ! 125: ! 126: for (; argc > 0; argv++, argc--) ! 127: { ! 128: if (xppath(*argv, &pathbuf) == -1) ! 129: { ! 130: patherr(*argv); ! 131: status = 1; ! 132: continue; ! 133: } ! 134: if (CWP == NULL && (pathbuf.p_mode&P_IFMT) != P_IFHOME) ! 135: fatal("no project environment"); ! 136: if (mustexist) ! 137: switch (pathbuf.p_mode & P_IFMT) ! 138: { ! 139: case P_IFHOME: ! 140: case P_IFPROOT: ! 141: if (SLNUM(pdirtyp) > 0) ! 142: status |= addtyp(*argv, pdirtyp, ! 143: &pathbuf); ! 144: if (plusdflag == YES) ! 145: status |= chdesc(*argv, &pathbuf); ! 146: if (alias != NULL) ! 147: status |= chalias(*argv, alias, ! 148: &pathbuf); ! 149: break; ! 150: case P_IFPDIR: ! 151: warn("%s is a project directory", *argv); ! 152: status = 1; ! 153: break; ! 154: case P_IFNEW: ! 155: case P_IFREG: ! 156: warn("%s: no such project", *argv); ! 157: status = 1; ! 158: break; ! 159: } ! 160: else { ! 161: status |= mkproject(*argv, alias, pdirtyp, minusdflag, &pathbuf); ! 162: } ! 163: if (WANT_TO_EXIT) ! 164: exit(1); ! 165: } ! 166: exit(status); ! 167: } ! 168: ! 169: ! 170: ! 171: /* ! 172: * addtyp() adds type labels to an existing project directory. ! 173: */ ! 174: addtyp(ppathname, pdirtyp, pb) ! 175: char *ppathname; /* project directory pathname */ ! 176: SLIST *pdirtyp; /* project directory type labels list */ ! 177: PATH *pb; /* pathname struct buffer */ ! 178: { ! 179: char *pbfndkey(); /* find key */ ! 180: int closepdb(); /* close database */ ! 181: int errpdb(); /* print database error */ ! 182: int pgetent(); /* load next entry into buffer */ ! 183: int pputent(); /* write buffer to database */ ! 184: PDB *openpdb(); /* open database */ ! 185: PDB *pldp; /* project link directory stream */ ! 186: void pbaddtyp(); /* add type labels to buffer */ ! 187: ! 188: if ((pldp = openpdb(PLDNAME, pb->p_project, "rw")) == NULL) ! 189: return(errpdb((PDB *) NULL)); ! 190: while (pgetent(pldp) != EOF) ! 191: { ! 192: if (pbfndkey(CURPROJECT) != NULL) ! 193: pbaddtyp(ppathname, pdirtyp); ! 194: pputent(pldp); ! 195: } ! 196: return(closepdb(pldp)); ! 197: } ! 198: ! 199: ! 200: ! 201: /* ! 202: * badtyp() prints a bad format type label message. ! 203: */ ! 204: void ! 205: badtyp(type) ! 206: char *type; /* type label */ ! 207: { ! 208: warn("\"%s\" type label is badly formatted", type); ! 209: } ! 210: ! 211: ! 212: ! 213: /* ! 214: * chalias() changes an existing project directory alias. ! 215: */ ! 216: chalias(ppathname, newalias, pb) ! 217: char *ppathname; /* project directory pathname */ ! 218: char *newalias; /* new project directory alias */ ! 219: PATH *pb; /* pathname struct buffer */ ! 220: { ! 221: char *pbfndkey(); /* find key */ ! 222: char *ppathcat(); /* project pathname concatenation */ ! 223: char pppathname[PPATHSIZE]; /* parent project pathname */ ! 224: int _closepdb(); /* close database without updating */ ! 225: int closepdb(); /* close database */ ! 226: int errpdb(); /* print database error */ ! 227: int pbchgkey(); /* change existing key */ ! 228: int pgetent(); /* load next entry into buffer */ ! 229: int pputent(); /* write buffer to database */ ! 230: int xppath(); /* expand project pathname */ ! 231: PATH ppathbuf; /* parent pathname struct buffer */ ! 232: PDB *openpdb(); /* open database */ ! 233: PDB *pldp; /* project link directory stream */ ! 234: ! 235: ppathcat(pppathname, ppathname, PARENTPROJECT); ! 236: xppath(pppathname, &ppathbuf); ! 237: if ((pldp = openpdb(PLDNAME, ppathbuf.p_path, "rw")) == NULL) ! 238: return(errpdb((PDB *) NULL)); ! 239: while (pgetent(pldp) != EOF) ! 240: { ! 241: if (pbfndkey(newalias) != NULL) ! 242: { ! 243: warn("%s: %s exists", ppathname, newalias); ! 244: _closepdb(pldp); ! 245: return(1); ! 246: } ! 247: pbchgkey(pb->p_alias, newalias); ! 248: pputent(pldp); ! 249: } ! 250: return(closepdb(pldp)); ! 251: } ! 252: ! 253: ! 254: ! 255: /* ! 256: * chdesc() changes an existing project directory description. ! 257: */ ! 258: chdesc(ppathname, pb) ! 259: char *ppathname; /* project directory pathname */ ! 260: PATH *pb; /* pathname struct buffer */ ! 261: { ! 262: char *pbfndkey(); /* find key */ ! 263: int closepdb(); /* close database */ ! 264: int errpdb(); /* print database error */ ! 265: int pgetent(); /* load next entry into buffer */ ! 266: int pputent(); /* write buffer to database */ ! 267: PDB *openpdb(); /* open database */ ! 268: PDB *pldp; /* project link directory stream */ ! 269: void pbadddesc(); /* add project directory description */ ! 270: ! 271: if ((pldp = openpdb(PLDNAME, pb->p_project, "rw")) == NULL) ! 272: return(errpdb((PDB *) NULL)); ! 273: while (pgetent(pldp) != EOF) ! 274: { ! 275: if (pbfndkey(CURPROJECT) != NULL) ! 276: pbadddesc(ppathname); ! 277: pputent(pldp); ! 278: } ! 279: return(closepdb(pldp)); ! 280: } ! 281: ! 282: ! 283: ! 284: /* ! 285: * mkpld() creates a project link directory. If PLDNAME already exists, ! 286: * the database is altered accordingly. ! 287: */ ! 288: mkpld(pathname, ppathname, ptp, pdirtyp, dflag) ! 289: char *pathname; /* project root directory pathname */ ! 290: char *ppathname; /* project directory pathname */ ! 291: char *ptp; /* path to parent project */ ! 292: SLIST *pdirtyp; /* project directory type labels list */ ! 293: int dflag; /* project directory description flag */ ! 294: { ! 295: char *pathcat(); /* pathname concatenation */ ! 296: char *pbfndkey(); /* find key */ ! 297: char pldpath[PATHSIZE]; /* project link directory pathname */ ! 298: int closepdb(); /* close database */ ! 299: int errpdb(); /* print database error message */ ! 300: int pbaddflag(); /* add flag field */ ! 301: int pbaddkey(); /* add key */ ! 302: int pbaddstring(); /* add string field */ ! 303: int pgetent(); /* load database entry into buffer */ ! 304: int pputent(); /* write buffer to database */ ! 305: PDB *openpdb(); /* open database */ ! 306: PDB *pldp; /* project link directory stream */ ! 307: void pbclear(); /* clear buffer */ ! 308: void resetpdb(); /* reset current database pointer */ ! 309: void pbadddesc(); /* add project directory description */ ! 310: void pbaddtyp(); /* add type labels to buffer */ ! 311: ! 312: if (FILEXIST(pathcat(pldpath, pathname, PLDNAME))) ! 313: { ! 314: if ((pldp = openpdb(PLDNAME, pathname, "rw")) == NULL) ! 315: return(errpdb((PDB *) NULL)); ! 316: while (pgetent(pldp) != EOF) ! 317: { ! 318: if (pbfndkey(CURPROJECT) != NULL) ! 319: { ! 320: pbaddtyp(ppathname, pdirtyp); ! 321: if (dflag == YES) ! 322: pbadddesc(ppathname); ! 323: } ! 324: else if (pbfndkey(PARENTPROJECT) != NULL) ! 325: pbaddstring(PDIRPATH, ptp); ! 326: pputent(pldp); ! 327: } ! 328: } ! 329: else { ! 330: if ((pldp = openpdb(PLDNAME, pathname, "w")) == NULL) ! 331: return(errpdb((PDB *) NULL)); ! 332: ! 333: /* create current project entry */ ! 334: resetpdb(pldp); ! 335: pbclear(); ! 336: pbaddkey(CURPROJECT); ! 337: pbaddflag(PROOTDIR); ! 338: pbaddstring(PDIRPATH, CURDIR); ! 339: pbaddtyp(ppathname, pdirtyp); ! 340: if (dflag == YES) ! 341: pbadddesc(ppathname); ! 342: else ! 343: pbaddstring(PDIRDESC, ""); ! 344: pputent(pldp); ! 345: ! 346: /* create parent project entry */ ! 347: pbclear(); ! 348: pbaddkey(PARENTPROJECT); ! 349: pbaddflag(PROOTDIR); ! 350: pbaddstring(PDIRPATH, ptp); ! 351: pputent(pldp); ! 352: } ! 353: return(closepdb(pldp)); ! 354: } ! 355: ! 356: ! 357: ! 358: /* ! 359: * mkproject() makes a project root directory. ! 360: */ ! 361: mkproject(ppathname, alias, pdirtyp, dflag, pb) ! 362: char *ppathname; /* project root directory pathname */ ! 363: char *alias; /* alternative project directory name */ ! 364: int dflag; /* project directory description flag */ ! 365: SLIST *pdirtyp; /* project directory type labels list */ ! 366: PATH *pb; /* pathname struct buffer */ ! 367: { ! 368: char apathname[PATHSIZE]; /* absolute regular pathname */ ! 369: char *mkalias(); /* construct alias from pathname */ ! 370: char *mkptp(); /* make path to parent project */ ! 371: char *optpath(); /* optimize pathname */ ! 372: char *pathcat(); /* pathname concatenation */ ! 373: char *pbfndkey(); /* find database key */ ! 374: char *rdp; /* relative project directory path */ ! 375: char rpathname[PATHSIZE]; /* project root directory pathname */ ! 376: char *strcpy(); /* string copy */ ! 377: char *xorpath(); /* remove subpathname */ ! 378: int _closepdb(); /* close database without updating */ ! 379: int closepdb(); /* close database */ ! 380: int errpdb(); /* print database error message */ ! 381: int mkpld(); /* make project link directory */ ! 382: int mkrootproject(); /* make root project root directory */ ! 383: int pbaddflag(); /* add flag field */ ! 384: int pbaddkey(); /* add key */ ! 385: int pbaddstring(); /* add string field */ ! 386: int pgetent(); /* load next entry into buffer */ ! 387: int pputent(); /* write buffer to database */ ! 388: PDB *openpdb(); /* open database */ ! 389: PDB *pldp; /* project link directory stream */ ! 390: void pbadddesc(); /* add project directory description */ ! 391: void pbclear(); /* clear buffer */ ! 392: ! 393: switch (pb->p_mode & P_IFMT) ! 394: { ! 395: case P_IFNEW: ! 396: case P_IFREG: ! 397: break; ! 398: case P_IFHOME: ! 399: return(mkrootproject(ppathname, pdirtyp, dflag, pb)); ! 400: case P_IFPDIR: ! 401: case P_IFPROOT: ! 402: warn("%s exists", ppathname); ! 403: return(1); ! 404: } ! 405: ! 406: /* create pathname relative to project root directory */ ! 407: strcpy(rpathname, pb->p_project); ! 408: if (*pb->p_path == _RDIRC) ! 409: { ! 410: rdp = xorpath(rpathname, pb->p_path); ! 411: } ! 412: else { ! 413: optpath(pathcat(apathname, CWD, pb->p_path)); ! 414: rdp = xorpath(rpathname, apathname); ! 415: } ! 416: ! 417: /* open project link directory */ ! 418: if ((pldp = openpdb(PLDNAME, rpathname, "rw")) == NULL) ! 419: return(errpdb((PDB *) NULL)); ! 420: ! 421: /* ! 422: * check for existing aliases while preparing project link ! 423: * directory for new entry ! 424: */ ! 425: if (alias == NULL) ! 426: if (EQUAL(pb->p_alias, CURDIR) || EQUAL(pb->p_alias, PARENTDIR)) ! 427: alias = mkalias(rdp); ! 428: else ! 429: alias = pb->p_alias; ! 430: while (pgetent(pldp) != EOF) ! 431: { ! 432: if (pbfndkey(alias) != NULL) ! 433: { ! 434: warn("%s: %s exists", ppathname, alias); ! 435: _closepdb(pldp); ! 436: return(1); ! 437: } ! 438: pputent(pldp); ! 439: } ! 440: ! 441: /* make the directory if non-existent */ ! 442: if ((pb->p_mode & P_IFMT) == P_IFREG) ! 443: { ! 444: if ((pb->p_mode & S_IFMT) != S_IFDIR) ! 445: { ! 446: warn("%s: not a directory", ppathname); ! 447: _closepdb(pldp); ! 448: return(1); ! 449: } ! 450: } ! 451: else if (MK_DIR(pb->p_path) != 0) ! 452: { ! 453: _closepdb(pldp); ! 454: return(1); ! 455: } ! 456: ! 457: /* update database */ ! 458: pbclear(); ! 459: pbaddkey(alias); ! 460: pbaddflag(PROOTDIR); ! 461: pbaddstring(PDIRPATH, rdp); ! 462: pputent(pldp); ! 463: if (mkpld(pb->p_path, ppathname, mkptp(rpathname, rdp), pdirtyp, dflag) != 0) ! 464: { ! 465: _closepdb(pldp); ! 466: return(1); ! 467: } ! 468: return(closepdb(pldp)); ! 469: } ! 470: ! 471: ! 472: ! 473: /* ! 474: * mkptp() returns a pathname to the parent project root directory. ! 475: * It attempts to create a relative pathname if possible, otherwise ! 476: * the parent root directory pathname is used. ! 477: */ ! 478: char * ! 479: mkptp(rpathname, rdp) ! 480: char *rpathname; /* parent project root directory */ ! 481: register char *rdp; /* pathname to project being created */ ! 482: { ! 483: register char *rp; /* parent project root directory ptr */ ! 484: char *strpcpy(); /* string copy and update pointer */ ! 485: ! 486: if (*rdp == _RDIRC) ! 487: return(rpathname); ! 488: for(rp = rpathname; *rdp != '\0'; rdp++) ! 489: if (*rdp == _PSC) ! 490: rp = strpcpy(strpcpy(rp, PARENTDIR), PATHSEP); ! 491: rp = strpcpy(rp, PARENTDIR); ! 492: return(rpathname); ! 493: } ! 494: ! 495: ! 496: ! 497: /* ! 498: * mkrootproject creates a project link directory in the user's home ! 499: * directory. Returns zero if successful, otherwise 1. ! 500: */ ! 501: mkrootproject(ppathname, pdirtyp, dflag, pb) ! 502: char *ppathname; /* project pathname */ ! 503: SLIST *pdirtyp; /* project directory type labels list */ ! 504: int dflag; /* project directory description flag */ ! 505: PATH *pb; /* pathname struct buffer */ ! 506: { ! 507: char *pathcat(); /* pathname concatenation */ ! 508: char pldpath[PATHSIZE]; /* project link directory pathname */ ! 509: int mkpld(); /* make a project link directory */ ! 510: ! 511: if (FILEXIST(pathcat(pldpath, pb->p_path, PLDNAME))) ! 512: { ! 513: warn("%s exists", ppathname); ! 514: return(1); ! 515: } ! 516: return(mkpld(pb->p_path, ROOTPROJECT, CURDIR, pdirtyp, dflag)); ! 517: } ! 518: ! 519: ! 520: ! 521: /* ! 522: * onintr() resets interrupt, quit, and hangup signals, and sets a flag ! 523: * which advises the process to exit at the first opportunity. ! 524: */ ! 525: onintr() ! 526: { ! 527: signal(SIGINT, onintr); ! 528: signal(SIGQUIT, onintr); ! 529: signal(SIGHUP, onintr); ! 530: ! 531: WANT_TO_EXIT = 1; ! 532: } ! 533: ! 534: ! 535: ! 536: /* ! 537: * pbadddesc() fetchs a project directory description from stdin and ! 538: * adds to database buffer. ! 539: */ ! 540: void ! 541: pbadddesc(ppathname) ! 542: char *ppathname; /* project directory pathname */ ! 543: { ! 544: char dirdesc[DIRDESCSIZE]; /* project directory description */ ! 545: char *gets(); /* get a line from stdin */ ! 546: int pbaddstring(); /* add string field */ ! 547: ! 548: printf("%s: description? (1 line): ", ppathname); ! 549: gets(dirdesc); ! 550: pbaddstring(PDIRDESC, dirdesc); ! 551: } ! 552: ! 553: ! 554: ! 555: ! 556: /* ! 557: * pbaddtyp() adds type labels to database buffer. ! 558: */ ! 559: void ! 560: pbaddtyp(ppathname, typlist) ! 561: char *ppathname; /* project pathname */ ! 562: SLIST *typlist; /* type labels list */ ! 563: { ! 564: char *pbgetstring(); /* get specified string field */ ! 565: char *pdtfind(); /* find type label in buffer */ ! 566: char *pfxcpy(); /* copy string prefix */ ! 567: char *slget(); /* get next key from list */ ! 568: char *tp; /* pointer to type label */ ! 569: char type[TYPESIZE]; /* type label buffer */ ! 570: char typbuf[TYPBUFSIZE]; /* project directory types buffer */ ! 571: int pbaddstring(); /* add string field */ ! 572: void pdtinsert(); /* insert type label */ ! 573: void slrewind(); /* rewind list */ ! 574: ! 575: pbgetstring(PDIRTYPE, typbuf); ! 576: slrewind(typlist); ! 577: while ((tp = slget(typlist)) != NULL) ! 578: { ! 579: if (pdtfind(pfxcpy(type, tp), typbuf) == NULL) ! 580: pdtinsert(tp, typbuf); ! 581: else ! 582: warn("%s: \"%s\" type label exists", ppathname, type); ! 583: } ! 584: pbaddstring(PDIRTYPE, typbuf); ! 585: } ! 586: ! 587: ! 588: ! 589: /* ! 590: * typargtolist() prepends comma-separated type labels specified in typarg ! 591: * to typlist. Returns NO if type labels are badly formatted, otherwise ! 592: * YES. ! 593: */ ! 594: typargtolist(typarg, typlist) ! 595: register char *typarg; /* type labels argument */ ! 596: SLIST *typlist; /* type labels list */ ! 597: { ! 598: register char *t; /* type label argument pointer */ ! 599: char *slprepend(); /* prepend singly-linked list key */ ! 600: int ispdt(); /* is project dir type label legal? */ ! 601: int status = YES; /* return status */ ! 602: void badtyp(); /* print bad type label message */ ! 603: ! 604: for (t = typarg; *t != '\0'; t++) ! 605: continue; ! 606: for (; t >= typarg; t--) ! 607: if (t[0] == ',') ! 608: { ! 609: if (t[1] != '\0') ! 610: if (ispdt(t+1)) ! 611: slprepend(t+1, typlist); ! 612: else { ! 613: badtyp(t+1); ! 614: status = NO; ! 615: } ! 616: t[0] = '\0'; ! 617: } ! 618: if (ispdt(typarg)) ! 619: slprepend(typarg, typlist); ! 620: else { ! 621: badtyp(typarg); ! 622: status = NO; ! 623: } ! 624: return(status); ! 625: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.