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