4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved
29 * routines to examine and manipulate file names
32 * qualify ... ensure that a name is fully qualified
33 * expand ... expand env variables within a string or file name
34 * noblanks .. ensure that a name contains no embdded unescaped blanks
35 * lex ....... a lexer that can handle escaped/embedded blanks
36 * wildcards . see whether or not a name contains wild cards
37 * prefix .... does one string begin with another
38 * suffix .... does one string end with another
39 * contains .. does one string contain another
41 * cannonize (static) ... compress redundant "." and ".." out of name
44 * we are interested in embedded blanks because international
45 * character sets and non-unix file systems can both contain
46 * the byte 0x20. Thus, whenever we record a filename in
47 * file, we must be careful to escape any embedded blanks that
48 * cause trouble when we re-lex that file later.
61 static void cannonize(char *name
);
68 * to fully qualify a name
71 * name to be qualified
74 * either original pointer or copy to a new (malloced) buffer
77 * someday I may conclude that I should always make a copy
78 * so that the caller can know that it is safe to free the parm
80 * I thought about this and concluded that there is never a need
81 * to fully qualify a string containing variables. If the string
82 * came from the command line, the variables were already expanded
83 * and if it came from the rules data base it is required to already
89 char namebuf
[ MAX_PATH
];
91 /* in the simple case, the parameter is already there */
97 /* things that begin with variables get the benefit of the doubt */
103 /* start with the current working directory */
104 if (getcwd(namebuf
, sizeof (namebuf
)) == 0) {
105 fprintf(stderr
, gettext(ERR_nocwd
), name
);
109 /* make sure we have room for our file name */
110 if ((strlen(namebuf
) + strlen(name
) + 2) >= sizeof (namebuf
)) {
111 fprintf(stderr
, gettext(ERR_longname
), name
);
115 /* append the specified file name to it */
116 strcat(namebuf
, "/");
117 strcat(namebuf
, name
);
119 /* filter out redundant dots */
122 if (opt_debug
& DBG_VARS
)
123 fprintf(stderr
, "VARS: QUALIFY %s to %s\n", name
, namebuf
);
125 /* and return a newly malloc'd copy */
126 return (strdup(namebuf
));
134 * to expand variable names within a string
137 * string to be expanded. Variable references always begin
138 * with a $ and are delimited by parens or curleys.
141 * either original pointer or a copy to a new (malloced) buffer
144 * someday I may conclude that I should always make a copy
145 * so that the caller can know that it is safe to free the parm
147 * someday I may decide to support escape conventions for embedding
148 * $(){} in file names, but I suspec that day will never come.
150 * I thought about this and concluded there was no reason to
151 * fully qualify these names, because the only names that should
152 * need qualification are src/dst lines from the command line,
153 * and the shell should have handled those for me. Once something
154 * makes it into the database, it is expected to be fully qualified
157 * We are limited to producing strings of length MAX_PATH or less
158 * and variable names of length MAX_NAME or less. In practice,
159 * these limitations should not be a problem.
166 char namebuf
[ MAX_PATH
];
167 char varbuf
[ MAX_NAME
];
169 /* first see if there are no variables to be bound */
170 for (s
= name
; *s
&& *s
!= '$'; s
++);
174 /* move through the string, copying and expanding */
175 for (s
= name
, p
= namebuf
; *s
; s
++) {
177 /* check for overflow */
178 if (p
>= &namebuf
[ MAX_PATH
]) {
179 fprintf(stderr
, gettext(ERR_longname
), name
);
183 /* normal characters, we just copy */
189 /* figure out how the variable name is delimited */
194 } else if (delim
== '{') {
200 /* copy the variable name up to the closing delimiter */
201 for (v
= varbuf
; *s
; s
++) {
202 if (isalnum(*s
) || (*s
== '_') ||
203 (delim
&& *s
!= delim
))
208 /* make sure we don't overflow var name buffer */
209 if (v
>= &varbuf
[MAX_NAME
- 1]) {
211 fprintf(stderr
, gettext(ERR_longname
), varbuf
);
218 /* FIX THIS ... there must be a more elegant way */
219 /* we may have to back up because s will be bumped */
220 if (delim
== 0 || *s
!= delim
)
223 /* look up the variable */
225 if (v
== 0 || *v
== 0) {
226 fprintf(stderr
, gettext(ERR_undef
), varbuf
);
230 /* copy the variable into the buffer */
235 /* null terminate the copy */
238 /* compress out any redundant dots and dot-dots */
241 if (opt_debug
& DBG_VARS
)
242 fprintf(stderr
, "VARS: EXPAND %s to %s\n", name
, namebuf
);
244 /* and return a newly malloc'd copy */
245 return (strdup(namebuf
));
253 * to ensure that a name contains no unescaped embedded blanks
259 * pointer to name or pointer to buffer containing escaped version of name
262 * this routine can be called on full file names, and so can
263 * conceivably require an arbitrarily large buffer.
266 noblanks(const char *name
)
270 static char *namebuf
= 0;
271 static int buflen
= 0;
274 /* first see if there are no embedded blanks */
275 for (s
= name
; *s
&& *s
!= ' '; s
++);
279 /* make sure we have a buffer large enough for the worst case */
280 l
= 4 + (2*strlen(name
));
281 for (buflen
= MAX_PATH
; buflen
< l
; buflen
+= MAX_NAME
);
282 namebuf
= (char *) realloc(namebuf
, buflen
);
284 /* quote the name, and copy it, escaping quotes */
288 for (s
= name
; *s
; s
++) {
289 if (*s
== '"' || *s
== '\\')
305 * my own version of strtok that handles quoting and escaping
308 * FILE structure for file to read (0 for same string, same file)
311 * pointer to next token
314 * this routine makes no changes to the string it is passed,
315 * copying tokens into a static buffer.
317 * this routine handles continuation lines after reading and
318 * before the lexing even starts. This limits continued lines
319 * to a length of MAX_LINE, but keeps everything else very simple.
320 * We also, therefore, limit tokens to a maximum length of MAX_LINE.
322 int lex_linenum
; /* line number in current input file */
330 static char namebuf
[ MAX_LINE
];
331 static char inbuf
[ MAX_LINE
];
333 if (file
) { /* read a new line */
334 p
= inbuf
+ sizeof (inbuf
);
336 /* read the next input line, with all continuations */
337 for (s
= inbuf
; savep
= fgets(s
, p
- s
, file
); ) {
340 /* go find the last character of the input line */
346 /* see whether or not we need a continuation */
347 if (s
< inbuf
|| *s
!= '\\')
357 } else { /* continue with old line */
364 /* skip over leading white space */
370 /* see if this is a quoted string */
372 if (c
== '\'' || c
== '"') {
378 /* copy the token into the buffer */
379 for (p
= namebuf
; (c
= *s
) != 0; s
++) {
387 /* closing delimiter */
393 /* delimiting white space */
394 if (delim
== 0 && isspace(c
))
397 /* ordinary characters */
402 /* remember where we left off */
405 /* null terminate and return the buffer */
415 * determine whether or not there are any wild cards in a name
424 * we use this to take shortcuts
427 wildcards(const char *name
)
431 for (s
= name
; *s
; s
++)
434 case '\'': /* end of literal string */
437 case '\\': /* escape next character */
443 case '\'': /* literal string */
446 case '\\': /* escape next character */
453 /* any of these is a wild card */
465 * to compress redundant dots out of a path
468 * file name in an editable buffer
474 * because we compress the string in place, there is no danger
475 * of our overflowing any fixed sized buffer.
478 cannonize(char *name
)
481 /* leading dot-slashes */
482 for (s
= name
; *s
== '.' && s
[1] == '/'; strcpy(s
, &s
[2]));
484 for (s
= name
; *s
; s
++) {
485 /* interesting things happen after slashes */
489 /* embedded dot-slashes */
490 while (s
[1] == '.' && s
[2] == '/')
491 strcpy(&s
[1], &s
[3]);
493 /* embedded slash-dot-dot-slash */
494 if (strncmp(s
, "/../", 4) == 0) {
495 /* scan backwards to eliminate last directory */
496 for (p
= s
-1; p
> name
&& *p
!= '/'; p
--);
512 * determine whether or not one string begins with another
515 * string to be tested
520 * yes pointer character after prefix
523 prefix(const char *s
, const char *p
)
537 * determine whether or not one string ends with another
540 * string to be tested
547 suffix(const char *str
, const char *suf
)
550 /* go to where the alleged suffix would start */
551 for (s
= str
; *s
; s
++);
556 /* see if the string ends with the suffix */
569 * determine whether or not one string contains another
572 * string to be checked
573 * pattern we are seeking
579 contains(const char *str
, const char *pat
)
583 if (*str
++ == *pat
) {
584 for (s
= str
, p
= &pat
[1]; *s
== *p
; s
++, p
++)