#include #include #include #include #include static char* conf_directory = NULL; static char* work_directory = NULL; typedef struct _graph { const char* name; char* title; int width; int height; int interval; char* category; struct _graph *next; } graph; static graph* allgraphs = NULL; /* ----------------------------------------------------------------------------- * CONFIG PARSING */ int cfg_value(const char* filename, const char* header, const char* name, char* value, void* data) { static graph* gr = NULL; /* called like this after ever file */ if (!header) { /* add to the list */ gr->next = allgraphs; allgraphs = gr; gr = NULL; return 0; } if (gr == NULL) { gr = calloc(1, sizeof(graph)); if (!gr) err(1, "Out of memory"); gr->name = filename; gr->category = ""; } if (strcmp(header, "general") == 0) { if (strcmp(name, "title") == 0) gr->title = value; else if (strcmp(name, "category") == 0) gr->category = value; } else if (strcmp(header, "graph") == 0) { if (strcmp(name, "height") == 0) gr->height = atoi(value); else if (strcmp(name, "width") == 0) gr->width = atoi(value); } else if (strcmp(header, "poll") == 0) { if (strcmp(name, "interval") == 0) gr->interval = atoi(value); } } int cfg_error(const char* filename, const char* errmsg, void* data) { /* todo skip the rest of this file on error */ warnx("%s", errmsg); return 0; } void freegraphs () { graph* l; graph* t; for (l = allgraphs; l != NULL; ) { t = l->next; free(l); l = t; } } /* ----------------------------------------------------------------------------- * METHODS */ static void listgraphs () { graph* l; printf("Content-Type: text/xml\n\n"); printf("\n"); printf("\n"); for (l = allgraphs; l != NULL; l = l->next) { printf(" name, l->category, l->title); if (l->width) printf(" width=\"%d\"", l->width); if (l->height) printf(" height=\"%d\"", l->height); if (l->interval) printf(" interval=\"%d\"", l->interval); printf(" />\n"); } printf("\n"); } #if 0 static void displaygraphs () { char* name = NULL; int width; int height; char* q; char* query = NULL; q = getenv("QUERY_STRING"); if (q) { query = q = strdup(q); while (q[0] && (q[0] == '?' || isspace(q[0]))) q++; while (q && q[0]) { nm = strsep(&q, "&"); vl = strchr(nm, '='); if (!vl) continue; vl[0] = 0; vl++; if (strcmp(nm, "name") == 0) name = vl; else if (strcmp(nm, "width") == 0) width = atoi(vl); else if (strcmp(nm, "height") == ) height = atoi(vl); } } } #endif /* ----------------------------------------------------------------------------- * MAIN */ static void usererror (const char* msg) { printf("Content-Type: text/plain\n\n"); printf("%s\n", msg); /* Custom error so webserver doesn't think it's a server error */ exit(0); } static int pathstarts (const char* path, const char* method) { int len = strlen(method); if (strncmp(path, method, len) != 0) return 0; if (path[len] == '/' || !path[len]) return 1; return 0; } int main (int argc, char* argv[]) { char* path; conf_directory = getenv("CONFDIR"); work_directory = getenv("WORKDIR"); if (!conf_directory || !work_directory) errx(2, "not setup properly. CONFDIR and WORKDIR env variables must be set"); /* * We always have this as our current directory. * It helps when constructing graphs and the like */ if (chdir(work_directory) < 0) err(1, "Couldn't change to work directory: %s", work_directory); path = getenv("PATH_INFO"); while (path && path[0] && (isspace(path[0]) || path[0] == '/')) path++; cfg_parse_dir(conf_directory, NULL); if (!path || !path[0] || pathstarts(path, "list")) listgraphs(); else if (pathstarts(path, "graph")) printf("graph\n"); else usererror("Invalid request"); freegraphs(); return 0; }