Commit | Line | Data |
---|---|---|
805e021f CE |
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 | } |