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 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