sunx86-59-sysname-id-20040324
[openafs.git] / src / config / mc.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #define MAXLINELEN      1024
11 #define MAXTOKLEN       100
12 #include <sys/param.h>
13 #include <sys/types.h>
14 #include <sys/file.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17
18 #include <afsconfig.h>
19 #ifdef HAVE_STRING_H
20 #include <string.h>
21 #endif
22
23 #define TOK_DONTUSE 1           /* Don't copy if match and this flag is set. */
24 struct token {
25     struct token *next;
26     char *key;
27     int flags;
28 };
29
30 /* free token list returned by parseLine */
31 static int
32 FreeTokens(register struct token *alist)
33 {
34     register struct token *nlist;
35     for (; alist; alist = nlist) {
36         nlist = alist->next;
37         free(alist->key);
38         free(alist);
39     }
40     return 0;
41 }
42
43 #define space(x)    ((x) == ' ' || (x) == '\t' || (x) == '<' || (x) == '>')
44 static int
45 ParseLine(char *aline, struct token **alist)
46 {
47     char tbuffer[MAXTOKLEN + 1];
48     register char *tptr = NULL;
49     int inToken;
50     struct token *first, *last;
51     register struct token *ttok;
52     register int tc;
53     int dontUse = 0;
54
55     inToken = 0;                /* not copying token chars at start */
56     first = NULL;
57     last = NULL;
58     while (1) {
59         tc = *aline++;
60         if (tc == 0 || space(tc)) {     /* terminating null gets us in here, too */
61             if (inToken) {
62                 inToken = 0;    /* end of this token */
63                 if (!tptr)
64                     return -1;  /* should never get here */
65                 else
66                     *tptr++ = 0;
67                 ttok = (struct token *)malloc(sizeof(struct token));
68                 ttok->next = NULL;
69                 if (dontUse) {
70                     ttok->key = (char *)malloc(strlen(tbuffer));
71                     strcpy(ttok->key, tbuffer + 1);
72                     ttok->flags = TOK_DONTUSE;
73                     dontUse = 0;
74                 } else {
75                     ttok->key = (char *)malloc(strlen(tbuffer) + 1);
76                     strcpy(ttok->key, tbuffer);
77                     ttok->flags = 0;
78                 }
79                 if (last) {
80                     last->next = ttok;
81                     last = ttok;
82                 } else
83                     last = ttok;
84                 if (!first)
85                     first = ttok;
86             }
87         } else {
88             /* an alpha character */
89             if (!inToken) {
90                 if (tc == '-') {
91                     dontUse = 1;
92                 }
93                 tptr = tbuffer;
94                 inToken = 1;
95             }
96             if (tptr - tbuffer >= MAXTOKLEN)
97                 return -1;      /* token too long */
98             *tptr++ = tc;
99         }
100         if (tc == 0) {
101             /* last token flushed 'cause space(0) --> true */
102             if (last)
103                 last->next = NULL;
104             *alist = first;
105             return 0;
106         }
107     }
108 }
109
110 /* read a line into a buffer, putting in null termination and stopping on appropriate
111     end of line char.  Returns 0 at eof, > 0 at normal line end, and < 0 on error */
112 static int
113 GetLine(FILE * afile, register char *abuffer, int amax)
114 {
115     register int tc;
116     int first;
117
118     first = 1;
119     while (1) {
120         tc = getc(afile);
121         if (first && tc < 0)
122             return 0;
123         first = 0;
124         if (tc <= 0 || tc == '\012') {
125             if (amax > 0)
126                 *abuffer++ = 0;
127             return (amax > 0 ? 1 : -1);
128         }
129         if (amax > 0) {
130             /* keep reading to end of line so next one isn't bogus */
131             *abuffer++ = tc;
132             amax--;
133         }
134     }
135 }
136
137 int
138 mc_copy(register FILE * ain, register FILE * aout, char *alist[])
139 {
140     char tbuffer[MAXLINELEN];
141     struct token *tokens;
142     register char **tp;
143     register struct token *tt;
144     register int code;
145     int copying;
146     int done;
147
148     copying = 1;                /* start off copying data */
149     while (1) {
150         /* copy lines, handling modes appropriately */
151         code = GetLine(ain, tbuffer, MAXLINELEN);
152         if (code <= 0)
153             break;
154         /* otherwise process the line */
155         if (tbuffer[0] == '<') {
156             /* interpret the line as a set of options, any one of which will cause us
157              * to start copying the data again. */
158             code = ParseLine(tbuffer, &tokens);
159             if (code != 0)
160                 return -1;
161             copying = 0;
162             done = 0;
163             for (tp = alist; (!done) && (*tp != NULL); tp++) {
164                 for (tt = tokens; tt; tt = tt->next) {
165                     if (!strcmp(*tp, tt->key)) {
166                         /* Need to search all tokens in case a dont use
167                          * flag is set. But we can stop on the first
168                          * don't use.
169                          */
170                         if (tt->flags & TOK_DONTUSE) {
171                             copying = 0;
172                             done = 1;
173                             break;
174                         } else {
175                             copying = 1;
176                         }
177                     }
178                 }
179             }
180             FreeTokens(tokens);
181         } else {
182             /* just copy the line */
183             if (copying) {
184                 fwrite(tbuffer, 1, strlen(tbuffer), aout);
185                 putc('\n', aout);
186             }
187         }
188     }
189     return 0;
190 }