|
|
1.1 ! root 1: static char *rcsid = "$Header$"; ! 2: /* ! 3: * pmkdir - make a project 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 "system.h" ! 19: #include "yesno.h" ! 20: ! 21: char CWD[PATHSIZE]; /* current working directory */ ! 22: char *CWP; /* current working project */ ! 23: char *PGN = "pmkdir"; /* program name */ ! 24: int WANT_TO_EXIT = 0; /* advisory exit flag */ ! 25: ! 26: main(argc, argv) ! 27: int argc; ! 28: char **argv; ! 29: { ! 30: extern int PPDEBUG; /* project pathname debug flag */ ! 31: char *alias = NULL; /* alternative project directory name */ ! 32: char *getcwp(); /* get current working project */ ! 33: char *getwd(); /* get current working directory */ ! 34: int addtyp(); /* make project directory type labels */ ! 35: int chalias(); /* change project directory alias */ ! 36: int chdesc(); /* change project directory descrip */ ! 37: int isfg(); /* is process in foreground? */ ! 38: int minusdflag = YES; /* project directory description flag */ ! 39: int mkpdir(); /* make a project directory */ ! 40: int mustexist = 0; /* existing directories flag */ ! 41: int onintr(); /* process signals */ ! 42: int plusdflag = NO; /* project directory description flag */ ! 43: int status = 0; /* exit status */ ! 44: int typargtolist(); /* type labels -> pdirtyp list */ ! 45: int xppath(); /* expand project pathname */ ! 46: PATH pathbuf; /* pathname struct buffer */ ! 47: SLIST *pdirtyp; /* project directory type labels list */ ! 48: SLIST *slinit(); /* initialize singly-linked list */ ! 49: ! 50: pdirtyp = slinit(); ! 51: { ! 52: register char *s; /* option pointer */ ! 53: while (--argc > 0 && (**++argv == '-' || **argv == '+')) ! 54: { ! 55: if (**argv == '-') ! 56: { ! 57: for (s = argv[0]+1; *s != '\0'; s++) ! 58: switch (*s) ! 59: { ! 60: case 'D': ! 61: PPDEBUG = YES; ! 62: break; ! 63: case 'N': ! 64: alias = GETARG(s); ! 65: if (*alias == '\0') ! 66: status = 1; ! 67: goto endif; ! 68: case 'T': ! 69: if (typargtolist(GETARG(s),pdirtyp)==NO) ! 70: status = 1; ! 71: else if (*s == '\0') ! 72: status = 1; ! 73: goto endif; ! 74: case 'd': ! 75: minusdflag = NO; ! 76: break; ! 77: default: ! 78: warn("bad option -%c", *s); ! 79: status = 1; ! 80: goto endif; ! 81: } ! 82: } ! 83: else { ! 84: mustexist = 1; ! 85: for (s = argv[0]+1; *s != '\0'; s++) ! 86: switch (*s) ! 87: { ! 88: case 'N': ! 89: alias = GETARG(s); ! 90: if (*alias == '\0') ! 91: status = 1; ! 92: goto endif; ! 93: case 'T': ! 94: if (typargtolist(GETARG(s),pdirtyp)==NO) ! 95: status = 1; ! 96: else if (*s == '\0') ! 97: status = 1; ! 98: goto endif; ! 99: case 'd': ! 100: plusdflag = YES; ! 101: break; ! 102: default: ! 103: warn("bad option +%c", *s); ! 104: status = 1; ! 105: goto endif; ! 106: } ! 107: } ! 108: endif: continue; ! 109: } ! 110: if (status == 1 || argc < 1) ! 111: fatal("usage: pmkdir [{+-}d] [{+-}N alias] %s", ! 112: "[{+-}T type[,type...]]\n pdirname ..."); ! 113: } ! 114: ! 115: if ((CWP = getcwp()) == NULL) ! 116: fatal("no project environment"); ! 117: if (getwd(CWD) == NULL) ! 118: fatal("can't find current working directory"); ! 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 (mustexist) ! 135: switch (pathbuf.p_mode & P_IFMT) ! 136: { ! 137: case P_IFPDIR: ! 138: if (SLNUM(pdirtyp) > 0) ! 139: status |= addtyp(*argv, pdirtyp, ! 140: &pathbuf); ! 141: if (plusdflag == YES) ! 142: status |= chdesc(*argv, &pathbuf); ! 143: if (alias != NULL) ! 144: status |= chalias(*argv, alias, ! 145: &pathbuf); ! 146: break; ! 147: case P_IFNEW: ! 148: case P_IFREG: ! 149: warn("%s: no such project directory", *argv); ! 150: status = 1; ! 151: break; ! 152: case P_IFHOME: ! 153: case P_IFPROOT: ! 154: warn("%s is a project root directory", *argv); ! 155: status = 1; ! 156: break; ! 157: } ! 158: else ! 159: status |= mkpdir(*argv, alias, pdirtyp, minusdflag, &pathbuf); ! 160: if (WANT_TO_EXIT) ! 161: exit(1); ! 162: } ! 163: exit(status); ! 164: } ! 165: ! 166: ! 167: ! 168: /* ! 169: * addtyp() adds type labels to an existing project directory. ! 170: */ ! 171: addtyp(ppathname, pdirtyp, pb) ! 172: char *ppathname; /* project directory pathname */ ! 173: SLIST *pdirtyp; /* project directory type labels list */ ! 174: PATH *pb; /* pathname struct buffer */ ! 175: { ! 176: char *pbfndkey(); /* find key */ ! 177: int closepdb(); /* close database */ ! 178: int errpdb(); /* print database error */ ! 179: int pgetent(); /* load next entry into buffer */ ! 180: int pputent(); /* write buffer to database */ ! 181: PDB *openpdb(); /* open database */ ! 182: PDB *pldp; /* project link directory stream */ ! 183: void pbaddtyp(); /* add type labels to buffer */ ! 184: ! 185: if ((pldp = openpdb(PLDNAME, pb->p_project, "rw")) == NULL) ! 186: return(errpdb((PDB *) NULL)); ! 187: while (pgetent(pldp) != EOF) ! 188: { ! 189: if (pbfndkey(pb->p_alias) != NULL) ! 190: pbaddtyp(ppathname, pdirtyp); ! 191: pputent(pldp); ! 192: } ! 193: return(closepdb(pldp)); ! 194: } ! 195: ! 196: ! 197: ! 198: /* ! 199: * badtyp() prints a bad format type label message. ! 200: */ ! 201: void ! 202: badtyp(type) ! 203: char *type; /* type label */ ! 204: { ! 205: warn("\"%s\" type label is badly formatted", type); ! 206: } ! 207: ! 208: ! 209: ! 210: /* ! 211: * chalias() changes an existing project directory alias. ! 212: */ ! 213: chalias(ppathname, newalias, pb) ! 214: char *ppathname; /* project directory pathname */ ! 215: char *newalias; /* new project directory alias */ ! 216: PATH *pb; /* pathname struct buffer */ ! 217: { ! 218: char *pbfndkey(); /* find key */ ! 219: int _closepdb(); /* close database without updating */ ! 220: int closepdb(); /* close database */ ! 221: int errpdb(); /* print database error */ ! 222: int pbchgkey(); /* change existing key */ ! 223: int pgetent(); /* load next entry into buffer */ ! 224: int pputent(); /* write buffer to database */ ! 225: PDB *openpdb(); /* open database */ ! 226: PDB *pldp; /* project link directory stream */ ! 227: ! 228: if ((pldp = openpdb(PLDNAME, pb->p_project, "rw")) == NULL) ! 229: return(errpdb((PDB *) NULL)); ! 230: while (pgetent(pldp) != EOF) ! 231: { ! 232: if (pbfndkey(newalias) != NULL) ! 233: { ! 234: warn("%s: %s exists", ppathname, newalias); ! 235: _closepdb(pldp); ! 236: return(1); ! 237: } ! 238: pbchgkey(pb->p_alias, newalias); ! 239: pputent(pldp); ! 240: } ! 241: return(closepdb(pldp)); ! 242: } ! 243: ! 244: ! 245: ! 246: /* ! 247: * chdesc() changes an existing project directory description. ! 248: */ ! 249: chdesc(ppathname, pb) ! 250: char *ppathname; /* project directory pathname */ ! 251: PATH *pb; /* pathname struct buffer */ ! 252: { ! 253: char *pbfndkey(); /* find key */ ! 254: int closepdb(); /* close database */ ! 255: int errpdb(); /* print database error */ ! 256: int pgetent(); /* load next entry into buffer */ ! 257: int pputent(); /* write buffer to database */ ! 258: PDB *openpdb(); /* open database */ ! 259: PDB *pldp; /* project link directory stream */ ! 260: void pbadddesc(); /* add project directory description */ ! 261: ! 262: if ((pldp = openpdb(PLDNAME, pb->p_project, "rw")) == NULL) ! 263: return(errpdb((PDB *) NULL)); ! 264: while (pgetent(pldp) != EOF) ! 265: { ! 266: if (pbfndkey(pb->p_alias) != NULL) ! 267: pbadddesc(ppathname); ! 268: pputent(pldp); ! 269: } ! 270: return(closepdb(pldp)); ! 271: } ! 272: ! 273: ! 274: ! 275: /* ! 276: * mkpdir() makes a project directory. ! 277: */ ! 278: mkpdir(ppathname, alias, pdirtyp, dflag, pb) ! 279: char *ppathname; /* project directory pathname */ ! 280: char *alias; /* alternative project directory name */ ! 281: int dflag; /* project directory description flag */ ! 282: SLIST *pdirtyp; /* project directory type labels list */ ! 283: PATH *pb; /* pathname struct buffer */ ! 284: { ! 285: char apathname[PATHSIZE]; /* absolute regular pathname */ ! 286: char *mkalias(); /* construct alias from pathname */ ! 287: char *optpath(); /* optimize pathname */ ! 288: char *pathcat(); /* pathname concatenation */ ! 289: char *pbfndkey(); /* find database key */ ! 290: char *rdp; /* relative project directory path */ ! 291: char rpathname[PATHSIZE]; /* project root directory pathname */ ! 292: char *strcpy(); /* string copy */ ! 293: char *xorpath(); /* remove subpathname */ ! 294: int _closepdb(); /* close database without updating */ ! 295: int closepdb(); /* close database */ ! 296: int errpdb(); /* print database error message */ ! 297: int pbaddkey(); /* add key */ ! 298: int pbaddstring(); /* add string field */ ! 299: int pgetent(); /* load next entry into buffer */ ! 300: int pputent(); /* write buffer to database */ ! 301: PDB *openpdb(); /* open database */ ! 302: PDB *pldp; /* project link directory stream */ ! 303: void pbadddesc(); /* add project directory description */ ! 304: void pbaddtyp(); /* add type labels to buffer */ ! 305: void pbclear(); /* clear buffer */ ! 306: ! 307: switch (pb->p_mode & P_IFMT) ! 308: { ! 309: case P_IFNEW: ! 310: case P_IFREG: ! 311: break; ! 312: case P_IFPDIR: ! 313: case P_IFHOME: ! 314: case P_IFPROOT: ! 315: warn("%s exists", ppathname); ! 316: return(1); ! 317: } ! 318: ! 319: /* create pathname relative to project root directory */ ! 320: strcpy(rpathname, pb->p_project); ! 321: if (*pb->p_path == _RDIRC) ! 322: { ! 323: rdp = xorpath(rpathname, pb->p_path); ! 324: } ! 325: else { ! 326: optpath(pathcat(apathname, CWD, pb->p_path)); ! 327: rdp = xorpath(rpathname, apathname); ! 328: } ! 329: ! 330: /* open project link directory */ ! 331: if ((pldp = openpdb(PLDNAME, rpathname, "rw")) == NULL) ! 332: return(errpdb((PDB *) NULL)); ! 333: ! 334: /* ! 335: * check for existing aliases while preparing project link ! 336: * directory for new entry. ! 337: */ ! 338: if (alias == NULL) ! 339: if (EQUAL(pb->p_alias, CURDIR) || EQUAL(pb->p_alias, PARENTDIR)) ! 340: alias = mkalias(rdp); ! 341: else ! 342: alias = pb->p_alias; ! 343: while (pgetent(pldp) != EOF) ! 344: { ! 345: if (pbfndkey(alias) != NULL) ! 346: { ! 347: warn("%s: %s exists", ppathname, alias); ! 348: _closepdb(pldp); ! 349: return(1); ! 350: } ! 351: pputent(pldp); ! 352: } ! 353: ! 354: /* make the directory if non-existent */ ! 355: if ((pb->p_mode & P_IFMT) == P_IFREG) ! 356: { ! 357: if ((pb->p_mode & S_IFMT) != S_IFDIR) ! 358: { ! 359: warn("%s: not a directory", ppathname); ! 360: _closepdb(pldp); ! 361: return(1); ! 362: } ! 363: } ! 364: else if (MK_DIR(pb->p_path) != 0) ! 365: { ! 366: _closepdb(pldp); ! 367: return(1); ! 368: } ! 369: ! 370: /* update database */ ! 371: pbclear(); ! 372: pbaddkey(alias); ! 373: pbaddstring(PDIRPATH, rdp); ! 374: pbaddtyp(ppathname, pdirtyp); ! 375: if (dflag == YES) ! 376: pbadddesc(ppathname); ! 377: else ! 378: pbaddstring(PDIRDESC, ""); ! 379: pputent(pldp); ! 380: return(closepdb(pldp)); ! 381: } ! 382: ! 383: ! 384: ! 385: /* ! 386: * onintr() resets interrupt, quit, and hangup signals, and sets a flag ! 387: * which advises the process to exit at the first opportunity. ! 388: */ ! 389: onintr() ! 390: { ! 391: signal(SIGINT, onintr); ! 392: signal(SIGQUIT, onintr); ! 393: signal(SIGHUP, onintr); ! 394: ! 395: WANT_TO_EXIT = 1; ! 396: } ! 397: ! 398: ! 399: ! 400: /* ! 401: * pbadddesc() fetchs a project directory description from stdin and ! 402: * adds to database buffer. ! 403: */ ! 404: void ! 405: pbadddesc(ppathname) ! 406: char *ppathname; /* project directory pathname */ ! 407: { ! 408: char dirdesc[DIRDESCSIZE]; /* project directory description */ ! 409: char *gets(); /* get a line from stdin */ ! 410: int pbaddstring(); /* add string field */ ! 411: ! 412: printf("%s: description? (1 line): ", ppathname); ! 413: gets(dirdesc); ! 414: pbaddstring(PDIRDESC, dirdesc); ! 415: } ! 416: ! 417: ! 418: ! 419: /* ! 420: * pbaddtyp() adds type labels to database buffer. ! 421: */ ! 422: void ! 423: pbaddtyp(ppathname, typlist) ! 424: char *ppathname; /* project pathname */ ! 425: SLIST *typlist; /* type labels list */ ! 426: { ! 427: char *pbgetstring(); /* get specified string field */ ! 428: char *pdtfind(); /* find type label in buffer */ ! 429: char *pfxcpy(); /* copy string prefix */ ! 430: char *slget(); /* get next key from list */ ! 431: char *tp; /* pointer to type label */ ! 432: char type[TYPESIZE]; /* type label buffer */ ! 433: char typbuf[TYPBUFSIZE]; /* project directory types buffer */ ! 434: int pbaddstring(); /* add string field */ ! 435: void pdtinsert(); /* insert type label */ ! 436: void slrewind(); /* rewind list */ ! 437: ! 438: pbgetstring(PDIRTYPE, typbuf); ! 439: slrewind(typlist); ! 440: while ((tp = slget(typlist)) != NULL) ! 441: { ! 442: if (pdtfind(pfxcpy(type, tp), typbuf) == NULL) ! 443: pdtinsert(tp, typbuf); ! 444: else ! 445: warn("%s: \"%s\" type label exists", ppathname, type); ! 446: } ! 447: pbaddstring(PDIRTYPE, typbuf); ! 448: } ! 449: ! 450: ! 451: ! 452: /* ! 453: * typargtolist() prepends comma-separated type labels specified in typarg ! 454: * to typlist. Returns NO if type labels are badly formatted, otherwise ! 455: * YES. ! 456: */ ! 457: typargtolist(typarg, typlist) ! 458: register char *typarg; /* type labels argument */ ! 459: SLIST *typlist; /* type labels list */ ! 460: { ! 461: register char *t; /* type label argument pointer */ ! 462: char *slprepend(); /* prepend singly-linked list key */ ! 463: int ispdt(); /* is project dir type label legal? */ ! 464: int status = YES; /* return status */ ! 465: void badtyp(); /* print bad type label message */ ! 466: ! 467: for (t = typarg; *t != '\0'; t++) ! 468: continue; ! 469: for (; t >= typarg; t--) ! 470: if (t[0] == ',') ! 471: { ! 472: if (t[1] != '\0') ! 473: if (ispdt(t+1)) ! 474: slprepend(t+1, typlist); ! 475: else { ! 476: badtyp(t+1); ! 477: status = NO; ! 478: } ! 479: t[0] = '\0'; ! 480: } ! 481: if (ispdt(typarg)) ! 482: slprepend(typarg, typlist); ! 483: else { ! 484: badtyp(typarg); ! 485: status = NO; ! 486: } ! 487: return(status); ! 488: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.