|
|
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.