1 /* $OpenBSD: init.c,v 1.8 2005/04/11 07:12:03 deraadt Exp $ */
2
3 /*-
4 * Copyright (c) 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Peter McIlroy.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #ifndef lint
36 #if 0
37 static char sccsid[] = "@(#)init.c 8.1 (Berkeley) 6/6/93";
38 #else
39 static char rcsid[] = "$OpenBSD: init.c,v 1.8 2005/04/11 07:12:03 deraadt Exp $";
40 #endif
41 #endif /* not lint */
42
43 #include "sort.h"
44
45 #include <ctype.h>
46 #include <string.h>
47
48 extern struct coldesc *clist;
49 extern int ncols;
50 u_char gweights[NBINS];
51
52 static void insertcol(struct field *);
53 char *setcolumn(char *, struct field *, int);
54
55 /*
56 * clist (list of columns which correspond to one or more icol or tcol)
57 * is in increasing order of columns.
58 * Fields are kept in increasing order of fields.
59 */
60
61 /*
62 * keep clist in order--inserts a column in a sorted array
63 */
64 static void
insertcol(struct field * field)65 insertcol(struct field *field)
66 {
67 int i;
68 for (i = 0; i < ncols; i++)
69 if (field->icol.num <= clist[i].num)
70 break;
71 if (field->icol.num != clist[i].num) {
72 memmove(clist+i+1, clist+i, sizeof(COLDESC)*(ncols-i));
73 clist[i].num = field->icol.num;
74 ncols++;
75 }
76 if (field->tcol.num && field->tcol.num != field->icol.num) {
77 for (i = 0; i < ncols; i++)
78 if (field->tcol.num <= clist[i].num)
79 break;
80 if (field->tcol.num != clist[i].num) {
81 memmove(clist+i+1, clist+i,sizeof(COLDESC)*(ncols-i));
82 clist[i].num = field->tcol.num;
83 ncols++;
84 }
85 }
86 }
87
88 /*
89 * matches fields with the appropriate columns--n^2 but who cares?
90 */
91 void
fldreset(struct field * fldtab)92 fldreset(struct field *fldtab)
93 {
94 int i;
95 fldtab[0].tcol.p = clist+ncols-1;
96 for (++fldtab; fldtab->icol.num; ++fldtab) {
97 for (i = 0; fldtab->icol.num != clist[i].num; i++)
98 ;
99 fldtab->icol.p = clist + i;
100 if (!fldtab->tcol.num)
101 continue;
102 for (i = 0; fldtab->tcol.num != clist[i].num; i++)
103 ;
104 fldtab->tcol.p = clist + i;
105 }
106 }
107
108 /*
109 * interprets a column in a -k field
110 */
111 char *
setcolumn(char * pos,struct field * cur_fld,int gflag)112 setcolumn(char *pos, struct field *cur_fld, int gflag)
113 {
114 struct column *col;
115 int tmp;
116
117 col = cur_fld->icol.num ? (&(*cur_fld).tcol) : (&(*cur_fld).icol);
118 pos += sscanf(pos, "%d", &(col->num));
119 while (isdigit(*pos))
120 pos++;
121 if (col->num <= 0 && !(col->num == 0 && col == &(cur_fld->tcol)))
122 errx(2, "field numbers must be positive");
123 if (*pos == '.') {
124 if (!col->num)
125 errx(2, "cannot indent end of line");
126 pos += sscanf(++pos, "%d", &(col->indent));
127 while (isdigit(*pos))
128 pos++;
129 if (&cur_fld->icol == col)
130 col->indent--;
131 if (col->indent < 0)
132 errx(2, "illegal offset");
133 }
134 if (optval(*pos, cur_fld->tcol.num))
135 while ((tmp = optval(*pos, cur_fld->tcol.num))) {
136 cur_fld->flags |= tmp;
137 pos++;
138 }
139 if (cur_fld->icol.num == 0)
140 cur_fld->icol.num = 1;
141 return (pos);
142 }
143
144 int
setfield(char * pos,struct field * cur_fld,int gflag)145 setfield(char *pos, struct field *cur_fld, int gflag)
146 {
147 int tmp;
148 cur_fld->weights = ascii;
149 cur_fld->mask = alltable;
150 pos = setcolumn(pos, cur_fld, gflag);
151 if (*pos == '\0') /* key extends to EOL. */
152 cur_fld->tcol.num = 0;
153 else {
154 if (*pos != ',')
155 errx(2, "illegal field descriptor");
156 setcolumn((++pos), cur_fld, gflag);
157 }
158 if (!cur_fld->flags)
159 cur_fld->flags = gflag;
160 tmp = cur_fld->flags;
161
162 /*
163 * Assign appropriate mask table and weight table.
164 * If the global weights are reversed, the local field
165 * must be "re-reversed".
166 */
167 if (((tmp & R) ^ (gflag & R)) && tmp & F)
168 cur_fld->weights = RFtable;
169 else if (tmp & F)
170 cur_fld->weights = Ftable;
171 else if ((tmp & R) ^ (gflag & R))
172 cur_fld->weights = Rascii;
173 if (tmp & I)
174 cur_fld->mask = itable;
175 else if (tmp & D)
176 cur_fld->mask = dtable;
177 cur_fld->flags |= (gflag & (BI | BT));
178 if (!cur_fld->tcol.indent) /* BT has no meaning at end of field */
179 cur_fld->flags &= (D|F|I|N|R|BI);
180 if (cur_fld->tcol.num && !(!(cur_fld->flags & BI)
181 && cur_fld->flags & BT) && (cur_fld->tcol.num <= cur_fld->icol.num
182 && cur_fld->tcol.indent < cur_fld->icol.indent))
183 errx(2, "fields out of order");
184 insertcol(cur_fld);
185 return (cur_fld->tcol.num);
186 }
187
188 int
optval(int desc,int tcolflag)189 optval(int desc, int tcolflag)
190 {
191 switch(desc) {
192 case 'b':
193 if (!tcolflag)
194 return (BI);
195 else
196 return (BT);
197 case 'd': return (D);
198 case 'f': return (F);
199 case 'i': return (I);
200 case 'n': return (N);
201 case 'r': return (R);
202 default: return (0);
203 }
204 }
205
206 /*
207 * Convert obsolescent "+pos1 [-pos2]" format to POSIX -k form.
208 * Note that the conversion is tricky, see the manual for details.
209 */
210 void
fixit(int * argc,char ** argv)211 fixit(int *argc, char **argv)
212 {
213 int i, j;
214 long v, w, x;
215 char *p, *ep;
216 char buf[128], *bufp, *bufend;
217 size_t n;
218
219 bufend = buf + sizeof(buf);
220 for (i = 1; i < *argc; i++) {
221 if (argv[i][0] == '+') {
222 bufp = buf;
223 p = argv[i] + 1;
224 v = strtol(p, &ep, 10);
225 if (ep == p || v < 0 ||
226 (v == LONG_MAX && errno == ERANGE))
227 errx(2, "invalid field number");
228 p = ep;
229 if (*p == '.') {
230 x = strtol(++p, &ep, 10);
231 if (ep == p || x < 0 ||
232 (x == LONG_MAX && errno == ERANGE))
233 errx(2, "invalid field number");
234 p = ep;
235 n = snprintf(bufp, bufend - bufp, "-k%ld.%ld%s",
236 v+1, x+1, p);
237 } else {
238 n = snprintf(bufp, bufend - bufp, "-k%ld%s",
239 v+1, p);
240 }
241 if (n == -1 || n >= bufend - bufp)
242 errx(2, "bad field specification");
243 bufp += n;
244
245 if (argv[i+1] &&
246 argv[i+1][0] == '-' && isdigit(argv[i+1][1])) {
247 p = argv[i+1] + 1;
248 w = strtol(p, &ep, 10);
249 if (ep == p || w < 0 ||
250 (w == LONG_MAX && errno == ERANGE))
251 errx(2, "invalid field number");
252 p = ep;
253 x = 0;
254 if (*p == '.') {
255 x = strtol(++p, &ep, 10);
256 if (ep == p || x < 0 ||
257 (x == LONG_MAX && errno == ERANGE))
258 errx(2, "invalid field number");
259 p = ep;
260 }
261 if (x == 0) {
262 n = snprintf(bufp, bufend - bufp,
263 ",%ld%s", w, p);
264 } else {
265 n = snprintf(bufp, bufend - bufp,
266 ",%ld.%ld%s", w+1, x, p);
267 }
268 if (n == -1 || n >= bufend - bufp)
269 errx(2, "bad field specification");
270
271 /* shift over argv */
272 for (j = i+1; j < *argc; j++)
273 argv[j] = argv[j+1];
274 *argc -= 1;
275 }
276 if ((argv[i] = strdup(buf)) == NULL)
277 err(2, NULL);
278 }
279 }
280 }
281
282 /*
283 * ascii, Rascii, Ftable, and RFtable map
284 * REC_D -> REC_D; {not REC_D} -> {not REC_D}.
285 * gweights maps REC_D -> (0 or 255); {not REC_D} -> {not gweights[REC_D]}.
286 * Note: when sorting in forward order, to encode character zero in a key,
287 * use \001\001; character 1 becomes \001\002. In this case, character 0
288 * is reserved for the field delimiter. Analagously for -r (fld_d = 255).
289 * Note: this is only good for ASCII sorting. For different LC 's,
290 * all bets are off. See also num_init in number.c
291 */
292 void
settables(int gflags)293 settables(int gflags)
294 {
295 u_char *wts;
296 int i, incr;
297 for (i=0; i < 256; i++) {
298 ascii[i] = i;
299 if (i > REC_D && i < 255 - REC_D+1)
300 Rascii[i] = 255 - i + 1;
301 else
302 Rascii[i] = 255 - i;
303 if (islower(i)) {
304 Ftable[i] = Ftable[i- ('a' -'A')];
305 RFtable[i] = RFtable[i - ('a' - 'A')];
306 } else if (REC_D>= 'A' && REC_D < 'Z' && i < 'a' && i > REC_D) {
307 Ftable[i] = i + 1;
308 RFtable[i] = Rascii[i] - 1;
309 } else {
310 Ftable[i] = i;
311 RFtable[i] = Rascii[i];
312 }
313 alltable[i] = 1;
314 if (i == '\n' || isprint(i))
315 itable[i] = 1;
316 else itable[i] = 0;
317 if (i == '\n' || i == '\t' || i == ' ' || isalnum(i))
318 dtable[i] = 1;
319 else dtable[i] = 0;
320 }
321 Rascii[REC_D] = RFtable[REC_D] = REC_D;
322 if (REC_D >= 'A' && REC_D < 'Z')
323 Ftable[REC_D + ('a' - 'A')]++;
324 if (gflags & R && (!(gflags & F) || !SINGL_FLD))
325 wts = Rascii;
326 else if (!(gflags & F) || !SINGL_FLD)
327 wts = ascii;
328 else if (gflags & R)
329 wts = RFtable;
330 else
331 wts = Ftable;
332 memmove(gweights, wts, sizeof(gweights));
333 incr = (gflags & R) ? -1 : 1;
334 for (i = 0; i < REC_D; i++)
335 gweights[i] += incr;
336 gweights[REC_D] = ((gflags & R) ? 255 : 0);
337 if (SINGL_FLD && gflags & F) {
338 for (i = 0; i < REC_D; i++) {
339 ascii[i] += incr;
340 Rascii[i] += incr;
341 }
342 ascii[REC_D] = Rascii[REC_D] = gweights[REC_D];
343 }
344 }
345