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