cachemgr-setuerror-ifdef-cleanup-20020827
[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 FreeTokens(register struct token *alist)
32 {
33     register struct token *nlist;
34     for(; alist; alist = nlist) {
35         nlist = alist->next;
36         free(alist->key);
37         free(alist);
38     }
39     return 0;
40 }
41
42 #define space(x)    ((x) == ' ' || (x) == '\t' || (x) == '<' || (x) == '>')
43 static int ParseLine(char *aline, struct token **alist)
44 {
45     char tbuffer[MAXTOKLEN+1];
46     register char *tptr = NULL;
47     int inToken;
48     struct token *first, *last;
49     register struct token *ttok;
50     register int tc;
51     int dontUse = 0;
52     
53     inToken = 0;        /* not copying token chars at start */
54     first = NULL;
55     last = NULL;
56     while (1) {
57         tc = *aline++;
58         if (tc == 0 || space(tc)) {    /* terminating null gets us in here, too */
59             if (inToken) {
60                 inToken = 0;    /* end of this token */
61                 if ( !tptr )
62                     return -1; /* should never get here */
63                 else
64                     *tptr++ = 0;
65                 ttok = (struct token *) malloc(sizeof(struct token));
66                 ttok->next = NULL;
67                 if (dontUse) {
68                     ttok->key = (char *) malloc(strlen(tbuffer));
69                     strcpy(ttok->key, tbuffer+1);
70                     ttok->flags = TOK_DONTUSE;
71                     dontUse = 0;
72                 }
73                 else {
74                     ttok->key = (char *) malloc(strlen(tbuffer)+1);
75                     strcpy(ttok->key, tbuffer);
76                     ttok->flags = 0;
77                 }
78                 if (last) {
79                     last->next = ttok;
80                     last = ttok;
81                 }
82                 else last = ttok;
83                 if (!first) first = ttok;
84             }
85         }
86         else {
87             /* an alpha character */
88             if (!inToken) {
89                 if (tc == '-') {
90                     dontUse = 1;
91                 }
92                 tptr = tbuffer;
93                 inToken = 1;
94             }
95             if (tptr - tbuffer >= MAXTOKLEN) return -1;   /* token too long */
96             *tptr++ = tc;
97         }
98         if (tc == 0) {
99             /* last token flushed 'cause space(0) --> true */
100             if (last) last->next = NULL;
101             *alist = first;
102             return 0;
103         }
104     }
105 }
106 /* read a line into a buffer, putting in null termination and stopping on appropriate
107     end of line char.  Returns 0 at eof, > 0 at normal line end, and < 0 on error */
108 static int GetLine(FILE *afile, register char *abuffer, int amax)
109 {
110     register int tc;
111     int first;
112
113     first = 1;
114     while (1) {
115         tc = getc(afile);
116         if (first && tc < 0) return 0;
117         first = 0;
118         if (tc <= 0 || tc == '\012') {
119             if (amax > 0) *abuffer++ = 0;
120             return (amax > 0? 1 : -1);
121         }
122         if (amax > 0) {
123             /* keep reading to end of line so next one isn't bogus */
124             *abuffer++ = tc;
125             amax--;
126         }
127     }
128 }
129
130 int mc_copy(register FILE *ain, register FILE *aout, char *alist[])
131 {
132     char tbuffer[MAXLINELEN];
133     struct token *tokens;
134     register char **tp;
135     register struct token *tt;
136     register int code;
137     int copying;
138     int done;
139
140     copying = 1;        /* start off copying data */
141     while (1) {
142         /* copy lines, handling modes appropriately */
143         code = GetLine(ain, tbuffer, MAXLINELEN);
144         if (code <= 0) break;
145         /* otherwise process the line */
146         if (tbuffer[0] == '<') {
147             /* interpret the line as a set of options, any one of which will cause us
148                 to start copying the data again. */
149             code = ParseLine(tbuffer, &tokens);
150             if (code != 0) return -1;
151             copying = 0;
152             done = 0;
153             for(tp = alist; (!done) && (*tp != NULL) ; tp++) {
154                 for(tt = tokens; tt; tt=tt->next) {
155                     if (!strcmp(*tp, tt->key)) {
156                         /* Need to search all tokens in case a dont use
157                          * flag is set. But we can stop on the first
158                          * don't use.
159                          */
160                         if (tt->flags & TOK_DONTUSE) {
161                             copying = 0;
162                             done = 1;
163                             break;
164                         }
165                         else {
166                             copying = 1;
167                         }
168                     }
169                 }
170             }
171             FreeTokens(tokens);
172         }
173         else {
174             /* just copy the line */
175             if (copying) {
176                 fwrite(tbuffer, 1, strlen(tbuffer), aout);
177                 putc('\n', aout);
178             }
179         }
180     }
181     return 0;
182 }