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