1
0
mirror of https://gitlab.xiph.org/xiph/ezstream.git synced 2024-09-15 04:08:07 -04:00

Improve string to integer conversion stuff, and have another stab at the config

file parsing. Ezstream now prints each error it can find and then bails out,
instead of bailing out on the first error. Tweak URL parsing as well, and do
some cosmetic changes to the error messages.


git-svn-id: https://svn.xiph.org/trunk/ezstream@12603 0101bb08-14d6-0310-b084-bc0e0c8e3800
This commit is contained in:
moritz 2007-03-02 12:52:10 +00:00
parent 956f674a44
commit 539bb39322
9 changed files with 294 additions and 132 deletions

View File

@ -71,7 +71,7 @@ dnl LIBRARY FUNCTIONS
AC_CHECK_LIB(gen, basename) AC_CHECK_LIB(gen, basename)
AC_CHECK_FUNCS(arc4random gettimeofday random srandomdev stat) AC_CHECK_FUNCS(arc4random gettimeofday random srandomdev stat)
AC_REPLACE_FUNCS(getopt strlcat strlcpy) AC_REPLACE_FUNCS(getopt strlcat strlcpy strtonum)
if test x"$ac_cv_header_signal_h" = "xyes"; then if test x"$ac_cv_header_signal_h" = "xyes"; then
AC_CHECK_FUNCS([sigaction], [ AC_CHECK_FUNCS([sigaction], [
AC_DEFINE(HAVE_SIGNALS, 1, [Define whether we have BSD signals]) AC_DEFINE(HAVE_SIGNALS, 1, [Define whether we have BSD signals])

View File

@ -8,6 +8,6 @@ ezstream_LDADD = @LIBOBJS@ @XIPH_LIBS@
AM_CFLAGS = @XIPH_CFLAGS@ AM_CFLAGS = @XIPH_CFLAGS@
AM_CPPFLAGS = @XIPH_CPPFLAGS@ AM_CPPFLAGS = @XIPH_CPPFLAGS@
EXTRA_DIST = configfile.h getopt.h playlist.h strlfctns.h util.h EXTRA_DIST = configfile.h getopt.h playlist.h strfctns.h util.h
CLEANFILES = core *.core *~ .*~ CLEANFILES = core *.core *~ .*~

View File

@ -28,12 +28,15 @@
#include <string.h> #include <string.h>
#include "configfile.h" #include "configfile.h"
#include "strfctns.h"
#include "util.h" #include "util.h"
#ifndef PATH_MAX #ifndef PATH_MAX
# define PATH_MAX 256 # define PATH_MAX 256
#endif #endif
extern char *__progname;
static EZCONFIG ezConfig; static EZCONFIG ezConfig;
static const char *blankString = ""; static const char *blankString = "";
@ -142,6 +145,7 @@ parseConfig(const char *fileName)
char *ls_xmlContentPtr; char *ls_xmlContentPtr;
int program_set, reconnect_set, shuffle_set, int program_set, reconnect_set, shuffle_set,
streamOnce_set, svrinfopublic_set; streamOnce_set, svrinfopublic_set;
unsigned int config_error;
xmlLineNumbersDefault(1); xmlLineNumbersDefault(1);
if ((doc = xmlParseFile(fileName)) == NULL) { if ((doc = xmlParseFile(fileName)) == NULL) {
@ -159,6 +163,7 @@ parseConfig(const char *fileName)
memset(&ezConfig, '\000', sizeof(ezConfig)); memset(&ezConfig, '\000', sizeof(ezConfig));
config_error = 0;
program_set = 0; program_set = 0;
reconnect_set = 0; reconnect_set = 0;
shuffle_set = 0; shuffle_set = 0;
@ -168,9 +173,10 @@ parseConfig(const char *fileName)
while (cur != NULL) { while (cur != NULL) {
if (!xmlStrcmp(cur->name, BAD_CAST "url")) { if (!xmlStrcmp(cur->name, BAD_CAST "url")) {
if (ezConfig.URL != NULL) { if (ezConfig.URL != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <url> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <url> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
@ -180,9 +186,10 @@ parseConfig(const char *fileName)
} }
if (!xmlStrcmp(cur->name, BAD_CAST "sourcepassword")) { if (!xmlStrcmp(cur->name, BAD_CAST "sourcepassword")) {
if (ezConfig.password != NULL) { if (ezConfig.password != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <sourcepassword> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <sourcepassword> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
@ -192,9 +199,10 @@ parseConfig(const char *fileName)
} }
if (!xmlStrcmp(cur->name, BAD_CAST "format")) { if (!xmlStrcmp(cur->name, BAD_CAST "format")) {
if (ezConfig.format != NULL) { if (ezConfig.format != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <format> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <format> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
char *p; char *p;
@ -208,16 +216,18 @@ parseConfig(const char *fileName)
} }
if (!xmlStrcmp(cur->name, BAD_CAST "filename")) { if (!xmlStrcmp(cur->name, BAD_CAST "filename")) {
if (ezConfig.fileName != NULL) { if (ezConfig.fileName != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <filename> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <filename> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
if (strlen(ls_xmlContentPtr) > PATH_MAX - 1) { if (strlen(ls_xmlContentPtr) > PATH_MAX - 1) {
printf("%s[%ld]: Error: Path or filename in <filename> is too long.\n", printf("%s[%ld]: Error: Path or filename in <filename> is too long\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
ezConfig.fileName = xstrdup(ls_xmlContentPtr); ezConfig.fileName = xstrdup(ls_xmlContentPtr);
xmlFree(ls_xmlContentPtr); xmlFree(ls_xmlContentPtr);
@ -225,70 +235,98 @@ parseConfig(const char *fileName)
} }
if (!xmlStrcmp(cur->name, BAD_CAST "playlist_program")) { if (!xmlStrcmp(cur->name, BAD_CAST "playlist_program")) {
if (program_set) { if (program_set) {
printf("%s[%ld]: Error: Cannot have multiple <playlist_program> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <playlist_program> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
int tmp; const char *errstr;
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
tmp = atoi(ls_xmlContentPtr); ezConfig.fileNameIsProgram = strtonum(ls_xmlContentPtr, 0, 1, &errstr);
ezConfig.fileNameIsProgram = (tmp == 0) ? 0 : 1; if (errstr) {
printf("%s[%ld]: Error: <playlist_program> may only contain 1 or 0\n",
fileName, xmlGetLineNo(cur));
config_error++;
continue;
}
xmlFree(ls_xmlContentPtr); xmlFree(ls_xmlContentPtr);
program_set = 1; program_set = 1;
} }
} }
if (!xmlStrcmp(cur->name, BAD_CAST "shuffle")) { if (!xmlStrcmp(cur->name, BAD_CAST "shuffle")) {
if (shuffle_set) { if (shuffle_set) {
printf("%s[%ld]: Error: Cannot have multiple <shuffle> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <shuffle> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
int tmp; const char *errstr;
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
tmp = atoi(ls_xmlContentPtr); ezConfig.shuffle = strtonum(ls_xmlContentPtr, 0, 1, &errstr);
ezConfig.shuffle = (tmp == 0) ? 0 : 1; if (errstr) {
printf("%s[%ld]: Error: <shuffle> may only contain 1 or 0\n",
fileName, xmlGetLineNo(cur));
config_error++;
continue;
}
xmlFree(ls_xmlContentPtr); xmlFree(ls_xmlContentPtr);
shuffle_set = 1; shuffle_set = 1;
} }
} }
if (!xmlStrcmp(cur->name, BAD_CAST "stream_once")) { if (!xmlStrcmp(cur->name, BAD_CAST "stream_once")) {
if (streamOnce_set) { if (streamOnce_set) {
printf("%s[%ld]: Error: Cannot have multiple <stream_once> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <stream_once> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
int tmp; const char *errstr;
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
tmp = atoi(ls_xmlContentPtr); ezConfig.streamOnce = strtonum(ls_xmlContentPtr, 0, 1, &errstr);
ezConfig.streamOnce = (tmp == 0) ? 0 : 1; if (errstr) {
printf("%s[%ld]: Error: <stream_once> may only contain 1 or 0\n",
fileName, xmlGetLineNo(cur));
config_error++;
continue;
}
xmlFree(ls_xmlContentPtr); xmlFree(ls_xmlContentPtr);
streamOnce_set = 1; streamOnce_set = 1;
} }
} }
if (!xmlStrcmp(cur->name, BAD_CAST "reconnect_tries")) { if (!xmlStrcmp(cur->name, BAD_CAST "reconnect_tries")) {
if (reconnect_set) { if (reconnect_set) {
printf("%s[%ld]: Error: Cannot have multiple <reconnect_tries> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <reconnect_tries> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
const char *errstr;
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
ezConfig.reconnectAttempts = atoi(ls_xmlContentPtr); ezConfig.reconnectAttempts = strtonum(ls_xmlContentPtr, 0, UINT_MAX, &errstr);
if (errstr) {
printf("%s[%ld]: Error: In <reconnect_tries>: '%s' is %s\n",
fileName, xmlGetLineNo(cur), ls_xmlContentPtr, errstr);
config_error++;
continue;
}
xmlFree(ls_xmlContentPtr); xmlFree(ls_xmlContentPtr);
reconnect_set = 1; reconnect_set = 1;
} }
} }
if (!xmlStrcmp(cur->name, BAD_CAST "svrinfoname")) { if (!xmlStrcmp(cur->name, BAD_CAST "svrinfoname")) {
if (ezConfig.serverName != NULL) { if (ezConfig.serverName != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <svrinfoname> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <svrinfoname> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
@ -298,9 +336,10 @@ parseConfig(const char *fileName)
} }
if (!xmlStrcmp(cur->name, BAD_CAST "svrinfourl")) { if (!xmlStrcmp(cur->name, BAD_CAST "svrinfourl")) {
if (ezConfig.serverURL != NULL) { if (ezConfig.serverURL != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <svrinfourl> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <svrinfourl> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
@ -310,9 +349,10 @@ parseConfig(const char *fileName)
} }
if (!xmlStrcmp(cur->name, BAD_CAST "svrinfogenre")) { if (!xmlStrcmp(cur->name, BAD_CAST "svrinfogenre")) {
if (ezConfig.serverGenre != NULL) { if (ezConfig.serverGenre != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <svrinfogenre> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <svrinfogenre> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
@ -322,9 +362,10 @@ parseConfig(const char *fileName)
} }
if (!xmlStrcmp(cur->name, BAD_CAST "svrinfodescription")) { if (!xmlStrcmp(cur->name, BAD_CAST "svrinfodescription")) {
if (ezConfig.serverDescription != NULL) { if (ezConfig.serverDescription != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <svrinfodescription> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <svrinfodescription> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
@ -334,9 +375,10 @@ parseConfig(const char *fileName)
} }
if (!xmlStrcmp(cur->name, BAD_CAST "svrinfobitrate")) { if (!xmlStrcmp(cur->name, BAD_CAST "svrinfobitrate")) {
if (ezConfig.serverBitrate != NULL) { if (ezConfig.serverBitrate != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <svrinfobitrate> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <svrinfobitrate> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
@ -347,9 +389,10 @@ parseConfig(const char *fileName)
if (!xmlStrcmp(cur->name, BAD_CAST "svrinfochannels")) { if (!xmlStrcmp(cur->name, BAD_CAST "svrinfochannels")) {
if (ezConfig.serverChannels != NULL) { if (ezConfig.serverChannels != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <svrinfochannels> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <svrinfochannels> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
@ -359,9 +402,10 @@ parseConfig(const char *fileName)
} }
if (!xmlStrcmp(cur->name, BAD_CAST "svrinfosamplerate")) { if (!xmlStrcmp(cur->name, BAD_CAST "svrinfosamplerate")) {
if (ezConfig.serverSamplerate != NULL) { if (ezConfig.serverSamplerate != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <svrinfosamplerate> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <svrinfosamplerate> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
@ -371,9 +415,10 @@ parseConfig(const char *fileName)
} }
if (!xmlStrcmp(cur->name, BAD_CAST "svrinfoquality")) { if (!xmlStrcmp(cur->name, BAD_CAST "svrinfoquality")) {
if (ezConfig.serverQuality != NULL) { if (ezConfig.serverQuality != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <svrinfoquality> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <svrinfoquality> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
@ -383,16 +428,22 @@ parseConfig(const char *fileName)
} }
if (!xmlStrcmp(cur->name, BAD_CAST "svrinfopublic")) { if (!xmlStrcmp(cur->name, BAD_CAST "svrinfopublic")) {
if (svrinfopublic_set) { if (svrinfopublic_set) {
printf("%s[%ld]: Error: Cannot have multiple <svrinfopublic> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <svrinfopublic> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur->xmlChildrenNode != NULL) { if (cur->xmlChildrenNode != NULL) {
int tmp; const char *errstr;
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
tmp = atoi(ls_xmlContentPtr); ezConfig.serverPublic = strtonum(ls_xmlContentPtr, 0, 1, &errstr);
ezConfig.serverPublic = (tmp == 0) ? 0 : 1; if (errstr) {
printf("%s[%ld]: Error: <svrinfopublic> may only contain 1 or 0\n",
fileName, xmlGetLineNo(cur));
config_error++;
continue;
}
xmlFree(ls_xmlContentPtr); xmlFree(ls_xmlContentPtr);
svrinfopublic_set = 1; svrinfopublic_set = 1;
} }
@ -406,16 +457,22 @@ parseConfig(const char *fileName)
while (cur2 != NULL) { while (cur2 != NULL) {
if (!xmlStrcmp(cur2->name, BAD_CAST "enable")) { if (!xmlStrcmp(cur2->name, BAD_CAST "enable")) {
if (enable_set) { if (enable_set) {
printf("%s[%ld]: Error: Cannot have multiple <enable> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <enable> elements\n",
fileName, xmlGetLineNo(cur)); fileName, xmlGetLineNo(cur));
goto config_error; config_error++;
continue;
} }
if (cur2->xmlChildrenNode != NULL) { if (cur2->xmlChildrenNode != NULL) {
int tmp; const char *errstr;
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1);
tmp = atoi(ls_xmlContentPtr); ezConfig.reencode = strtonum(ls_xmlContentPtr, 0, 1, &errstr);
ezConfig.reencode = (tmp == 0) ? 0 : 1; if (errstr) {
printf("%s[%ld]: Error: <enable> may only contain 1 or 0\n",
fileName, xmlGetLineNo(cur));
config_error++;
continue;
}
xmlFree(ls_xmlContentPtr); xmlFree(ls_xmlContentPtr);
enable_set = 1; enable_set = 1;
} }
@ -431,9 +488,10 @@ parseConfig(const char *fileName)
while (cur3 != NULL) { while (cur3 != NULL) {
if (!xmlStrcmp(cur3->name, BAD_CAST "format")) { if (!xmlStrcmp(cur3->name, BAD_CAST "format")) {
if (pformatEncDec->format != NULL) { if (pformatEncDec->format != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <format> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <format> elements\n",
fileName, xmlGetLineNo(cur3)); fileName, xmlGetLineNo(cur3));
goto config_error; config_error++;
continue;
} }
if (cur3->xmlChildrenNode != NULL) { if (cur3->xmlChildrenNode != NULL) {
char *p; char *p;
@ -447,9 +505,10 @@ parseConfig(const char *fileName)
} }
if (!xmlStrcmp(cur3->name, BAD_CAST "match")) { if (!xmlStrcmp(cur3->name, BAD_CAST "match")) {
if (pformatEncDec->match != NULL) { if (pformatEncDec->match != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <match> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <match> elements\n",
fileName, xmlGetLineNo(cur3)); fileName, xmlGetLineNo(cur3));
goto config_error; config_error++;
continue;
} }
if (cur3->xmlChildrenNode != NULL) { if (cur3->xmlChildrenNode != NULL) {
char *p; char *p;
@ -463,9 +522,10 @@ parseConfig(const char *fileName)
} }
if (!xmlStrcmp(cur3->name, BAD_CAST "decode")) { if (!xmlStrcmp(cur3->name, BAD_CAST "decode")) {
if (pformatEncDec->decoder != NULL) { if (pformatEncDec->decoder != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <decode> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <decode> elements\n",
fileName, xmlGetLineNo(cur3)); fileName, xmlGetLineNo(cur3));
goto config_error; config_error++;
continue;
} }
if (cur3->xmlChildrenNode != NULL) { if (cur3->xmlChildrenNode != NULL) {
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1);
@ -476,7 +536,8 @@ parseConfig(const char *fileName)
if ((p = strstr(p, TRACK_PLACEHOLDER)) != NULL) { if ((p = strstr(p, TRACK_PLACEHOLDER)) != NULL) {
printf("%s[%ld]: Error: Multiple `%s' placeholders in decoder command\n", printf("%s[%ld]: Error: Multiple `%s' placeholders in decoder command\n",
fileName, xmlGetLineNo(cur3), TRACK_PLACEHOLDER); fileName, xmlGetLineNo(cur3), TRACK_PLACEHOLDER);
goto config_error; config_error++;
continue;
} }
} }
if ((p = strstr(pformatEncDec->decoder, METADATA_PLACEHOLDER)) != NULL) { if ((p = strstr(pformatEncDec->decoder, METADATA_PLACEHOLDER)) != NULL) {
@ -484,16 +545,18 @@ parseConfig(const char *fileName)
if ((p = strstr(p, METADATA_PLACEHOLDER)) != NULL) { if ((p = strstr(p, METADATA_PLACEHOLDER)) != NULL) {
printf("%s[%ld]: Error: Multiple `%s' placeholders in decoder command\n", printf("%s[%ld]: Error: Multiple `%s' placeholders in decoder command\n",
fileName, xmlGetLineNo(cur3), METADATA_PLACEHOLDER); fileName, xmlGetLineNo(cur3), METADATA_PLACEHOLDER);
goto config_error; config_error++;
continue;
} }
} }
} }
} }
if (!xmlStrcmp(cur3->name, BAD_CAST "encode")) { if (!xmlStrcmp(cur3->name, BAD_CAST "encode")) {
if (pformatEncDec->encoder != NULL) { if (pformatEncDec->encoder != NULL) {
printf("%s[%ld]: Error: Cannot have multiple <encode> elements.\n", printf("%s[%ld]: Error: Cannot have multiple <encode> elements\n",
fileName, xmlGetLineNo(cur3)); fileName, xmlGetLineNo(cur3));
goto config_error; config_error++;
continue;
} }
if (cur3->xmlChildrenNode != NULL) { if (cur3->xmlChildrenNode != NULL) {
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1);
@ -502,14 +565,16 @@ parseConfig(const char *fileName)
if ((p = strstr(pformatEncDec->encoder, TRACK_PLACEHOLDER)) != NULL) { if ((p = strstr(pformatEncDec->encoder, TRACK_PLACEHOLDER)) != NULL) {
printf("%s[%ld]: Error: `%s' placeholder not allowed in encoder command\n", printf("%s[%ld]: Error: `%s' placeholder not allowed in encoder command\n",
fileName, xmlGetLineNo(cur3), TRACK_PLACEHOLDER); fileName, xmlGetLineNo(cur3), TRACK_PLACEHOLDER);
goto config_error; config_error++;
continue;
} }
if ((p = strstr(pformatEncDec->encoder, METADATA_PLACEHOLDER)) != NULL) { if ((p = strstr(pformatEncDec->encoder, METADATA_PLACEHOLDER)) != NULL) {
p += strlen(METADATA_PLACEHOLDER); p += strlen(METADATA_PLACEHOLDER);
if ((p = strstr(p, METADATA_PLACEHOLDER)) != NULL) { if ((p = strstr(p, METADATA_PLACEHOLDER)) != NULL) {
printf("%s[%ld]: Error: Multiple `%s' placeholders in encoder command\n", printf("%s[%ld]: Error: Multiple `%s' placeholders in encoder command\n",
fileName, xmlGetLineNo(cur3), METADATA_PLACEHOLDER); fileName, xmlGetLineNo(cur3), METADATA_PLACEHOLDER);
goto config_error; config_error++;
continue;
} }
} }
} }
@ -526,11 +591,13 @@ parseConfig(const char *fileName)
} }
xmlFreeDoc(doc); xmlFreeDoc(doc);
return(1);
config_error: if (config_error == 0)
return (1);
xmlFreeDoc(doc);
freeConfig(&ezConfig); freeConfig(&ezConfig);
printf("%s: %u configuration errors in %s\n", __progname,
config_error, fileName);
return (0); return (0);
} }

View File

@ -57,11 +57,9 @@
#ifndef HAVE_GETOPT #ifndef HAVE_GETOPT
# include "getopt.h" # include "getopt.h"
#endif #endif
#if !defined(HAVE_STRLCAT) || !defined(HAVE_STRLCPY)
# include "strlfctns.h"
#endif
#include "configfile.h" #include "configfile.h"
#include "playlist.h" #include "playlist.h"
#include "strfctns.h"
#include "util.h" #include "util.h"
#ifndef PATH_MAX #ifndef PATH_MAX
@ -187,9 +185,10 @@ strrcmp(const char *s, const char *sub)
int int
urlParse(const char *url, char **hostname, int *port, char **mountname) urlParse(const char *url, char **hostname, int *port, char **mountname)
{ {
char *p1, *p2, *p3; char *p1, *p2, *p3;
char tmpPort[25] = ""; char tmpPort[6] = "";
size_t hostsiz, mountsiz; size_t hostsiz, mountsiz;
const char *errstr;
if (hostname == NULL || port == NULL || mountname == NULL) { if (hostname == NULL || port == NULL || mountname == NULL) {
printf("%s: urlParse(): Internal error: Bad arguments\n", printf("%s: urlParse(): Internal error: Bad arguments\n",
@ -197,24 +196,40 @@ urlParse(const char *url, char **hostname, int *port, char **mountname)
exit(1); exit(1);
} }
if (strncmp(url, "http://", strlen("http://")) != 0) if (strncmp(url, "http://", strlen("http://")) != 0) {
printf("%s: Error: Invalid <url>: Not an HTTP address\n",
__progname);
return (0); return (0);
}
p1 = (char *)(url) + strlen("http://"); p1 = (char *)(url) + strlen("http://");
p2 = strchr(p1, ':'); p2 = strchr(p1, ':');
if (p2 == NULL) if (p2 == NULL) {
printf("%s: Error: Invalid <url>: Missing port\n",
__progname);
return (0); return (0);
}
hostsiz = (p2 - p1) + 1; hostsiz = (p2 - p1) + 1;
*hostname = xmalloc(hostsiz); *hostname = xmalloc(hostsiz);
strlcpy(*hostname, p1, hostsiz); strlcpy(*hostname, p1, hostsiz);
p2++; p2++;
p3 = strchr(p2, '/'); p3 = strchr(p2, '/');
if (p3 == NULL || p3 - p2 >= (int)sizeof(tmpPort)) if (p3 == NULL || p3 - p2 >= (int)sizeof(tmpPort)) {
printf("%s: Error: Invalid <url>: Missing mountpoint or too long port number\n",
__progname);
xfree(*hostname);
return (0); return (0);
}
strlcpy(tmpPort, p2, (p3 - p2) + 1); strlcpy(tmpPort, p2, (p3 - p2) + 1);
*port = atoi(tmpPort); *port = strtonum(tmpPort, 1, 65535, &errstr);
if (errstr) {
printf("%s: Error: Invalid <url>: Port '%s' is %s\n",
__progname, tmpPort, errstr);
xfree(*hostname);
return (0);
}
mountsiz = strlen(p3) + 1; mountsiz = strlen(p3) + 1;
*mountname = xmalloc(mountsiz); *mountname = xmalloc(mountsiz);
@ -269,7 +284,7 @@ buildCommandString(const char *extension, const char *fileName,
decoder = xstrdup(getFormatDecoder(extension)); decoder = xstrdup(getFormatDecoder(extension));
if (strlen(decoder) == 0) { if (strlen(decoder) == 0) {
printf("%s: Unknown extension '%s', cannot decode '%s'.\n", printf("%s: Unknown extension '%s', cannot decode '%s'\n",
__progname, extension, fileName); __progname, extension, fileName);
xfree(decoder); xfree(decoder);
return (NULL); return (NULL);
@ -371,27 +386,27 @@ processMetadata(shout_t *shout, const char *extension, const char *fileName)
if ((ret = ov_open(filepstream, &vf, NULL, 0)) != 0) { if ((ret = ov_open(filepstream, &vf, NULL, 0)) != 0) {
switch (ret) { switch (ret) {
case OV_EREAD: case OV_EREAD:
printf("%s: No metadata support: %s: Media read error.\n", printf("%s: No metadata support: %s: Media read error\n",
__progname, fileName); __progname, fileName);
break; break;
case OV_ENOTVORBIS: case OV_ENOTVORBIS:
printf("%s: No metadata support: %s: Invalid Vorbis bitstream.\n", printf("%s: No metadata support: %s: Invalid Vorbis bitstream\n",
__progname, fileName); __progname, fileName);
break; break;
case OV_EVERSION: case OV_EVERSION:
printf("%s: No metadata support: %s: Vorbis version mismatch.\n", printf("%s: No metadata support: %s: Vorbis version mismatch\n",
__progname, fileName); __progname, fileName);
break; break;
case OV_EBADHEADER: case OV_EBADHEADER:
printf("%s: No metadata support: %s: Invalid Vorbis bitstream header.\n", printf("%s: No metadata support: %s: Invalid Vorbis bitstream header\n",
__progname, fileName); __progname, fileName);
break; break;
case OV_EFAULT: case OV_EFAULT:
printf("%s: Fatal: Internal libvorbisfile fault.\n", printf("%s: Fatal: Internal libvorbisfile fault\n",
__progname); __progname);
abort(); abort();
default: default:
printf("%s: No metadata support: %s: ov_read() returned unknown error.\n", printf("%s: No metadata support: %s: ov_read() returned unknown error\n",
__progname, fileName); __progname, fileName);
break; break;
} }
@ -487,7 +502,7 @@ openResource(shout_t *shout, const char *fileName, int *popenFlag,
if (strcmp(fileName, "stdin") == 0) { if (strcmp(fileName, "stdin") == 0) {
if (vFlag) if (vFlag)
printf("%s: Reading from standard input.\n", printf("%s: Reading from standard input\n",
__progname); __progname);
if (isStdin != NULL) if (isStdin != NULL)
*isStdin = 1; *isStdin = 1;
@ -555,7 +570,7 @@ openResource(shout_t *shout, const char *fileName, int *popenFlag,
if (qFlag) if (qFlag)
dup2(stderr_fd, STDERR_FILENO); dup2(stderr_fd, STDERR_FILENO);
} else } else
printf("%s: Error: Cannot determine file type of '%s'.\n", printf("%s: Error: Cannot determine file type of '%s'\n",
__progname, fileName); __progname, fileName);
xfree(pMetadata); xfree(pMetadata);
@ -577,7 +592,7 @@ reconnectServer(shout_t *shout, int closeConn)
unsigned int i; unsigned int i;
int close_conn = closeConn; int close_conn = closeConn;
printf("%s: Connection to %s lost.\n", __progname, pezConfig->URL); printf("%s: Connection to %s lost\n", __progname, pezConfig->URL);
i = 0; i = 0;
while (++i) { while (++i) {
@ -593,7 +608,7 @@ reconnectServer(shout_t *shout, int closeConn)
else else
shout_close(shout); shout_close(shout);
if (shout_open(shout) == SHOUTERR_SUCCESS) { if (shout_open(shout) == SHOUTERR_SUCCESS) {
printf("OK\n%s: Reconnect to %s successful.\n", printf("OK\n%s: Reconnect to %s successful\n",
__progname, pezConfig->URL); __progname, pezConfig->URL);
return (1); return (1);
} }
@ -613,7 +628,7 @@ reconnectServer(shout_t *shout, int closeConn)
#endif #endif
}; };
printf("%s: Giving up.\n", __progname); printf("%s: Giving up\n", __progname);
return (0); return (0);
} }
@ -650,7 +665,7 @@ sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
if (rereadPlaylist_notify) { if (rereadPlaylist_notify) {
rereadPlaylist_notify = 0; rereadPlaylist_notify = 0;
if (!pezConfig->fileNameIsProgram) if (!pezConfig->fileNameIsProgram)
printf("%s: SIGHUP signal received, will reread playlist after this file.\n", printf("%s: SIGHUP signal received, will reread playlist after this file\n",
__progname); __progname);
} }
if (skipTrack) { if (skipTrack) {
@ -776,7 +791,7 @@ streamFile(shout_t *shout, const char *fileName)
if (ret == STREAM_SKIP || skipTrack) { if (ret == STREAM_SKIP || skipTrack) {
skipTrack = 0; skipTrack = 0;
if (!isStdin && vFlag) if (!isStdin && vFlag)
printf("%s: SIGUSR1 signal received, skipping current track.\n", printf("%s: SIGUSR1 signal received, skipping current track\n",
__progname); __progname);
retval = 1; retval = 1;
ret = STREAM_DONE; ret = STREAM_DONE;
@ -914,7 +929,7 @@ main(int argc, char *argv[])
switch (c) { switch (c) {
case 'c': case 'c':
if (configFile != NULL) { if (configFile != NULL) {
printf("Error: multiple -c arguments given.\n"); printf("Error: multiple -c arguments given\n");
usage(); usage();
return (2); return (2);
} }
@ -959,10 +974,10 @@ main(int argc, char *argv[])
return (2); return (2);
} }
if (vFlag && (st.st_mode & (S_IRGRP | S_IROTH))) if (vFlag && (st.st_mode & (S_IRGRP | S_IROTH)))
printf("%s: Warning: %s is group and/or world readable.\n", printf("%s: Warning: %s is group and/or world readable\n",
__progname, configFile); __progname, configFile);
if (st.st_mode & (S_IWGRP | S_IWOTH)) { if (st.st_mode & (S_IWGRP | S_IWOTH)) {
printf("%s: Error: %s is group and/or world writeable.\n", printf("%s: Error: %s is group and/or world writeable\n",
__progname, configFile); __progname, configFile);
return (2); return (2);
} }
@ -989,36 +1004,30 @@ main(int argc, char *argv[])
return (2); return (2);
} }
if (!urlParse(pezConfig->URL, &host, &port, &mount)) { if (!urlParse(pezConfig->URL, &host, &port, &mount)) {
printf("%s: Error: Invalid <url>:\n", configFile); printf("Must be of the form ``http://server:port/mountpoint''\n");
printf("Must be of the form ``http://server:port/mountpoint''.\n");
return (2); return (2);
} }
if ((host == NULL)) { if (strlen(host) == 0) {
printf("%s: Error: Invalid <url>: Missing server:\n", configFile); printf("%s: Error: Invalid <url>: Missing server:\n", configFile);
printf("Must be of the form ``http://server:port/mountpoint''.\n"); printf("Must be of the form ``http://server:port/mountpoint''\n");
return (2); return (2);
} }
if ((port < 1 || port > 65535)) { if (strlen(mount) == 0) {
printf("%s: Error: Invalid <url>: Missing or invalid port:\n", configFile);
printf("Must be of the form ``http://server:port/mountpoint''.\n");
return (2);
}
if ((mount == NULL)) {
printf("%s: Error: Invalid <url>: Missing mountpoint:\n", configFile); printf("%s: Error: Invalid <url>: Missing mountpoint:\n", configFile);
printf("Must be of the form ``http://server:port/mountpoint''.\n"); printf("Must be of the form ``http://server:port/mountpoint''\n");
return (2); return (2);
} }
if ((pezConfig->password == NULL)) { if (pezConfig->password == NULL) {
printf("%s: Error: Missing <sourcepassword>\n", configFile); printf("%s: Error: Missing <sourcepassword>\n", configFile);
return (2); return (2);
} }
if ((pezConfig->fileName == NULL)) { if (pezConfig->fileName == NULL) {
printf("%s: Error: Missing <filename>\n", configFile); printf("%s: Error: Missing <filename>\n", configFile);
return (2); return (2);
} }
if (pezConfig->format == NULL) { if (pezConfig->format == NULL) {
printf("%s: Warning: Missing <format>:\n", configFile); printf("%s: Warning: Missing <format>:\n", configFile);
printf("Specify a stream format of either MP3, VORBIS or THEORA.\n"); printf("Specify a stream format of either MP3, VORBIS or THEORA\n");
} }
xfree(configFile); xfree(configFile);

23
src/strfctns.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef __STRLFCTNS_H__
#define __STRLFCTNS_H__
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifndef HAVE_STRLCAT
# define strlcat local_strlcat
#endif
size_t local_strlcat(char *, const char *, size_t);
#ifndef HAVE_STRLCPY
# define strlcpy local_strlcpy
#endif
size_t local_strlcpy(char *, const char *, size_t);
#ifndef HAVE_STRTONUM
# define strtonum local_strtonum
#endif
long long local_strtonum(const char *, long long, long long, const char **);
#endif /* __STRLFCTNS_H__ */

View File

@ -24,7 +24,7 @@
# include <sys/types.h> # include <sys/types.h>
#endif #endif
#include <string.h> #include <string.h>
#include "strlfctns.h" #include "strfctns.h"
/* /*
* Appends src to string dst of size siz (unlike strncat, siz is the * Appends src to string dst of size siz (unlike strncat, siz is the

View File

@ -24,7 +24,7 @@
# include <sys/types.h> # include <sys/types.h>
#endif #endif
#include <string.h> #include <string.h>
#include "strlfctns.h" #include "strfctns.h"
/* /*
* Copy src to string dst of size siz. At most siz-1 characters * Copy src to string dst of size siz. At most siz-1 characters

View File

@ -1,18 +0,0 @@
#ifndef __STRLFCTNS_H__
#define __STRLFCTNS_H__
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifndef HAVE_STRLCAT
# define strlcat local_strlcat
#endif
size_t local_strlcat(char *, const char *, size_t);
#ifndef HAVE_STRLCPY
# define strlcpy local_strlcpy
#endif
size_t local_strlcpy(char *, const char *, size_t);
#endif /* __STRLFCTNS_H__ */

81
src/strtonum.c Normal file
View File

@ -0,0 +1,81 @@
/* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */
/*
* Copyright (c) 2004 Ted Unangst and Todd Miller
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include "strfctns.h"
#define INVALID 1
#define TOOSMALL 2
#define TOOLARGE 3
#if !defined(LLONG_MIN) || !defined(LLONG_MAX)
# undef LLONG_MIN
# undef LLONG_MAX
# define LLONG_MIN LONG_LONG_MIN
# define LLONG_MAX LONG_LONG_MAX
#endif
#ifdef WIN32
# define strtoll _strtoi64
#endif
long long
local_strtonum(const char *numstr, long long minval, long long maxval,
const char **errstrp)
{
long long ll = 0;
char *ep;
int error = 0;
struct errval {
const char *errstr;
int err;
} ev[4] = {
{ NULL, 0 },
{ "invalid", EINVAL },
{ "too small", ERANGE },
{ "too large", ERANGE },
};
ev[0].err = errno;
errno = 0;
if (minval > maxval)
error = INVALID;
else {
ll = strtoll(numstr, &ep, 10);
if (numstr == ep || *ep != '\0')
error = INVALID;
else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
error = TOOSMALL;
else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
error = TOOLARGE;
}
if (errstrp != NULL)
*errstrp = ev[error].errstr;
errno = ev[error].err;
if (error)
ll = 0;
return (ll);
}