1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 1997 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
31
32 #include "stdio.h"
33 #include "string.h"
34 #include "errno.h"
35 #include "sys/types.h"
36 #include "stdlib.h"
37
38 #include "lp.h"
39 #include "form.h"
40
41 extern struct {
42 char *v;
43 short len;
44 short infile;
45 } formheadings[];
46
47 #if defined(__STDC__)
48 int _search_fheading ( char * );
49 #else
50 int _search_fheading();
51 #endif
52
53 int
rdform(char * name,FORM * formp,int fd,int (* error_handler)(int,int,int),int * which_set)54 rdform(char *name, FORM *formp, int fd, int (*error_handler)( int , int , int ),
55 int *which_set)
56 {
57 char buf[BUFSIZ];
58
59 char * rest;
60 char * mandp;
61 char * dftp;
62 char * here;
63
64 int fld;
65 int have_line_already;
66 int found_alignment_pattern;
67 int size;
68 int add_size;
69 int linenum;
70 int i;
71
72 SCALED sdn;
73
74 register char * p;
75
76
77 /*
78 * Initialize the entire structure, to ensure no random
79 * values get in it. However, make sure some values won't
80 * be null or empty. Do the latter here as opposed to
81 * after reading the file, because sometimes the file
82 * contains an empty header to FORCE a null/empty value.
83 */
84 (void)memset ((char *)formp, 0, sizeof(*formp));
85 formp->name = Strdup(name);
86 formp->plen.val = DPLEN;
87 formp->plen.sc = 0;
88 formp->pwid.val = DPWIDTH;
89 formp->pwid.sc = 0;
90 formp->lpi.val = DLPITCH;
91 formp->lpi.sc = 0;
92 formp->cpi.val = DCPITCH;
93 formp->cpi.sc = 0;
94 formp->np = DNP;
95 formp->chset = Strdup(DCHSET);
96 formp->mandatory = 0;
97 formp->rcolor = Strdup(DRCOLOR);
98 formp->conttype = Strdup(DCONTYP);
99 formp->paper = NULL;
100 formp->isDefault = 0;
101
102 /*
103 * Read the file.
104 */
105
106 #define FGETS(B,S,F) (linenum++, fdgets(B,S,F))
107
108 have_line_already = 0;
109 found_alignment_pattern = 0;
110 linenum = 0;
111 errno = 0;
112 while (!found_alignment_pattern
113 && (have_line_already || FGETS(buf, BUFSIZ, fd))
114 ) {
115
116 int pos = strlen(buf) - 1;
117
118
119 have_line_already = 0;
120
121 while (isspace(buf[pos]))
122 buf[pos--] = 0;
123
124 fld = _search_fheading(buf);
125 if (fld >= FO_MAX) {
126 lp_errno = LP_EBADHDR;
127 BadFile: errno = EBADF;
128 if (error_handler) {
129 if ((*error_handler)(errno, lp_errno, linenum) == -1)
130 return (-1);
131 continue;
132 } else {
133 /*
134 * To allow future extensions to not
135 * impact applications using old versions
136 * of this routine, ignore strange fields.
137 */
138 continue;
139 }
140 }
141
142 p = buf + formheadings[fld].len;
143 while (isspace(*p))
144 p++;
145
146 if (which_set)
147 which_set[fld] = 1;
148
149 if (
150 formheadings[fld].infile
151 || error_handler
152 ) switch (fld) {
153
154 case FO_PLEN:
155 sdn = getsdn(p);
156 if (errno == EINVAL) {
157 lp_errno = LP_EBADSDN;
158 goto BadFile;
159 }
160 formp->plen = sdn;
161 break;
162
163 case FO_PWID:
164 sdn = getsdn(p);
165 if (errno == EINVAL) {
166 lp_errno = LP_EBADSDN;
167 goto BadFile;
168 }
169 formp->pwid = sdn;
170 break;
171
172 case FO_CPI:
173 sdn = getcpi(p);
174 if (errno == EINVAL) {
175 lp_errno = LP_EBADSDN;
176 goto BadFile;
177 }
178 formp->cpi = sdn;
179 break;
180
181 case FO_LPI:
182 sdn = getsdn(p);
183 if (errno == EINVAL) {
184 lp_errno = LP_EBADSDN;
185 goto BadFile;
186 }
187 formp->lpi = sdn;
188 break;
189
190 case FO_NP:
191 if (
192 (i = strtol(p, &rest, 10)) <= 0
193 || *rest
194 ) {
195 lp_errno = LP_EBADINT;
196 goto BadFile;
197 }
198 formp->np = i;
199 break;
200
201 case FO_CHSET:
202 if (!(mandp = strchr(p, ',')))
203 formp->mandatory = 0;
204 else {
205 do
206 *mandp++ = 0;
207 while (*mandp && isspace(*mandp));
208 if (CS_STREQU(MANSTR, mandp))
209 formp->mandatory = 1;
210 else {
211 lp_errno = LP_EBADARG;
212 goto BadFile;
213 }
214 }
215 if (!syn_name(p)) {
216 lp_errno = LP_EBADNAME;
217 goto BadFile;
218 }
219 if (formp->chset)
220 Free (formp->chset);
221 formp->chset = Strdup(p);
222 break;
223
224 case FO_RCOLOR:
225 if (formp->rcolor)
226 Free (formp->rcolor);
227 formp->rcolor = Strdup(p);
228 break;
229
230 case FO_CMT:
231 if (*p) {
232 lp_errno = LP_ETRAILIN;
233 goto BadFile;
234 }
235 if (formp->comment)
236 Free (formp->comment);
237 formp->comment = 0;
238 size = 0;
239 while (FGETS(buf, BUFSIZ, fd)) {
240 p = buf;
241
242 /*
243 * A recognized header ends the comment.
244 */
245 if (_search_fheading(p) < FO_MAX) {
246 have_line_already = 1;
247 break;
248 }
249
250 /*
251 * On the other hand, a '>' may hide what
252 * would otherwise look like a header.
253 */
254 if (
255 p[0] == '>'
256 && _search_fheading(p+1) < FO_MAX
257 )
258 p++;
259
260 /*
261 * (Re)allocate space to hold this
262 * (additional) line of the comment.
263 */
264 add_size = strlen(p);
265 if (formp->comment)
266 formp->comment = Realloc(
267 formp->comment,
268 size + add_size + 1
269 );
270 else
271 formp->comment = Malloc(
272 size + add_size + 1
273 );
274 if (!formp->comment) {
275 freeform (formp);
276 close(fd);
277 errno = ENOMEM;
278 return (-1);
279 }
280
281 /*
282 * Copy this (additional) line of the
283 * comment to the allocated space. "here"
284 * points to where to copy the line.
285 */
286 strcpy (formp->comment + size, p);
287 size += add_size;
288 }
289 if (errno != 0)
290 goto BadFile;
291
292 /*
293 * The comment is held internally without a
294 * trailing newline.
295 */
296 if (size && formp->comment[size - 1] == '\n')
297 formp->comment[size - 1] = 0;
298
299 break;
300
301 case FO_ALIGN:
302 if (*p) {
303 if (!syn_type(p)) {
304 lp_errno = LP_EBADCTYPE;
305 goto BadFile;
306 }
307 if (formp->conttype)
308 Free (formp->conttype);
309 formp->conttype = Strdup(p);
310 }
311
312 /*
313 * Actual alignment pattern has to be read in
314 * by caller; we leave the file pointer ready.
315 */
316 found_alignment_pattern = 1;
317 break;
318
319 case FO_PAPER:
320 if (!(dftp = strchr(p, ',')))
321 formp->isDefault = 0;
322 else {
323 do
324 *dftp++ = 0;
325 while (*dftp && isspace(*dftp));
326 if (CS_STREQU(DFTSTR, dftp))
327 formp->isDefault = 1;
328 else {
329 lp_errno = LP_EBADARG;
330 goto BadFile;
331 }
332 }
333 if (!syn_name(p)) {
334 lp_errno = LP_EBADNAME;
335 goto BadFile;
336 }
337 if (formp->paper)
338 Free (formp->paper);
339 formp->paper = Strdup(p);
340 break;
341 }
342
343 }
344 if (errno != 0) {
345 int save_errno = errno;
346
347 freeform (formp);
348 errno = save_errno;
349 return (-1);
350 }
351
352 /*
353 * Get the form description (if it exists) (?)
354 */
355 if (!error_handler) {
356
357 char * path;
358
359
360 if (!(path = getformfile(name, COMMENTFILE))) {
361 freeform (formp);
362 errno = ENOMEM;
363 return (-1);
364 }
365 if (
366 !(formp->comment = loadstring(path))
367 && errno != ENOENT
368 ) {
369 Free (path);
370 freeform (formp);
371 return (-1);
372 }
373 Free (path);
374 }
375
376 return (0);
377 }
378