[Debburn-devel] Rewritten config parser
Eduard Bloch
edi at gmx.de
Sat Sep 9 20:54:31 UTC 2006
#include <hallo.h>
As said on IRC, I have rewritten the config file parser of cdrkit to
make it more robust, more flexible and more user-friendly. You will
find the suggested change attaced, as files and as svn diff. Please
proofread and tell me if you find anythign suspicious, I hope that I
documented the code well enough.
Now it should accept all kinds of input which available before and
support more, like typical user mistakes: trailing spaces, spaces around
=, arbitrary number of whitespace instead of one single TAB, and, of
course, omiting the last values.
See attachement. I intend to commit it to the stable trunk RSN.
Eduard.
--
<Myon> TV ist Zeitverschwendung
* micsch muss auch nochmal seine TV-Karte einbauen
-------------- next part --------------
A non-text attachment was scrubbed...
Name: defaults.c
Type: text/x-csrc
Size: 7080 bytes
Desc: not available
Url : http://lists.alioth.debian.org/pipermail/debburn-devel/attachments/20060909/4ae31f31/defaults.c
-------------- next part --------------
A non-text attachment was scrubbed...
Name: defaults.h
Type: text/x-chdr
Size: 1423 bytes
Desc: not available
Url : http://lists.alioth.debian.org/pipermail/debburn-devel/attachments/20060909/4ae31f31/defaults.h
-------------- next part --------------
Index: cdrecord/defaults.c
===================================================================
--- cdrecord/defaults.c (Revision 243)
+++ cdrecord/defaults.c (Arbeitskopie)
@@ -1,24 +1,15 @@
-/*
- * This file has been modified for the cdrkit suite.
+/*
+ * Copyright 2006 Eduard Bloch
*
- * The behaviour and appearence of the program code below can differ to a major
- * extent from the version distributed by the original author(s).
+ * This code emulates the interface of the original defaults.c file. However,
+ * it improves its behaviour and deals with corner cases: prepended and
+ * trailing spaces on variable and value, no requirement for using TABs
+ * anymore. No requirements to insert dummy values like -1 or "".
*
- * For details, see Changelog file distributed with the cdrkit package. If you
- * received this file from another source then ask the distributing person for
- * a log of modifications.
- *
+ * FIXME, minor priority: implement alternative atoi function which returns
+ * custom values as "bad values" instead of 0
*/
-
-/* @(#)defaults.c 1.17 06/02/15 Copyright 1998-2005 J. Schilling */
-#ifndef lint
-static char sccsid[] =
- "@(#)defaults.c 1.17 06/02/15 Copyright 1998-2005 J. Schilling";
-#endif
/*
- * Copyright (c) 1998-2005 J. Schilling
- */
-/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
@@ -34,217 +25,195 @@
*/
#include <mconfig.h>
-#include <stdxlib.h>
-#include <unixstd.h>
-#include <strdefs.h>
+#include <stdlib.h>
#include <stdio.h>
-#include <standard.h>
-#include <deflts.h>
-#include <utypes.h>
-#include <schily.h>
-#include "cdrecord.h" /* only for getnum() */
#include "defaults.h"
+#include <ctype.h>
+#include <string.h>
-LOCAL int open_cdrdefaults __PR((void));
-EXPORT void cdr_defaults __PR((char **devp, int *speedp, long *fsp, char **drvoptp));
-LOCAL void cdr_xdefaults __PR((char **devp, int *speedp, long *fsp, char **drvoptp));
-LOCAL char * strsv __PR((char *s));
+#define CFGPATH "/etc/default/wodim"
+/* The better way would be exporting the meta functions to getnum.h or so */
+extern int getnum (char *arg, long *valp);
-LOCAL int
-open_cdrdefaults()
-{
- /*
- * WARNING you are only allowed to change this filename if you also
- * change the documentation and add a statement that makes clear
- * where the official location of the file is why you did choose a
- * nonstandard location and that the nonstandard location only refers
- * to inofficial cdrecord versions.
- *
- * I was forced to add this because some people change cdrecord without
- * rational reason and then publish the result. As those people
- * don't contribute work and don't give support, they are causing extra
- * work for me and this way slow down the cdrecord development.
- */
- return (defltopen("/etc/default/wodim"));
-}
+/*
+ * Warning, uses static line buffer, not reentrant. NULL returned if the key isn't found.
+ */
+static char *get_value(FILE *srcfile, char *key) {
+ static char linebuf[256];
-EXPORT void
-cdr_defaults(devp, speedp, fsp, drvoptp)
- char **devp;
- int *speedp;
- long *fsp;
- char **drvoptp;
-{
- char *dev = NULL;
- int speed = 0;
- long fs = 0L;
+ if(!srcfile)
+ return NULL;
- if (devp != NULL)
- dev = *devp;
- if (speedp != NULL)
- speed = *speedp;
- if (fsp != NULL)
- fs = *fsp;
+ rewind(srcfile);
+next_line:
+ while(fgets(linebuf, 256, srcfile)) {
+ int i;
+ int keybeg;
+ int s=0; /* state */
+ char *ret=NULL;
+ int lastchar=0;
- if (!dev && devp != NULL) {
- *devp = getenv("CDR_DEVICE");
+ for(i=0;i<256;) {
+ switch(s) {
+ case(0):
+ {
+ if(isspace(linebuf[i]))
+ i++;
+ else if(linebuf[i]=='\0' || linebuf[i] == '#')
+ goto next_line;
+ else {
+ s=1;
+ keybeg=i;
+ }
+ }
+ break;
+ case(1): /* compare the key */
+ {
+ if(key[i-keybeg]=='\0')
+ /* end of key, next state decides what to do on this position */
+ s=2;
+ else {
+ if(linebuf[i-keybeg]!=key[i-keybeg])
+ goto next_line;
+ else
+ i++;
+ }
+ }
+ break;
+ case(2): /* skip whitespace, stop on =, break on anything else */
+ {
+ if(isspace(linebuf[i]))
+ i++;
+ else if(linebuf[i]=='=') {
+ s=3;
+ i++;
+ }
+ else
+ goto next_line;
+ }
+ break;
+ case(3):
+ {
+ if(isspace(linebuf[i]))
+ i++;
+ else { /* beginning of value found */
+ lastchar=i;
+ ret= & linebuf[i];
+ s=4;
+ }
+ }
+ break;
+ case(4):
+ {
+ if(linebuf[i]) {
+ if(!isspace(linebuf[i]))
+ lastchar=i;
+ }
+ else { /* got string end, terminate after the last seen char */
+ linebuf[lastchar+1]='\0';
+ if(! *ret) // instead of empty string
+ return NULL;
+ return ret;
+ }
+ i++;
+ }
+ break;
+ }
+ }
+ }
+ return NULL;
+}
- if (!*devp && open_cdrdefaults() == 0) {
- dev = defltread("CDR_DEVICE=");
- if (dev != NULL)
- *devp = strsv(dev);
- }
- }
- if (devp != NULL && *devp)
- cdr_xdefaults(devp, &speed, &fs, drvoptp);
+void
+cdr_defaults(char **ppszDevice, int *piSpeed, long *plFifoSize, char *ppszDriverOptions) {
+ FILE *stream;
+ char *t; /* tmp */
+ int wc=0;
+ char loc[256], sSpeed[10], sFs[10], sOpts[80];
+ char *devcand=NULL;
- if (speed < 0) {
- char *p = getenv("CDR_SPEED");
+ stream=fopen(CFGPATH, "r");
- if (!p) {
- if (open_cdrdefaults() == 0) {
- p = defltread("CDR_SPEED=");
- }
- }
- if (p) {
- speed = atoi(p);
- if (speed < 0 && speed != -1) {
- comerrno(EX_BAD,
- "Bad speed environment (%s).\n", p);
- }
- }
- }
- if (speed >= 0 && speedp != NULL)
- *speedp = speed;
+ if(ppszDevice && *ppszDevice)
+ devcand=*ppszDevice;
+ else if(NULL!=(t=getenv("CDR_DEVICE")))
+ devcand=t;
+ else if(NULL!=(t=get_value(stream, "CDR_DEVICE")))
+ devcand=strdup(t); // needs to use it as a key later, same stat. memory
- if (fs < 0L) {
- char *p = getenv("CDR_FIFOSIZE");
+ if(devcand && NULL != (t=get_value(stream,devcand))) {
+ /* extract them now, may be used later */
+ wc=sscanf(t, "%256s %10s %10s %80s", loc, sSpeed, sFs, sOpts);
+ }
- if (!p) {
- if (open_cdrdefaults() == 0) {
- p = defltread("CDR_FIFOSIZE=");
- }
- }
- if (p) {
- if (getnum(p, &fs) != 1) {
- comerrno(EX_BAD,
- "Bad fifo size environment (%s).\n", p);
- }
- }
- }
- if (fs > 0L && fsp != NULL) {
- char *p = NULL;
- long maxfs;
+ if(ppszDevice) {
+ if(wc>0)
+ *ppszDevice = strdup(loc);
+ else if(devcand) // small mem. leak possible, does not matter, checks for that would require more code size than we loose
+ *ppszDevice=strdup(devcand);
+ }
+ if(piSpeed) { // sth. to write back
+ if(*piSpeed>0) {
+ /* ok, already set by the user */
+ }
+ else if(NULL!=(t=getenv("CDR_SPEED"))) {
+ *piSpeed=atoi(t);
+ if(*piSpeed<-1) {
+ fprintf(stderr, "Bad CDR_SPEED environment (%s).\n", t);
+ exit(EXIT_FAILURE);
+ }
+ }
+ else if(wc>1) {
+ *piSpeed=atoi(sSpeed);
+ if(*piSpeed<-1) {
+ fprintf(stderr, "Bad speed (%s) in the config, drive description.\n", sSpeed);
+ exit(EXIT_FAILURE);
+ }
+ }
+ else if(NULL!=(t=get_value(stream, "CDR_SPEED"))) {
+ *piSpeed=atoi(t);
+ if(*piSpeed<-1) {
+ fprintf(stderr, "Bad default CDR_SPEED setting (%s).\n", t);
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+ if(plFifoSize) { // sth. to write back
+ if(*plFifoSize>0) {
+ /* ok, already set by the user */
+ }
+ else if(NULL!=(t=getenv("CDR_FIFOSIZE"))) {
+ if(getnum(t, plFifoSize)!=1 || *plFifoSize<-1) {
+ fprintf(stderr, "Bad CDR_FIFOSIZE environment (%s).\n", t);
+ exit(EXIT_FAILURE);
+ }
+ }
+ else if(wc>2) {
+ if(getnum(sFs, plFifoSize)!=1 || *plFifoSize<-1) {
+ fprintf(stderr, "Bad fifo size (%s) in the config, device description.\n", sSpeed);
+ exit(EXIT_FAILURE);
+ }
+ }
+ else if(NULL!=(t=get_value(stream, "CDR_FIFOSIZE"))) {
+ if(getnum(t, plFifoSize)!=1 || *plFifoSize<-1) {
+ fprintf(stderr, "Bad speed default setting (%s).\n", t);
+ exit(EXIT_FAILURE);
+ }
+ }
+ /* undocumented option. Most likely to prevent killing Schily's underpowered
+ * machines (see docs) by allocating to much memory after doing a mistake
+ * in the config. */
+ if(NULL!=(t=get_value(stream, "CDR_MAXFIFOSIZE"))) {
+ long max;
+ if(getnum(t, &max)!=1 || *plFifoSize<-1) {
+ fprintf(stderr, "Bad CDR_MAXFIFOSIZE setting (%s).\n", t);
+ exit(EXIT_FAILURE);
+ }
+ if(*plFifoSize>max)
+ *plFifoSize=max;
+ }
+ }
+ if(ppszDriverOptions && !*ppszDriverOptions && wc>3 && strcmp(sOpts, "\"\""))
+ *ppszDriverOptions=strdup(sOpts);
- if (open_cdrdefaults() == 0) {
- p = defltread("CDR_MAXFIFOSIZE=");
- }
- if (p) {
- if (getnum(p, &maxfs) != 1) {
- comerrno(EX_BAD,
- "Bad max fifo size default (%s).\n", p);
- }
- if (fs > maxfs)
- fs = maxfs;
- }
- *fsp = fs;
- }
-
-
- defltclose();
}
-
-/*
- * All args execpt "drvoptp" are granted to be non NULL pointers.
- */
-LOCAL void
-cdr_xdefaults(devp, speedp, fsp, drvoptp)
- char **devp;
- int *speedp;
- long *fsp;
- char **drvoptp;
-{
- char dname[256];
- char *p = *devp;
- char *x = ",:/@";
-
- while (*x) {
- if (strchr(p, *x))
- return;
- x++;
- }
- js_snprintf(dname, sizeof (dname), "%s=", p);
- if (open_cdrdefaults() != 0)
- return;
-
- p = defltread(dname);
- if (p != NULL) {
- while (*p == '\t' || *p == ' ')
- p++;
- if ((x = strchr(p, '\t')) != NULL)
- *x = '\0';
- else if ((x = strchr(p, ' ')) != NULL)
- *x = '\0';
- *devp = strsv(p);
- if (x) {
- p = ++x;
- while (*p == '\t' || *p == ' ')
- p++;
- if ((x = strchr(p, '\t')) != NULL)
- *x = '\0';
- else if ((x = strchr(p, ' ')) != NULL)
- *x = '\0';
- if (*speedp < 0)
- *speedp = atoi(p);
- if (*speedp < 0 && *speedp != -1) {
- comerrno(EX_BAD,
- "Bad speed in defaults (%s).\n", p);
- }
- }
- if (x) {
- p = ++x;
- while (*p == '\t' || *p == ' ')
- p++;
- if ((x = strchr(p, '\t')) != NULL)
- *x = '\0';
- else if ((x = strchr(p, ' ')) != NULL)
- *x = '\0';
- if (*fsp < 0L) {
- if (getnum(p, fsp) != 1) {
- comerrno(EX_BAD,
- "Bad fifo size in defaults (%s).\n",
- p);
- }
- }
- }
- if (x) {
- p = ++x;
- while (*p == '\t' || *p == ' ')
- p++;
- if ((x = strchr(p, '\t')) != NULL)
- *x = '\0';
- else if ((x = strchr(p, ' ')) != NULL)
- *x = '\0';
- if (strcmp(p, "\"\"") != '\0') {
- /*
- * Driver opts found.
- */
- if (drvoptp && *drvoptp == NULL)
- *drvoptp = strsv(p);
- }
- }
- }
-}
-
-LOCAL char *
-strsv(s)
- char *s;
-{
- char *p;
- int len = strlen(s);
-
- p = malloc(len+1);
- if (p)
- strcpy(p, s);
- return (p);
-}
Index: cdrecord/defaults.h
===================================================================
--- cdrecord/defaults.h (Revision 243)
+++ cdrecord/defaults.h (Arbeitskopie)
@@ -36,6 +36,6 @@
/*
* defaults.c
*/
-extern void cdr_defaults __PR((char **devp, int *speedp, long *fsp, char **drvoptp));
+//extern void cdr_defaults __PR((char **devp, int *speedp, long *fsp, char **drvoptp));
#endif /* _DEFAULTS_H */
More information about the Debburn-devel
mailing list