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