1 /*****************************************************************************\
3 model.c - model parser for hplip devices
5 (c) 2006-2007 Copyright Hewlett-Packard Development Company, LP
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11 of the Software, and to permit persons to whom the Software is furnished to do
12 so, subject to the following conditions:
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 \*****************************************************************************/
30 #include <sys/types.h>
42 #define SECTION_SIZE 4096 /* Rough estimate of key/value section size in bytes. */
48 int valueSize; /* size of list in bytes */
49 char *value; /* list of key/value pairs */
50 struct list_head list;
53 static LabelRecord head; /* list of labels from include files */
54 static char homedir[255] = "";
56 static int GetPair(char *buf, int buf_len, char *key, char *value, char **tail)
65 for (; buf[i] != '\n' && i < buf_len; i++); /* eat comment line */
67 i++; /* bump past '\n' */
71 while ((buf[i] != '=') && (i < buf_len) && (j < HPMUD_LINE_SIZE))
73 for (j--; key[j] == ' ' && j > 0; j--); /* eat white space before = */
77 for (i++; buf[i] == ' ' && i < buf_len; i++); /* eat white space after = */
80 while ((buf[i] != '\n') && (i < buf_len) && (j < HPMUD_LINE_SIZE))
81 value[j++] = buf[i++];
82 for (j--; value[j] == ' ' && j > 0; j--); /* eat white space before \n */
86 i++; /* bump past '\n' */
89 *tail = buf + i; /* tail points to next line */
94 static int ReadConfig()
96 char key[HPMUD_LINE_SIZE];
97 char value[HPMUD_LINE_SIZE];
106 if((inFile = fopen(CONFDIR "/hplip.conf", "r")) == NULL)
108 BUG("unable to open %s: %m\n", CONFDIR "/hplip.conf");
114 /* Read the config file */
115 while ((fgets(rcbuf, sizeof(rcbuf), inFile) != NULL))
119 strncpy(section, rcbuf, sizeof(section)); /* found new section */
123 GetPair(rcbuf, strlen(rcbuf), key, value, &tail);
125 if ((strncasecmp(section, "[dirs]", 6) == 0) && (strcasecmp(key, "home") == 0))
127 strncpy(homedir, value, sizeof(homedir));
141 /* Find last occurance of y in x. */
142 static char *strrstr(const char *x, const char *y)
144 char *prev=NULL, *next;
147 return strchr(x, '\0');
149 while ((next = strstr(x, y)) != NULL)
157 static int CopyLabel(char *label, char *buf, int bufSize)
163 /* Look for label. */
164 list_for_each(p, &head.list)
166 pl = list_entry(p, LabelRecord, list);
167 if (strcasecmp(pl->name, label) == 0)
169 found = 1; /* found label */
176 BUG("error undefined label %s\n", label);
180 if (pl->valueSize > bufSize)
182 BUG("error label %s size=%d buf=%d\n", label, pl->valueSize, bufSize);
186 memcpy(buf, pl->value, pl->valueSize);
193 static int ResolveAttributes(FILE *fp, char *attr, int attrSize)
198 /* Process each key/value line. */
204 ungetc(ch, fp); /* found new section, done with current section */
208 if (ch == '#' || ch == ' ')
210 while ((ch = fgetc(fp)) != '\n' && ch != EOF); /* skip line */
214 /* skip blank line */
219 while ((ch = fgetc(fp)) != '\n' && ch != EOF) /* get label */
221 if (j < sizeof(label)-1)
225 i += CopyLabel(label, attr+i, attrSize-i);
231 while ((ch = fgetc(fp)) != '\n' && ch != EOF) /* get key/value line */
241 ch = fgetc(fp); /* bump to next line */
245 attr[i] = 0; /* terminate string */
249 static int RegisterLabel(FILE *fp, char *incFile, char *label)
253 char buf[SECTION_SIZE];
256 /* Look for duplicate label. */
257 list_for_each(p, &head.list)
259 pl = list_entry(p, LabelRecord, list);
260 if (strcasecmp(pl->name, label) == 0)
262 BUG("error duplicate label %s\n", label);
267 if ((pl = (LabelRecord *)malloc(sizeof(LabelRecord))) == NULL)
269 BUG("unable to creat label record: %m\n");
273 pl->incFile = strdup(incFile);
274 pl->name = strdup(label);
276 /* Process each key/value line. */
282 ungetc(ch, fp); /* found new section, done with label */
286 if (ch == '#' || ch == ' ')
288 while ((ch = fgetc(fp)) != '\n' && ch != EOF); /* skip line */
292 /* skip blank line */
296 if (i < SECTION_SIZE-1)
298 while ((ch = fgetc(fp)) != '\n' && ch != EOF) /* get key/value line */
300 if (i < SECTION_SIZE-1)
303 if (i < SECTION_SIZE-1)
308 ch = fgetc(fp); /* bump to next line */
312 buf[i] = 0; /* terminate string */
314 pl->value = strdup(buf);
315 pl->valueSize = i; /* size does not include zero termination */
317 list_add(&(pl->list), &(head.list));
325 static int UnRegisterLabel(LabelRecord *pl)
333 list_del(&(pl->list));
340 struct list_head *p, *n;
343 /* Remove each label. */
344 list_for_each_safe(p, n, &head.list)
346 pl = list_entry(p, LabelRecord, list);
352 /* Parse *.inc file. */
353 static int ParseInc(char *incFile)
362 /* Look for duplicate include file. */
363 list_for_each(p, &head.list)
365 pl = list_entry(p, LabelRecord, list);
366 if (strcmp(pl->incFile, incFile) == 0)
368 BUG("error duplicate include file %s\n", incFile);
373 if ((fp = fopen(incFile, "r")) == NULL)
375 BUG("open %s failed: %m\n", incFile);
381 /* Read the *.inc file, check each line for new label. */
382 while ((fgets(rcbuf, sizeof(rcbuf), fp) != NULL))
386 strncpy(section, rcbuf+1, sizeof(section)); /* found new section */
388 section[n-2]=0; /* remove ']' and CR */
389 RegisterLabel(fp, incFile, section);
401 /* Parse *.dat file. */
402 static int ParseFile(char *datFile, char *model, char *attr, int attrSize, int *bytes_read)
410 if ((fp = fopen(datFile, "r")) == NULL)
415 /* Read the *.dat file, check each line for model match. */
416 while ((fgets(rcbuf, sizeof(rcbuf), fp) != NULL))
420 strncpy(section, rcbuf+1, sizeof(section)); /* found new section */
422 section[n-2]=0; /* remove ']' and CR */
423 if (strcasecmp(model, section) == 0)
425 /* Found model match. */
426 *bytes_read = ResolveAttributes(fp, attr, attrSize);
431 else if (strncmp(rcbuf, "%include", 8) == 0)
433 strncpy(file, datFile, sizeof(file)); /* get dirname from *.dat file */
434 n = strrstr(file, "/") - file + 1;
435 strncpy(file+n, rcbuf+9, sizeof(file)-n); /* concatenate include filename to dirname */
437 file[n-1]=0; /* remove CR */
449 /* Parse and convert all known key value pairs in buffer. Do sanity check on values. */
450 static int parse_key_value_pair(char *buf, int len, struct hpmud_model_attributes *ma)
452 char key[HPMUD_LINE_SIZE];
453 char value[HPMUD_LINE_SIZE];
455 int i=0, ret=HPMUD_R_OK;
457 ma->prt_mode = HPMUD_RAW_MODE;
458 ma->mfp_mode = HPMUD_DOT4_MODE;
460 ma->statustype = HPMUD_STATUSTYPE_SFIELD;
461 ma->support = HPMUD_SUPPORT_TYPE_NONE;
464 return HPMUD_R_OK; /* initialize ma */
470 i += GetPair(tail, len-i, key, value, &tail);
472 if (strcasecmp(key, "io-mode") == 0)
474 ma->prt_mode = strtol(value, &tail2, 10); /* uni | raw | mlc */
476 else if (strcasecmp(key, "io-mfp-mode") == 0)
478 ma->mfp_mode = strtol(value, &tail2, 10); /* mfc | dot4 */
480 else if(strcasecmp(key, "scan-type") == 0)
482 ma->scantype = strtol(value, &tail2, 10); /*SCL, PML, SOAP, MARVELL, LEDM*/
484 else if(strcasecmp(key, "scan-src") == 0)
486 ma->scansrc = strtol(value, &tail2, 10); /*Flatbed, ADF, Camera or combination of these*/
488 else if(strcasecmp(key, "status-type") == 0)
490 ma->statustype = strtol(value, &tail2, 10);
492 else if(strcasecmp(key, "support-type") == 0)
494 ma->support = strtol(value, &tail2, 10);
496 else if(strcasecmp(key, "plugin") == 0)
498 ma->plugin = strtol(value, &tail2, 10);
502 /* Unknown keys are ignored (R_AOK). */
504 } // end while (i < len)
509 /* Request device model attributes for URI. Return all attributes. */
510 enum HPMUD_RESULT hpmud_get_model_attributes(char *uri, char *attr, int attrSize, int *bytes_read)
515 enum HPMUD_RESULT stat = HPMUD_R_DATFILE_ERROR;
517 memset(attr, 0, attrSize);
519 INIT_LIST_HEAD(&head.list);
524 hpmud_get_uri_model(uri, model, sizeof(model));
526 /* Search /data/models.dat file for specified model. */
527 snprintf(sz, sizeof(sz), "%s/data/models/models.dat", homedir);
528 found = ParseFile(sz, model, attr, attrSize, bytes_read); /* save any labels in *.inc files */
532 BUG("no %s attributes found in %s\n", model, sz);
534 DelList(); /* Unregister all labels. */
536 /* Search /data/models/unreleased/unreleased.dat file for specified model. */
537 snprintf(sz, sizeof(sz), "%s/data/models/unreleased/unreleased.dat", homedir);
538 found = ParseFile(sz, model, attr, attrSize, bytes_read); /* save any *.inc files */
543 BUG("no %s attributes found in %s\n", model, sz);
550 DelList(); /* Unregister all labels. */
554 /* Request device model attributes for URI. Return filled in hpmud_model_attributes structure. */
555 enum HPMUD_RESULT hpmud_query_model(char *uri, struct hpmud_model_attributes *ma)
557 char buf[SECTION_SIZE];
559 enum HPMUD_RESULT stat = HPMUD_R_DATFILE_ERROR;
561 parse_key_value_pair(NULL, 0, ma); /* set ma defaults */
563 if (hpmud_get_model_attributes(uri, buf, sizeof(buf), &len) != 0)
564 goto bugout; /* model not found, return ma defaults */
566 parse_key_value_pair(buf, len, ma);
575 /* Get value for specified section and key from hplip.conf. */
576 enum HPMUD_RESULT hpmud_get_conf(const char *section, const char *key, char *value, int value_size)
578 return hpmud_get_key_value(CONFDIR "/hplip.conf", section, key, value, value_size);
581 /* Get value for specified section and key from specified file. */
582 enum HPMUD_RESULT hpmud_get_key_value(const char *file, const char *section, const char *key, char *value, int value_size)
584 char new_key[HPMUD_LINE_SIZE];
585 char new_value[HPMUD_LINE_SIZE];
587 char new_section[32];
590 enum HPMUD_RESULT stat = HPMUD_R_DATFILE_ERROR;
593 if((inFile = fopen(file, "r")) == NULL)
595 BUG("unable to open %s: %m\n", file);
601 /* Read the config file */
602 while ((fgets(rcbuf, sizeof(rcbuf), inFile) != NULL))
607 while ((rcbuf[i] != ']') && (j < (sizeof(new_section)-2)))
608 new_section[j++] = rcbuf[i++];
609 new_section[j++] = rcbuf[i++]; /* ']' */
610 new_section[j] = 0; /* zero terminate */
614 GetPair(rcbuf, strlen(rcbuf), new_key, new_value, &tail);
616 if ((strcasecmp(new_section, section) == 0) && (strcasecmp(new_key, key) == 0))
618 strncpy(value, new_value, value_size);
624 if (stat != HPMUD_R_OK)
625 BUG("unable to find %s %s in %s\n", section, key, file);