1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * Copyright (c) 1996, by Sun Microsystems, Inc.
24*0Sstevel@tonic-gate * All Rights Reserved.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate #include <locale.h>
30*0Sstevel@tonic-gate #include <sys/types.h>
31*0Sstevel@tonic-gate #include <stdio.h>
32*0Sstevel@tonic-gate #include <sys/param.h>
33*0Sstevel@tonic-gate #include <string.h>
34*0Sstevel@tonic-gate #include <unistd.h>
35*0Sstevel@tonic-gate #include <errno.h>
36*0Sstevel@tonic-gate #include <fcntl.h>
37*0Sstevel@tonic-gate #include <sys/stat.h>
38*0Sstevel@tonic-gate #include <stdlib.h>
39*0Sstevel@tonic-gate
40*0Sstevel@tonic-gate #include "rules.h"
41*0Sstevel@tonic-gate
42*0Sstevel@tonic-gate char * lex(FILE *);
43*0Sstevel@tonic-gate
44*0Sstevel@tonic-gate extern char *mstrdup(const char *);
45*0Sstevel@tonic-gate extern void *mmalloc(size_t size);
46*0Sstevel@tonic-gate
47*0Sstevel@tonic-gate void
read_rules(FILE * file,int (* rulefunc)())48*0Sstevel@tonic-gate read_rules(FILE *file, int (*rulefunc)())
49*0Sstevel@tonic-gate {
50*0Sstevel@tonic-gate char *s;
51*0Sstevel@tonic-gate int base_active = 0;
52*0Sstevel@tonic-gate int list_ent_cnt = 0;
53*0Sstevel@tonic-gate int gign_ent_cnt = 0;
54*0Sstevel@tonic-gate int lign_ent_cnt = 0;
55*0Sstevel@tonic-gate struct item *add_item();
56*0Sstevel@tonic-gate struct item *fitem, *sitem;
57*0Sstevel@tonic-gate char version[20];
58*0Sstevel@tonic-gate
59*0Sstevel@tonic-gate last_gign = &gign_hd;
60*0Sstevel@tonic-gate gign_hd.i_next = (struct item *)0;
61*0Sstevel@tonic-gate gign_hd.i_str = (char *)0;
62*0Sstevel@tonic-gate list_hd.i_next = (struct item *)0;
63*0Sstevel@tonic-gate list_hd.i_str = (char *)0;
64*0Sstevel@tonic-gate while (s = lex(file)) {
65*0Sstevel@tonic-gate if (s == (char *)0)
66*0Sstevel@tonic-gate break;
67*0Sstevel@tonic-gate if (*s == '#')
68*0Sstevel@tonic-gate continue;
69*0Sstevel@tonic-gate if (*s == '*')
70*0Sstevel@tonic-gate continue;
71*0Sstevel@tonic-gate if (strcmp(s, BASE) == 0) {
72*0Sstevel@tonic-gate #ifdef DEBUG
73*0Sstevel@tonic-gate printf("BASE base_active = %d\n", base_active);
74*0Sstevel@tonic-gate #endif /* DEBUG */
75*0Sstevel@tonic-gate if (base_active) {
76*0Sstevel@tonic-gate /*
77*0Sstevel@tonic-gate * Tack local IGNORE strings to end of globals
78*0Sstevel@tonic-gate */
79*0Sstevel@tonic-gate if (lign_hd.i_next != (struct item *)0) {
80*0Sstevel@tonic-gate last_gign->i_next = &lign_hd;
81*0Sstevel@tonic-gate }
82*0Sstevel@tonic-gate /*
83*0Sstevel@tonic-gate * Process directives for previous BASE command
84*0Sstevel@tonic-gate * if there was one. Also free up LIST items
85*0Sstevel@tonic-gate * and local IGNORE items.
86*0Sstevel@tonic-gate */
87*0Sstevel@tonic-gate do_base_dir(basedir, &list_hd, &gign_hd,
88*0Sstevel@tonic-gate rulefunc);
89*0Sstevel@tonic-gate /*
90*0Sstevel@tonic-gate * Free up space from LIST item list
91*0Sstevel@tonic-gate */
92*0Sstevel@tonic-gate fitem = list_hd.i_next;
93*0Sstevel@tonic-gate if (fitem != (struct item *)0) {
94*0Sstevel@tonic-gate while (fitem != (struct item *)0) {
95*0Sstevel@tonic-gate free(fitem->i_str);
96*0Sstevel@tonic-gate sitem = fitem->i_next;
97*0Sstevel@tonic-gate free(fitem);
98*0Sstevel@tonic-gate fitem = sitem;
99*0Sstevel@tonic-gate }
100*0Sstevel@tonic-gate }
101*0Sstevel@tonic-gate /*
102*0Sstevel@tonic-gate * Free up space from local IGNORE item list
103*0Sstevel@tonic-gate */
104*0Sstevel@tonic-gate fitem = lign_hd.i_next;
105*0Sstevel@tonic-gate if (fitem != (struct item *)0) {
106*0Sstevel@tonic-gate while (fitem != (struct item *)0) {
107*0Sstevel@tonic-gate free(fitem->i_str);
108*0Sstevel@tonic-gate sitem = fitem->i_next;
109*0Sstevel@tonic-gate free(fitem);
110*0Sstevel@tonic-gate fitem = sitem;
111*0Sstevel@tonic-gate }
112*0Sstevel@tonic-gate }
113*0Sstevel@tonic-gate last_gign->i_next = (struct item *)0;
114*0Sstevel@tonic-gate }
115*0Sstevel@tonic-gate base_active = 1;
116*0Sstevel@tonic-gate /*
117*0Sstevel@tonic-gate * Reset LIST item list and local IGNORE item
118*0Sstevel@tonic-gate * list to be empty.
119*0Sstevel@tonic-gate */
120*0Sstevel@tonic-gate last_list = &list_hd;
121*0Sstevel@tonic-gate list_hd.i_next = (struct item *)0;
122*0Sstevel@tonic-gate list_hd.i_str = (char *)0;
123*0Sstevel@tonic-gate last_lign = &lign_hd;
124*0Sstevel@tonic-gate lign_hd.i_next = (struct item *)0;
125*0Sstevel@tonic-gate lign_hd.i_str = (char *)0;
126*0Sstevel@tonic-gate /*
127*0Sstevel@tonic-gate * Get BASE directory specified
128*0Sstevel@tonic-gate */
129*0Sstevel@tonic-gate s = lex(0);
130*0Sstevel@tonic-gate if (s == (char *)0) {
131*0Sstevel@tonic-gate fprintf(stderr, gettext("cachefspack: "));
132*0Sstevel@tonic-gate fprintf(stderr, gettext(
133*0Sstevel@tonic-gate "illegal BASE command\n"));
134*0Sstevel@tonic-gate return;
135*0Sstevel@tonic-gate }
136*0Sstevel@tonic-gate
137*0Sstevel@tonic-gate if (*s == '$') {
138*0Sstevel@tonic-gate /*
139*0Sstevel@tonic-gate * String starts with a '$', it must be an
140*0Sstevel@tonic-gate * environment variable
141*0Sstevel@tonic-gate */
142*0Sstevel@tonic-gate s = getenv(&s[1]);
143*0Sstevel@tonic-gate if (s == (char *)NULL) {
144*0Sstevel@tonic-gate fprintf(stderr,
145*0Sstevel@tonic-gate gettext("cachefspack: "));
146*0Sstevel@tonic-gate fprintf(stderr,
147*0Sstevel@tonic-gate gettext("Can't find "
148*0Sstevel@tonic-gate "environment variable\n"));
149*0Sstevel@tonic-gate exit(1);
150*0Sstevel@tonic-gate }
151*0Sstevel@tonic-gate }
152*0Sstevel@tonic-gate basedir = mstrdup(s);
153*0Sstevel@tonic-gate #ifdef DEBUG
154*0Sstevel@tonic-gate printf("basedir = %s\n", basedir);
155*0Sstevel@tonic-gate #endif /* DEBUG */
156*0Sstevel@tonic-gate continue;
157*0Sstevel@tonic-gate }
158*0Sstevel@tonic-gate if (strcmp(s, IGNORE) == 0) {
159*0Sstevel@tonic-gate #ifdef DEBUG
160*0Sstevel@tonic-gate printf("IGNORE - base_active = %d\n", base_active);
161*0Sstevel@tonic-gate #endif /* DEBUG */
162*0Sstevel@tonic-gate if (base_active) {
163*0Sstevel@tonic-gate /*
164*0Sstevel@tonic-gate * Local IGNORE rule
165*0Sstevel@tonic-gate */
166*0Sstevel@tonic-gate while ((s = lex(0))
167*0Sstevel@tonic-gate != 0) {
168*0Sstevel@tonic-gate last_lign = add_item(last_lign, s,
169*0Sstevel@tonic-gate def_lign_flags);
170*0Sstevel@tonic-gate }
171*0Sstevel@tonic-gate } else {
172*0Sstevel@tonic-gate /*
173*0Sstevel@tonic-gate * Global IGNORE rule
174*0Sstevel@tonic-gate */
175*0Sstevel@tonic-gate while ((s = lex(0)) != 0) {
176*0Sstevel@tonic-gate last_gign = add_item(last_gign, s,
177*0Sstevel@tonic-gate def_gign_flags);
178*0Sstevel@tonic-gate }
179*0Sstevel@tonic-gate }
180*0Sstevel@tonic-gate continue;
181*0Sstevel@tonic-gate }
182*0Sstevel@tonic-gate if (strcmp(s, LIST) == 0) {
183*0Sstevel@tonic-gate #ifdef DEBUG
184*0Sstevel@tonic-gate printf("LIST\n");
185*0Sstevel@tonic-gate #endif /* DEBUG */
186*0Sstevel@tonic-gate if (!base_active) {
187*0Sstevel@tonic-gate fprintf(stderr,
188*0Sstevel@tonic-gate gettext(
189*0Sstevel@tonic-gate "cachefspack: skipping LIST command - "));
190*0Sstevel@tonic-gate fprintf(stderr,
191*0Sstevel@tonic-gate gettext(" no active base\n"));
192*0Sstevel@tonic-gate continue;
193*0Sstevel@tonic-gate }
194*0Sstevel@tonic-gate while ((s = lex(0)) != 0) {
195*0Sstevel@tonic-gate last_list = add_item(last_list, s,
196*0Sstevel@tonic-gate def_list_flags);
197*0Sstevel@tonic-gate }
198*0Sstevel@tonic-gate continue;
199*0Sstevel@tonic-gate }
200*0Sstevel@tonic-gate if (strcmp(s, VERSION) == 0) {
201*0Sstevel@tonic-gate sprintf(version, "%d.%d", VERMAJOR, VERMINOR);
202*0Sstevel@tonic-gate s = lex(0);
203*0Sstevel@tonic-gate if (s == (char *)0) {
204*0Sstevel@tonic-gate fprintf(stderr, gettext("cachefspack: "));
205*0Sstevel@tonic-gate fprintf(stderr, gettext("missing version\n"));
206*0Sstevel@tonic-gate fprintf(stderr, gettext("cachefspack: "));
207*0Sstevel@tonic-gate fprintf(stderr, gettext(
208*0Sstevel@tonic-gate "version = %d.%d\n"), VERMAJOR, VERMINOR);
209*0Sstevel@tonic-gate exit(1);
210*0Sstevel@tonic-gate }
211*0Sstevel@tonic-gate if (strcmp(version, s) != 0) {
212*0Sstevel@tonic-gate fprintf(stderr, gettext(
213*0Sstevel@tonic-gate "cachefspack: "));
214*0Sstevel@tonic-gate fprintf(stderr, gettext(
215*0Sstevel@tonic-gate "WARNING - version of packing rules "));
216*0Sstevel@tonic-gate fprintf(stderr, gettext(
217*0Sstevel@tonic-gate "does not match cachefspack version\n"));
218*0Sstevel@tonic-gate fprintf(stderr, gettext(
219*0Sstevel@tonic-gate "version = %d.%d\n"), VERMAJOR, VERMINOR);
220*0Sstevel@tonic-gate }
221*0Sstevel@tonic-gate }
222*0Sstevel@tonic-gate }
223*0Sstevel@tonic-gate /*
224*0Sstevel@tonic-gate * Tack local IGNORE strings to end of globals
225*0Sstevel@tonic-gate */
226*0Sstevel@tonic-gate if (lign_hd.i_next != (struct item *)0) {
227*0Sstevel@tonic-gate last_gign->i_next = &lign_hd;
228*0Sstevel@tonic-gate }
229*0Sstevel@tonic-gate do_base_dir(basedir, &list_hd, &gign_hd, rulefunc);
230*0Sstevel@tonic-gate }
231*0Sstevel@tonic-gate
232*0Sstevel@tonic-gate struct item *
add_item(struct item * last_item,char * str,int flags)233*0Sstevel@tonic-gate add_item(struct item *last_item, char *str, int flags)
234*0Sstevel@tonic-gate {
235*0Sstevel@tonic-gate struct item * add_cmd_items();
236*0Sstevel@tonic-gate
237*0Sstevel@tonic-gate if (*str == CMDCHAR) {
238*0Sstevel@tonic-gate last_item = add_cmd_items(last_item, &str[1], bang_list_flags);
239*0Sstevel@tonic-gate } else {
240*0Sstevel@tonic-gate last_item->i_next = (struct item *)mmalloc(
241*0Sstevel@tonic-gate sizeof (struct item));
242*0Sstevel@tonic-gate last_item = last_item->i_next;
243*0Sstevel@tonic-gate last_item->i_str = mstrdup(str);
244*0Sstevel@tonic-gate last_item->i_flag = flags;
245*0Sstevel@tonic-gate last_item->i_next = (struct item *)0;
246*0Sstevel@tonic-gate }
247*0Sstevel@tonic-gate return (last_item);
248*0Sstevel@tonic-gate }
249*0Sstevel@tonic-gate
250*0Sstevel@tonic-gate struct item *
add_cmd_items(struct item * last_item,char * str,int flags)251*0Sstevel@tonic-gate add_cmd_items(struct item *last_item, char *str, int flags)
252*0Sstevel@tonic-gate {
253*0Sstevel@tonic-gate FILE *fd;
254*0Sstevel@tonic-gate char inbuf[MAX_RULE_SZ];
255*0Sstevel@tonic-gate char *olddir = NULL;
256*0Sstevel@tonic-gate char *s;
257*0Sstevel@tonic-gate void getcmd(char *, char *);
258*0Sstevel@tonic-gate
259*0Sstevel@tonic-gate if ((basedir != NULL) && (basedir[0] != '\0')) {
260*0Sstevel@tonic-gate olddir = getcwd(NULL, MAXPATHLEN + 1);
261*0Sstevel@tonic-gate if (olddir == NULL) {
262*0Sstevel@tonic-gate fprintf(stderr, gettext("cannot malloc buffer\n"));
263*0Sstevel@tonic-gate exit(1);
264*0Sstevel@tonic-gate }
265*0Sstevel@tonic-gate
266*0Sstevel@tonic-gate if (chdir(basedir) != 0) {
267*0Sstevel@tonic-gate fprintf(stderr, gettext("cannot chdir to %s: %s\n"),
268*0Sstevel@tonic-gate basedir, strerror(errno));
269*0Sstevel@tonic-gate exit(1);
270*0Sstevel@tonic-gate }
271*0Sstevel@tonic-gate }
272*0Sstevel@tonic-gate
273*0Sstevel@tonic-gate getcmd(str, inbuf);
274*0Sstevel@tonic-gate fd = popen(inbuf, "r");
275*0Sstevel@tonic-gate if (fd == NULL) {
276*0Sstevel@tonic-gate fprintf(stderr, gettext("cachefspack: LIST can't execute - "));
277*0Sstevel@tonic-gate fprintf(stderr, "%s\n", inbuf);
278*0Sstevel@tonic-gate exit(1);
279*0Sstevel@tonic-gate }
280*0Sstevel@tonic-gate
281*0Sstevel@tonic-gate while (s = lex(fd)) {
282*0Sstevel@tonic-gate last_item = add_item(last_item, s, flags);
283*0Sstevel@tonic-gate while (s = lex(0)) {
284*0Sstevel@tonic-gate last_item = add_item(last_item, s, flags);
285*0Sstevel@tonic-gate }
286*0Sstevel@tonic-gate }
287*0Sstevel@tonic-gate if (pclose(fd) < 0) {
288*0Sstevel@tonic-gate fprintf(stderr, gettext("cachefspack: can't close pipe\n"));
289*0Sstevel@tonic-gate }
290*0Sstevel@tonic-gate
291*0Sstevel@tonic-gate if (olddir != NULL) {
292*0Sstevel@tonic-gate if (chdir(olddir) != 0) {
293*0Sstevel@tonic-gate fprintf(stderr, gettext("cannot return to %s: %s\n"),
294*0Sstevel@tonic-gate olddir, strerror(errno));
295*0Sstevel@tonic-gate exit(1);
296*0Sstevel@tonic-gate }
297*0Sstevel@tonic-gate free(olddir);
298*0Sstevel@tonic-gate }
299*0Sstevel@tonic-gate
300*0Sstevel@tonic-gate return (last_item);
301*0Sstevel@tonic-gate }
302*0Sstevel@tonic-gate
303*0Sstevel@tonic-gate void
getcmd(char * str,char * buf)304*0Sstevel@tonic-gate getcmd(char *str, char *buf)
305*0Sstevel@tonic-gate {
306*0Sstevel@tonic-gate char *s;
307*0Sstevel@tonic-gate
308*0Sstevel@tonic-gate strcpy(buf, str);
309*0Sstevel@tonic-gate strcat(buf, " ");
310*0Sstevel@tonic-gate while (s = lex(0)) {
311*0Sstevel@tonic-gate strcat(buf, s);
312*0Sstevel@tonic-gate strcat(buf, " ");
313*0Sstevel@tonic-gate }
314*0Sstevel@tonic-gate #ifdef DEBUG
315*0Sstevel@tonic-gate printf("getcmd: cmd = %s\n", buf);
316*0Sstevel@tonic-gate #endif /* DEBUG */
317*0Sstevel@tonic-gate }
318*0Sstevel@tonic-gate
319*0Sstevel@tonic-gate /*
320*0Sstevel@tonic-gate * routine:
321*0Sstevel@tonic-gate * lex
322*0Sstevel@tonic-gate *
323*0Sstevel@tonic-gate * purpose:
324*0Sstevel@tonic-gate * my own version of strtok that handles quoting and escaping
325*0Sstevel@tonic-gate *
326*0Sstevel@tonic-gate * parameters:
327*0Sstevel@tonic-gate * string to be lexed (or 0 for same string)
328*0Sstevel@tonic-gate *
329*0Sstevel@tonic-gate * returns:
330*0Sstevel@tonic-gate * pointer to next token
331*0Sstevel@tonic-gate *
332*0Sstevel@tonic-gate * notes:
333*0Sstevel@tonic-gate * this routine makes no changes to the string it is passed,
334*0Sstevel@tonic-gate * copying tokens into a static buffer.
335*0Sstevel@tonic-gate */
336*0Sstevel@tonic-gate char *
lex(FILE * fd)337*0Sstevel@tonic-gate lex(FILE *fd)
338*0Sstevel@tonic-gate { char c, delim;
339*0Sstevel@tonic-gate char *p;
340*0Sstevel@tonic-gate const char *s;
341*0Sstevel@tonic-gate static const char *savep = 0;
342*0Sstevel@tonic-gate static char namebuf[MAX_RULE_SZ];
343*0Sstevel@tonic-gate static char inbuf[MAX_RULE_SZ];
344*0Sstevel@tonic-gate int len, space_left;
345*0Sstevel@tonic-gate char *err;
346*0Sstevel@tonic-gate
347*0Sstevel@tonic-gate /*
348*0Sstevel@tonic-gate * if the file descriptor is non-zero read a new command. Otherwise
349*0Sstevel@tonic-gate * get fields from current line.
350*0Sstevel@tonic-gate */
351*0Sstevel@tonic-gate if (fd != 0) {
352*0Sstevel@tonic-gate len = 0;
353*0Sstevel@tonic-gate space_left = sizeof (inbuf);
354*0Sstevel@tonic-gate while ((err = fgets(&inbuf[len], space_left, fd)) != NULL) {
355*0Sstevel@tonic-gate len = strlen(inbuf);
356*0Sstevel@tonic-gate if (len == 1) {
357*0Sstevel@tonic-gate /*
358*0Sstevel@tonic-gate * must be a blank line starting command.
359*0Sstevel@tonic-gate * If a blank line occurs after the start of
360*0Sstevel@tonic-gate * a command, blanks will be included in the
361*0Sstevel@tonic-gate * command.
362*0Sstevel@tonic-gate */
363*0Sstevel@tonic-gate len = 0;
364*0Sstevel@tonic-gate continue;
365*0Sstevel@tonic-gate }
366*0Sstevel@tonic-gate len -= 2;
367*0Sstevel@tonic-gate space_left -= len;
368*0Sstevel@tonic-gate s = (char *)((int)inbuf + len);
369*0Sstevel@tonic-gate /*
370*0Sstevel@tonic-gate * Continuation character
371*0Sstevel@tonic-gate */
372*0Sstevel@tonic-gate if (strcmp(s, "\\\n") == 0) {
373*0Sstevel@tonic-gate continue;
374*0Sstevel@tonic-gate }
375*0Sstevel@tonic-gate break;
376*0Sstevel@tonic-gate }
377*0Sstevel@tonic-gate if (err == NULL) {
378*0Sstevel@tonic-gate return (err);
379*0Sstevel@tonic-gate }
380*0Sstevel@tonic-gate s = inbuf;
381*0Sstevel@tonic-gate } else {
382*0Sstevel@tonic-gate if (savep == 0)
383*0Sstevel@tonic-gate return (0);
384*0Sstevel@tonic-gate s = savep;
385*0Sstevel@tonic-gate }
386*0Sstevel@tonic-gate savep = 0;
387*0Sstevel@tonic-gate
388*0Sstevel@tonic-gate /* skip over leading white space */
389*0Sstevel@tonic-gate while (isspace(*s))
390*0Sstevel@tonic-gate s++;
391*0Sstevel@tonic-gate if (*s == 0) {
392*0Sstevel@tonic-gate return (0);
393*0Sstevel@tonic-gate }
394*0Sstevel@tonic-gate
395*0Sstevel@tonic-gate /* see if this is a quoted string */
396*0Sstevel@tonic-gate c = *s;
397*0Sstevel@tonic-gate if (c == '\'' || c == '"') {
398*0Sstevel@tonic-gate delim = c;
399*0Sstevel@tonic-gate s++;
400*0Sstevel@tonic-gate } else
401*0Sstevel@tonic-gate delim = 0;
402*0Sstevel@tonic-gate
403*0Sstevel@tonic-gate /* copy the token into the buffer */
404*0Sstevel@tonic-gate for (p = namebuf; (c = *s) != 0; s++) {
405*0Sstevel@tonic-gate if ((p - namebuf) >= sizeof (namebuf)) {
406*0Sstevel@tonic-gate savep = 0;
407*0Sstevel@tonic-gate return (0);
408*0Sstevel@tonic-gate }
409*0Sstevel@tonic-gate /* literal escape */
410*0Sstevel@tonic-gate if (c == '\\') {
411*0Sstevel@tonic-gate s++;
412*0Sstevel@tonic-gate *p++ = *s;
413*0Sstevel@tonic-gate continue;
414*0Sstevel@tonic-gate }
415*0Sstevel@tonic-gate
416*0Sstevel@tonic-gate /* closing delimiter */
417*0Sstevel@tonic-gate if (c == delim) {
418*0Sstevel@tonic-gate s++;
419*0Sstevel@tonic-gate break;
420*0Sstevel@tonic-gate }
421*0Sstevel@tonic-gate
422*0Sstevel@tonic-gate /* delimiting white space */
423*0Sstevel@tonic-gate if (delim == 0 && isspace(c))
424*0Sstevel@tonic-gate break;
425*0Sstevel@tonic-gate
426*0Sstevel@tonic-gate /* ordinary characters */
427*0Sstevel@tonic-gate *p++ = *s;
428*0Sstevel@tonic-gate }
429*0Sstevel@tonic-gate
430*0Sstevel@tonic-gate
431*0Sstevel@tonic-gate /* remember where we left off */
432*0Sstevel@tonic-gate savep = *s ? s : 0;
433*0Sstevel@tonic-gate
434*0Sstevel@tonic-gate /* null terminate and return the buffer */
435*0Sstevel@tonic-gate *p = 0;
436*0Sstevel@tonic-gate return (namebuf);
437*0Sstevel@tonic-gate }
438*0Sstevel@tonic-gate
439*0Sstevel@tonic-gate char *
mk_base_dir(char * path,char * linkpath)440*0Sstevel@tonic-gate mk_base_dir(char *path, char *linkpath)
441*0Sstevel@tonic-gate {
442*0Sstevel@tonic-gate static char pathb[MAXPATHLEN];
443*0Sstevel@tonic-gate char *dnam;
444*0Sstevel@tonic-gate char *get_dirname(char *);
445*0Sstevel@tonic-gate int len;
446*0Sstevel@tonic-gate
447*0Sstevel@tonic-gate /*
448*0Sstevel@tonic-gate * absolute path name
449*0Sstevel@tonic-gate */
450*0Sstevel@tonic-gate if (*linkpath == '/') {
451*0Sstevel@tonic-gate strcpy(pathb, linkpath);
452*0Sstevel@tonic-gate } else {
453*0Sstevel@tonic-gate /*
454*0Sstevel@tonic-gate * relative path
455*0Sstevel@tonic-gate */
456*0Sstevel@tonic-gate dnam = get_dirname(path);
457*0Sstevel@tonic-gate if (dnam == (char *)0) {
458*0Sstevel@tonic-gate return ((char *) 0);
459*0Sstevel@tonic-gate }
460*0Sstevel@tonic-gate strcpy(pathb, dnam);
461*0Sstevel@tonic-gate len = strlen(pathb);
462*0Sstevel@tonic-gate if (len == 0)
463*0Sstevel@tonic-gate return (pathb);
464*0Sstevel@tonic-gate if (pathb[len-1] != '/')
465*0Sstevel@tonic-gate strcat(pathb, "/");
466*0Sstevel@tonic-gate if (strncmp(linkpath, "../", 3) == 0) {
467*0Sstevel@tonic-gate /*
468*0Sstevel@tonic-gate * path is relative to directory containing sym link
469*0Sstevel@tonic-gate * remove "../" from beginning of linkpath
470*0Sstevel@tonic-gate */
471*0Sstevel@tonic-gate strcat(pathb, &linkpath[3]);
472*0Sstevel@tonic-gate } else {
473*0Sstevel@tonic-gate /*
474*0Sstevel@tonic-gate * path is relative to directory containing sym link
475*0Sstevel@tonic-gate */
476*0Sstevel@tonic-gate strcat(pathb, linkpath);
477*0Sstevel@tonic-gate }
478*0Sstevel@tonic-gate }
479*0Sstevel@tonic-gate return (pathb);
480*0Sstevel@tonic-gate }
481