1: static char *rcsid = "$Header$"; 2: /* 3: * prmdir - remove a project 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 *RMFLAG = ""; /* rm "-f" flag */ 24: char *PGN = "prmdir"; /* program name */ 25: int RECURSIVE = 0; /* remove project dirs recursively */ 26: int UNDEFINE = 0; /* remove proj dir definitions only */ 27: int WANT_TO_EXIT = 0; /* advisory exit flag */ 28: 29: main(argc, argv) 30: int argc; 31: char **argv; 32: { 33: extern int PPDEBUG; /* project pathname debug flag */ 34: char *getcwp(); /* get current working project */ 35: char *getwd(); /* get current working directory */ 36: int isfg(); /* is process in foreground? */ 37: int onintr(); /* process signals */ 38: int rmpdir(); /* remove a project directory */ 39: int rmtyp(); /* remove project dir type labels */ 40: int unpdir(); /* undefine project directory */ 41: int status = 0; /* exit status */ 42: int xppath(); /* expand project pathname */ 43: PATH pathbuf; /* pathname struct buffer */ 44: SLIST *pdirtyp; /* project directory type labels list */ 45: SLIST *slinit(); /* initialize singly-linked list */ 46: void typargtolist(); /* type labels -> pdirtyp list */ 47: 48: pdirtyp = slinit(); 49: { 50: register char *s; /* option pointer */ 51: while (--argc > 0 && **++argv == '-') 52: { 53: for (s = argv[0]+1; *s != '\0'; s++) 54: switch (*s) 55: { 56: case 'D': 57: PPDEBUG = YES; 58: break; 59: case 'T': 60: typargtolist(GETARG(s), pdirtyp); 61: if (*s == '\0') 62: status = 1; 63: goto endfor; 64: case 'f': 65: RMFLAG = "-f"; 66: break; 67: case 'r': 68: RECURSIVE++; 69: break; 70: case 'u': 71: UNDEFINE++; 72: break; 73: default: 74: warn("bad option -%c", *s); 75: status = 1; 76: goto endfor; 77: } 78: endfor: continue; 79: } 80: } 81: if (status == 1 || argc < 1) 82: fatal("usage: prmdir [-fru] [-T type[,type...]] pdirname ..."); 83: 84: if ((CWP = getcwp()) == NULL) 85: fatal("no project environment"); 86: if (getwd(CWD) == NULL) 87: fatal("can't find current working directory"); 88: if (isfg() == YES) 89: { 90: signal(SIGHUP, onintr); 91: signal(SIGINT, onintr); 92: signal(SIGQUIT, onintr); 93: } 94: 95: for (; argc > 0; ++argv, --argc) 96: { 97: if (xppath(*argv, &pathbuf) == -1) 98: { 99: patherr(*argv); 100: status = 1; 101: continue; 102: } 103: switch (pathbuf.p_mode & P_IFMT) 104: { 105: case P_IFPDIR: 106: if (SLNUM(pdirtyp) > 0) 107: status |= rmtyp(*argv, pdirtyp, &pathbuf); 108: else if (UNDEFINE) 109: status |= unpdir(&pathbuf); 110: else 111: status |= rmpdir(*argv, &pathbuf); 112: break; 113: case P_IFHOME: 114: case P_IFPROOT: 115: warn("%s is a project root directory", *argv); 116: status = 1; 117: break; 118: case P_IFNEW: 119: case P_IFREG: 120: warn("%s: no such project directory", *argv); 121: status = 1; 122: break; 123: } 124: if (WANT_TO_EXIT) 125: exit(1); 126: } 127: exit(status); 128: } 129: 130: 131: 132: /* 133: * onintr() resets interrupt, quit, and hangup signals, and sets a flag 134: * which advises the process to exit at the first opportunity. 135: */ 136: onintr() 137: { 138: signal(SIGINT, onintr); 139: signal(SIGQUIT, onintr); 140: signal(SIGHUP, onintr); 141: 142: WANT_TO_EXIT = 1; 143: } 144: 145: 146: 147: /* 148: * pbrmtyp() removes type labels from database buffer. 149: */ 150: void 151: pbrmtyp(ppathname, typlist) 152: char *ppathname; /* project pathname */ 153: SLIST *typlist; /* type labels list */ 154: { 155: char *pbgetstring(); /* get specified string field */ 156: char *pdtfind(); /* find type label in buffer */ 157: char *slget(); /* get next key from list */ 158: char *tp; /* pointer to type label */ 159: char typbuf[TYPBUFSIZE]; /* project directory types buffer */ 160: int pbaddstring(); /* add string field */ 161: int strlen(); /* string length */ 162: void slrewind(); /* rewind list */ 163: void pdtrm(); /* remove type label */ 164: 165: pbgetstring(PDIRTYPE, typbuf); 166: slrewind(typlist); 167: while ((tp = slget(typlist)) != NULL) 168: { 169: if (pdtfind(tp, typbuf) != NULL) 170: pdtrm(tp, typbuf); 171: else 172: warn("%s: \"%s\" type label not found", ppathname, tp); 173: } 174: pbaddstring(PDIRTYPE, typbuf); 175: } 176: 177: 178: 179: /* 180: * rmd() removes a project directory. rmd() returns the status of the rm 181: * command or 1 if the user decides not to remove a project directory. 182: */ 183: rmd(pathname) 184: char *pathname; /* full pathname of directory */ 185: { 186: char cmdbuf[PATHSIZE+9]; /* command buffer */ 187: char *sprintf(); /* print output to string */ 188: int status; /* return status */ 189: int yes(); /* is reply yes? */ 190: 191: if (RECURSIVE) 192: { 193: sprintf(cmdbuf, "rm %s -r %s", RMFLAG, pathname); 194: printf("%s? [yn](n): ", cmdbuf); 195: if (!yes()) 196: return(1); 197: status = system(cmdbuf); 198: status >>= NBBY; 199: status &= 0xff; 200: } 201: else { 202: status = RM_DIR(pathname); 203: } 204: return(status); 205: } 206: 207: 208: 209: /* 210: * rmpdir() removes a project directory. Returns 0 is successful, otherwise 1. 211: */ 212: rmpdir(ppathname, pb) 213: char *ppathname; /* project directory pathname */ 214: PATH *pb; /* pathname struct buffer */ 215: { 216: int _closepdb(); /* close database without updating */ 217: int closepdb(); /* close database */ 218: int errpdb(); /* print database error */ 219: int plen; /* length of regular pathname */ 220: int pputent(); /* write buffer to database */ 221: int status = 0; /* return status */ 222: int strlen(); /* string length */ 223: int strncmp(); /* compare n characters */ 224: PATH *pd; /* pathname struct pointer */ 225: PATH *readpld(); /* read project link directory entry */ 226: PDB *openpdb(); /* open database */ 227: PDB *pldp; /* project link directory stream */ 228: 229: plen = strlen(pb->p_path); 230: if (strncmp(pb->p_path, CWD, plen) == 0) 231: { 232: warn("can't remove %s from current directory", ppathname); 233: return(1); 234: } 235: if ((pldp = openpdb(PLDNAME, pb->p_project, "rw")) == NULL) 236: return(errpdb((PDB *) NULL)); 237: while ((pd = readpld(pldp)) != NULL) 238: if (EQUAL(pb->p_alias, pd->p_alias)) 239: continue; /* the directory itself */ 240: else if (strncmp(pb->p_path, pd->p_path, plen) == 0) 241: { /* nest project directories */ 242: if (pd->p_mode == P_IFPROOT) 243: { /* don't clobber projects */ 244: warn("can't remove %s because project %s exists", 245: ppathname, pd->p_path); 246: status = 1; 247: break; 248: } 249: } 250: else { 251: pputent(pldp); 252: } 253: if (status == 1) 254: _closepdb(pldp); 255: else { 256: if ((status = rmd(pb->p_path)) != 0) 257: _closepdb(pldp); 258: else 259: status = closepdb(pldp); 260: } 261: return(status); 262: } 263: 264: 265: 266: /* 267: * rmtyp() removes type labels from an existing project directory. 268: */ 269: rmtyp(ppathname, pdirtyp, pb) 270: char *ppathname; /* project directory pathname */ 271: SLIST *pdirtyp; /* project directory type labels list */ 272: PATH *pb; /* pathname struct buffer */ 273: { 274: char *pbfndkey(); /* find key */ 275: int closepdb(); /* close database */ 276: int errpdb(); /* print database error */ 277: int pgetent(); /* load next entry into buffer */ 278: int pputent(); /* write buffer to database */ 279: int status = 0; /* return status */ 280: PDB *openpdb(); /* open database */ 281: PDB *pldp; /* project link directory stream */ 282: void pbrmtyp(); /* remove type labels from buffer */ 283: 284: if ((pldp = openpdb(PLDNAME, pb->p_project, "rw")) == NULL) 285: return(errpdb((PDB *) NULL)); 286: while (pgetent(pldp) != EOF) 287: { 288: if (pbfndkey(pb->p_alias) != NULL) 289: pbrmtyp(ppathname, pdirtyp); 290: pputent(pldp); 291: } 292: status = closepdb(pldp); 293: return(status); 294: } 295: 296: 297: 298: /* 299: * typargtolist() prepends comma-separated type labels specified in typarg 300: * to typlist. 301: */ 302: void 303: typargtolist(typarg, typlist) 304: register char *typarg; /* type labels argument */ 305: SLIST *typlist; /* type labels list */ 306: { 307: register char *t; /* type label argument pointer */ 308: char *slprepend(); /* prepend singly-linked list key */ 309: 310: for (t = typarg; *t != '\0'; t++) 311: continue; 312: for (; t >= typarg; t--) 313: if (t[0] == ',') 314: { 315: if (t[1] != '\0') 316: slprepend(t+1, typlist); 317: t[0] = '\0'; 318: } 319: slprepend(typarg, typlist); 320: } 321: 322: 323: 324: /* 325: * unpdir() undefines a project directory. Returns 0 is successful, otherwise 1. 326: */ 327: unpdir(pb) 328: PATH *pb; /* pathname struct buffer */ 329: { 330: int closepdb(); /* close database */ 331: int errpdb(); /* print database error */ 332: int pputent(); /* write buffer to database */ 333: PATH *pd; /* pathname struct pointer */ 334: PATH *readpld(); /* read project link directory entry */ 335: PDB *openpdb(); /* open database */ 336: PDB *pldp; /* project link directory stream */ 337: 338: if ((pldp = openpdb(PLDNAME, pb->p_project, "rw")) == NULL) 339: return(errpdb((PDB *) NULL)); 340: while ((pd = readpld(pldp)) != NULL) 341: if (EQUAL(pb->p_alias, pd->p_alias)) 342: continue; 343: else 344: pputent(pldp); 345: return(closepdb(pldp)); 346: }