1: /* $Header$ */
2:
3: /*
4: * Author: Peter J. Nicklin
5: */
6:
7: /*
8: * xppath() expands project pathname ppathname into regular pathname. Both
9: * the pathname type labels and description are ignored for efficiency.
10: * Returns -1 on error, otherwise zero.
11: */
12: #include <pwd.h>
13: #include <stdio.h>
14: #include <sys/types.h>
15: #include <sys/stat.h>
16: #include "null.h"
17: #include "path.h"
18: #include "pdb.h"
19: #include "pld.h"
20: #include "system.h"
21: #include "yesno.h"
22: /*
23: * pathname states
24: */
25: #define START 0001
26: #define HDIR 0002
27: #define PDIR1 0004
28: #define PDIR2 0010
29: #define DIR1 0020
30: #define DIR2 0040
31: #define EOP 0100
32: #define ERROR 0200
33: /*
34: * pathname errors
35: */
36: #define E_UNKNOWN 0
37: #define E_SYNTAX 1
38: #define E_NOTPDIR 2
39: #define E_NOTDIR 3
40:
41: extern int errno;
42: extern int sys_nerr;
43: extern char *sys_errlist[];
44: extern char PDBERR[]; /* project link dir error message */
45:
46: static char *pp; /* project pathname pointer */
47: static char *perrlist[] =
48: {
49: "unknown error",
50: "pathname syntax error",
51: "no such project directory",
52: "no such file, directory, or project",
53: };
54:
55: char *PATHERR; /* current pathname error condition */
56: int PPDEBUG = NO; /* project pathname debug flag */
57:
58: xppath(ppathname, pb)
59: char *ppathname; /* project pathname */
60: register PATH *pb; /* pathname struct pointer */
61: {
62: register char *p; /* regular pathname pointer */
63: register short pstat; /* pathname state */
64: char *getcwp(); /* get current project pathname */
65: char *gethdir(); /* get home directory pathname */
66: char *hdir; /* home directory pointer */
67: char *mkalias(); /* construct alias from pathname */
68: char *optpath(); /* optimize pathname */
69: char *pathcat(); /* pathname concatenation */
70: char *pbgetstring(); /* get specified string field */
71: char *pdir; /* project directory pathname */
72: char pplex(); /* pathname lexical analyzer */
73: char *strcpy(); /* string copy */
74: char *strpcpy(); /* copy string to pathname */
75: char token[PATHSIZE]; /* receiving token */
76: int closepdb(); /* close database */
77: int pbfndflag(); /* find flag field */
78: int pfndent(); /* find and load database entry */
79: int strlen(); /* string length */
80: PDB *openpdb(); /* open database */
81: PDB *pdbp; /* database stream */
82: struct passwd *getpwdir(); /* get password file entry for dir */
83: struct stat stbuf; /* file state buffer */
84:
85: PATHERR = perrlist[E_UNKNOWN];
86: pstat = START;
87: pp = ppathname;
88: pb->p_mode = P_IFREG;
89: pb->p_alias = optpath(strcpy(pb->p_buf, mkalias(ppathname)));
90: p = pb->p_path = pb->p_buf + strlen(pb->p_buf) + 1;
91: *pb->p_project = '\0';
92:
93: while (pstat != EOP)
94: {
95: switch (pplex(token))
96: {
97: case _HDIRC: /* user's home directory */
98: if (pstat == START)
99: {
100: if ((hdir = gethdir(token+1)) != NULL)
101: {
102: p = strpcpy(p, hdir);
103: strcpy(pb->p_project, pb->p_path);
104: pb->p_mode = P_IFHOME;
105: pstat = HDIR;
106: break;
107: }
108: }
109: PATHERR = perrlist[E_SYNTAX];
110: pstat = ERROR;
111: break;
112: case _PPSC: /* project pathname separator char */
113: if ((pstat&(START|HDIR|PDIR2)) == 0)
114: {
115: if ((pstat&DIR1) != 0)
116: PATHERR = perrlist[E_SYNTAX];
117: else
118: PATHERR = perrlist[E_NOTDIR];
119: pstat = ERROR;
120: break;
121: }
122: if (pstat == START)
123: {
124: pb->p_mode = P_IFHOME;
125: p = strpcpy(p, gethdir((char *) NULL));
126: strcpy(pb->p_project, pb->p_path);
127: }
128: p = strpcpy(p, PATHSEP);
129: pstat = PDIR1;
130: break;
131: case _PSC: /* pathname separator character */
132: if ((pstat&(START|HDIR|PDIR2|DIR2)) == 0)
133: {
134: PATHERR = perrlist[E_SYNTAX];
135: pstat = ERROR;
136: break;
137: }
138: if (pstat == START && (pdir = getcwp()) != NULL)
139: strcpy(pb->p_project, pdir);
140: p = strpcpy(p, PATHSEP);
141: pstat = DIR1;
142: break;
143: case '\0':
144: *p = '\0';
145: pstat = EOP;
146: break;
147: default:
148: /* project dir, regular dir, or file */
149: if ((pstat&(START|PDIR1|DIR1)) == 0)
150: {
151: PATHERR = perrlist[E_SYNTAX];
152: pstat = ERROR;
153: break;
154: }
155: if (pstat == DIR1)
156: {
157: regdir: p = strpcpy(p, token);
158: pb->p_mode = P_IFREG;
159: pstat = DIR2;
160: break;
161: }
162: /* initialize pathname */
163: if (pstat == START)
164: {
165: if ((pdir = getcwp()) == NULL)
166: goto regdir;
167: strcpy(pb->p_project, pdir);
168: }
169: else {
170: pdir = pb->p_path;
171: }
172: if ((pdbp = openpdb(PLDNAME, pdir, "r")) == NULL)
173: {
174: PATHERR = PDBERR;
175: pstat = ERROR;
176: break;
177: }
178: /* project directory? */
179: if (pfndent(token, pdbp) == NO)
180: {
181: closepdb(pdbp);
182: if ((pstat&PDIR1) != 0)
183: {/* project dir must follow ^ */
184: PATHERR = perrlist[E_NOTPDIR];
185: pstat = ERROR;
186: break;
187: }
188: goto regdir;
189: }
190: if (pstat == START)
191: {
192: p = strpcpy(p, pdir);
193: p = strpcpy(p, PATHSEP);
194: }
195: if (pbfndflag(PROOTDIR) == YES)
196: {
197: pb->p_mode = P_IFPROOT;
198: pstat = PDIR2;
199: }
200: else {
201: pb->p_mode = P_IFPDIR;
202: pstat = DIR2;
203: }
204: /* is new pathname absolute? */
205: if (*pbgetstring(PDIRPATH, p) == _RDIRC)
206: p = strpcpy(pb->p_path, p);
207: else while (*p != '\0') p++;
208: closepdb(pdbp);
209: if (pb->p_mode == P_IFPROOT)
210: strcpy(pb->p_project, pb->p_path);
211: break;
212: }
213: if (pstat == ERROR)
214: {
215: *p = '\0';
216: break;
217: }
218: }
219: if (pstat != ERROR)
220: {
221: optpath(pb->p_path);
222: optpath(pb->p_project);
223: if (stat(pb->p_path, &stbuf) == 0)
224: {
225: /*
226: * a regular dir may be a root project directory
227: * specified as ~user, but expanded by the shell.
228: */
229: if (pb->p_mode == P_IFREG &&
230: (stbuf.st_mode&S_IFMT) == S_IFDIR)
231: {
232: char pathbuf[PATHSIZE];
233:
234: pathcat(pathbuf, pb->p_path, PLDNAME);
235: if (FILEXIST(pathbuf) &&
236: getpwdir(pb->p_path) != NULL)
237: {
238: strcpy(pb->p_project, pb->p_path);
239: pb->p_mode = P_IFHOME;
240: }
241: }
242: pb->p_mode |= (unsigned long) stbuf.st_mode;
243: }
244: else {
245: if(errno < sys_nerr)
246: PATHERR = sys_errlist[errno];
247: if (pb->p_mode == P_IFREG)
248: pb->p_mode = P_IFNEW;
249: else { /* a project directory must exist */
250: pstat = ERROR;
251: }
252: }
253: pb->p_type = pb->p_path + strlen(pb->p_path) + 1;
254: pb->p_desc = pb->p_type + 1;
255: *pb->p_type = *pb->p_desc = '\0';
256: }
257: if (PPDEBUG == YES)
258: warn("%s --> %s", ppathname, pb->p_path);
259: return((pstat == ERROR) ? -1 : 0);
260: }
261:
262:
263:
264: /*
265: * pplex() gets next token. Returns first character of token.
266: */
267: static char
268: pplex(token)
269: register char *token; /* receiving token */
270: {
271: register char *rpp; /* project pathname pointer */
272: char t; /* 1st token character */
273:
274: rpp = pp;
275: t = *rpp;
276: switch (t)
277: {
278: case _PPSC:
279: *token++ = *rpp++;
280: while (*rpp == _PPSC) rpp++;
281: break;
282: case _PSC:
283: *token++ = *rpp++;
284: while (*rpp == _PSC) rpp++;
285: break;
286: case '\0':
287: break;
288: default:
289: while (*rpp != _PPSC && *rpp != _PSC && *rpp != '\0')
290: *token++ = *rpp++;
291: break;
292: }
293: *token = '\0';
294: pp = rpp;
295: return(t);
296: }
297:
298:
299:
300: /*
301: * patherr() prints the error message PATHERR to stderr stream and
302: * returns constant 1.
303: */
304: patherr(mesg)
305: char *mesg; /* error message */
306: {
307: int strlen(); /* string length */
308:
309: if (strlen(mesg) > 0)
310: warn("%s: %s", mesg, PATHERR);
311: else
312: warn("%s", PATHERR);
313: return(1);
314: }
Defined functions
Defined variables
pp
defined in line
46; used 3 times
Defined macros
DIR1
defined in line
29; used 4 times
DIR2
defined in line
30; used 3 times
EOP
defined in line
31; used 2 times
ERROR
defined in line
32; used 10 times
HDIR
defined in line
26; used 3 times
PDIR1
defined in line
27; used 3 times
PDIR2
defined in line
28; used 3 times
START
defined in line
25; used 9 times