1/* 2 * $Id: ppd.c,v 1.17 2009-10-14 02:24:05 didg Exp $ 3 * 4 * Copyright (c) 1995 Regents of The University of Michigan. 5 * All Rights Reserved. See COPYRIGHT. 6 */ 7 8#ifdef HAVE_CONFIG_H 9#include "config.h" 10#endif /* HAVE_CONFIG_H */ 11 12#include <stdio.h> 13#include <stdlib.h> 14#include <string.h> 15#include <errno.h> 16#include <atalk/logger.h> 17#include <sys/types.h> 18#include <sys/param.h> 19#include <sys/time.h> 20#include <netatalk/at.h> 21#include <atalk/atp.h> 22 23#include "printer.h" 24#include "ppd.h" 25 26struct ppd_font *ppd_fonts = NULL; 27 28struct ppd_feature ppd_features[] = { 29 { "*LanguageLevel", NULL }, 30 { "*PSVersion", NULL }, 31#ifdef HAVE_CUPS 32 { "*FreeVM", "33554432" }, 33#else 34 { "*FreeVM", NULL }, 35#endif 36 { "*Product", NULL }, 37 { "*PCFileName", NULL }, 38 { "*ModelName", NULL }, 39 { "*NickName", NULL }, 40 { "*ColorDevice", NULL }, 41 { "*FaxSupport", NULL }, 42 { "*TTRasterizer", NULL }, 43 { NULL, NULL }, 44}; 45 46struct ppdent { 47 char *pe_main; 48 char *pe_option; 49 char *pe_translation; 50 char *pe_value; 51}; 52 53#ifndef SHOWPPD 54static int ppd_inited; 55 56static void ppd_init(void) 57{ 58 if (ppd_inited) 59 return; 60 61 ppd_inited++; 62 63 if (printer->p_ppdfile) 64 read_ppd( printer->p_ppdfile, 0 ); 65} 66#endif /* SHOWPPD */ 67 68 69/* quick and ugly hack to be able to read 70 ppd files with Mac line ending */ 71static char* my_fgets(char *buf, size_t bufsize, FILE *stream) 72{ 73 int p; /* uninitialized, OK 310105 */ 74 size_t count = 0; 75 76 while (count < (bufsize - 1) && EOF != (p=fgetc(stream))) { 77 buf[count] = p; 78 count++; 79 if ( p == '\r' || p == '\n') 80 break; 81 } 82 83 if (p == EOF && count == 0) 84 return NULL; 85 86 /* translate line endings */ 87 if ( buf[count - 1] == '\r') 88 buf[count - 1] = '\n'; 89 90 buf[count] = 0; 91 return buf; 92} 93 94static struct ppdent *getppdent( FILE *stream) 95{ 96 static char buf[ 1024 ]; 97 static struct ppdent ppdent; 98 char *p, *q; 99 100 ppdent.pe_main = ppdent.pe_option = ppdent.pe_translation = 101 ppdent.pe_value = NULL; 102 103 while (( p = my_fgets( buf, sizeof( buf ), stream )) != NULL ) { 104 if ( *p != '*' ) { /* main key word */ 105 continue; 106 } 107 if ( p[ strlen( p ) - 1 ] != '\n') { 108 LOG(log_error, logtype_papd, "getppdent: line too long" ); 109 continue; 110 } 111 112 q = p; 113 while ( (*p != ' ') && (*p != '\t') && (*p != ':') && (*p != '\n') ) { 114 p++; 115 } 116 if ( (*( q + 1 ) == '%') || (*( q + 1 ) == '?') ) { /* comments & queries */ 117 continue; 118 } 119 ppdent.pe_main = q; 120 if ( *p == '\n' ) { 121 *p = '\0'; 122 ppdent.pe_option = ppdent.pe_translation = ppdent.pe_value = NULL; 123 return( &ppdent ); 124 } 125 126 if ( *p != ':' ) { /* option key word */ 127 *p++ = '\0'; 128 129 while ( (*p == ' ') || (*p == '\t') ) { 130 p++; 131 } 132 133 q = p; 134 while ( (*p != ':') && (*p != '/') && (*p != '\n') ) { 135 p++; 136 } 137 138 if ( *p == '\n' ) { 139 continue; 140 } 141 142 ppdent.pe_option = q; 143 if ( *p == '/' ) { /* translation string */ 144 *p++ = '\0'; 145 q = p; 146 while ( *p != ':' && *p != '\n' ) { 147 p++; 148 } 149 if ( *p != ':' ) { 150 continue; 151 } 152 153 ppdent.pe_translation = q; 154 } else { 155 ppdent.pe_translation = NULL; 156 } 157 } 158 *p++ = '\0'; 159 160 while ( (*p == ' ') || (*p == '\t') ) { 161 p++; 162 } 163 164 /* value */ 165 q = p; 166 while ( *p != '\n' ) { 167 p++; 168 } 169 *p = '\0'; 170 ppdent.pe_value = q; 171 172 return( &ppdent ); 173 } 174 175 return( NULL ); 176} 177 178int read_ppd(char *file, int fcnt) 179{ 180 FILE *ppdfile; 181 struct ppdent *pe; 182 struct ppd_feature *pfe; 183 struct ppd_font *pfo; 184 185 if ( fcnt > 20 ) { 186 LOG(log_error, logtype_papd, "read_ppd: %s: Too many files!", file ); 187 return( -1 ); 188 } 189 190 if (( ppdfile = fopen( file, "r" )) == NULL ) { 191 LOG(log_error, logtype_papd, "read_ppd %s: %s", file, strerror(errno) ); 192 return( -1 ); 193 } 194 195 while (( pe = getppdent( ppdfile )) != NULL ) { 196 /* *Include files */ 197 if ( strcmp( pe->pe_main, "*Include" ) == 0 ) { 198 read_ppd( pe->pe_value, fcnt + 1 ); 199 continue; 200 } 201 202 /* *Font */ 203 if ( strcmp( pe->pe_main, "*Font" ) == 0 && pe->pe_option ) { 204 for ( pfo = ppd_fonts; pfo; pfo = pfo->pd_next ) { 205 if ( strcmp( pfo->pd_font, pe->pe_option ) == 0 ) { 206 break; 207 } 208 } 209 if ( pfo ) { 210 continue; 211 } 212 213 if (( pfo = (struct ppd_font *)malloc( sizeof( struct ppd_font ))) 214 == NULL ) { 215 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) ); 216 exit( 1 ); 217 } 218 if (( pfo->pd_font = 219 (char *)malloc( strlen( pe->pe_option ) + 1 )) == NULL ) { 220 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) ); 221 exit( 1 ); 222 } 223 strcpy( pfo->pd_font, pe->pe_option ); 224 pfo->pd_next = ppd_fonts; 225 ppd_fonts = pfo; 226 continue; 227 } 228 229 230 /* Features */ 231 for ( pfe = ppd_features; pfe->pd_name; pfe++ ) { 232 if ( strcmp( pe->pe_main, pfe->pd_name ) == 0 ) { 233 break; 234 } 235 } 236 if ( pfe->pd_name && pe->pe_value ) { 237 if (( pfe->pd_value = 238 (char *)malloc( strlen( pe->pe_value ) + 1 )) == NULL ) { 239 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) ); 240 exit( 1 ); 241 } 242 243 strcpy( pfe->pd_value, pe->pe_value ); 244 continue; 245 } 246 } 247 248 fclose( ppdfile ); 249 return( 0 ); 250} 251 252struct ppd_font *ppd_font( char *font) 253{ 254 struct ppd_font *pfo; 255 256#ifndef SHOWPPD 257 if ( ! ppd_inited ) { 258 ppd_init(); 259 } 260#endif /* SHOWPPD */ 261 262 for ( pfo = ppd_fonts; pfo; pfo = pfo->pd_next ) { 263 if ( strcmp( pfo->pd_font, font ) == 0 ) { 264 return( pfo ); 265 } 266 } 267 return( NULL ); 268} 269 270struct ppd_feature *ppd_feature( const char *feature, int len) 271{ 272 struct ppd_feature *pfe; 273 char ppd_feature_main[ 256 ]; 274 const char *end, *p; 275 char *q; 276 277#ifndef SHOWPPD 278 if ( ! ppd_inited ) { 279 ppd_init(); 280 } 281#endif /* SHOWPPD */ 282 283 if (len > sizeof(ppd_feature_main) -1) 284 return( NULL ); 285 286 for ( end = feature + len, p = feature, q = ppd_feature_main; 287 (p <= end) && (*p != '\n') && (*p != '\r'); p++, q++ ) { 288 *q = *p; 289 } 290 if ( p > end ) { 291 return( NULL ); 292 } 293 *q = '\0'; 294 295 for ( pfe = ppd_features; pfe->pd_name; pfe++ ) { 296 if ( (strcmp( pfe->pd_name, ppd_feature_main ) == 0) && pfe->pd_value ) { 297 return( pfe ); 298 } 299 } 300 301 return( NULL ); 302} 303