This is wwwwais2.5.c in view mode; [Download] [Up]
/* ** wwwwais 2.5 ** 11/2/94 ** waisq/waissearch to HTML interface ** By Kevin Hughes, kevinh@eit.com ** ** 1.0 : Old waissearch interface code. Yuck! ** 2.0 : New waisq interface. ** 2.1 : Speed improvements and gettitle() fix. Access control, purified! ** 2.2 : Added in better waissearch code, compatibility with non-URL indices. ** 2.3 : Close stderr... ** 2.4 : sys/types.h, multiline titles, better lstrstr(), supports GET, POST, ** and PATH_INFO, better filename gathering for waisq and waissearch, ** environment variables, configuration file, title HTML, multiple ** WAIS sources, configurable icons, source recognition, file retrieval, ** signals. ** 2.41: Changed waisq flag, better waissource config file check, mystrdup(), ** translates CR/LF input to spaces. ** 2.42: <string.h>, *duh*..., WWWW_SELECTION. ** 2.5 : SWISH support added, TIMEOUT value, realbytes deleted, negative ** line info not printed, selection fix. ** ** Thanks to Andrew Williams, Christian Bartholdsson, Enzo Michelangeli, ** Achim Jung, Alexander Gagin, Jim Robb, and many others for good ** suggestions and patches. */ /* You will need to define the following option! */ #define CONFFILE "/usr/local/httpd/swish/wwwwais.conf" /* The configuration file for wwwwais that holds all the defaults. */ /* End of user-definable options */ #include <sys/types.h> #include <stdio.h> #include <ctype.h> #include <sys/stat.h> #include <signal.h> #include <string.h> #define VERSION "2.5" #define WAISTITLE "WAIS Gateway" #define VERSTITLE "WAIS Gateway Version Information" #define DOCURL "http://www.eit.com/software/wwwwais/wwwwais.html" #define TIMEOUT 45 #define MAXARGS 100 #define MAXARGLEN 1000 #define MAXSTRLEN 1024 #define MAXTITLELEN 1000 #define HEXLEN 5 #define TITLETOPLINES 12 #define SELECTTXT "selection=" #define SOURCETXT "source=" #define SOURCEDIRTXT "sourcedir=" #define MAXHITSTXT "maxhits=" #define VERSIONTXT "version=" #define ISINDEXTXT "isindex=" #define KEYWORDSTXT "keywords=" #define SORTTYPETXT "sorttype=" #define PORTTXT "port=" #define HOSTTXT "host=" #define SEARCHPROGTXT "searchprog=" #define ICONURLTXT "iconurl=" #define USEICONSTXT "useicons=" #define DESCTXT "getdesc=" #define DOCNUMTXT "docnum=" #define NO_ICON "no icon" #define NO_DESC "(No description)" #define NO_SELECT "none" #define ICONVAR "$ICONURL" #define KEYWORDVAR "$KEYWORDS" #define TI_OPEN 1 #define TI_CLOSE 2 #define TI_FOUND 4 struct entry { int score; int lines; int bytes; int docnum; char *filename; char *title; char *type; char *icon; struct entry *left; struct entry *right; } *entrylist; struct source { char *line; struct source *next; } *sourcelist, *ruleslist, *desclist, *bodylist; struct suffixentry { char *suffix; char *desc; char *url; char *mime; struct suffixentry *next; } *suffixlist; char *getvalue(); char *getkeywords(); char *mystrdup(); void *emalloc(); int getnumber(); char *getqfilename(); char *getsfilename(); char *gettype(); char *gettitle(); char *getmime(); char *parsetitle(); char *geticon(); char *lstrstr(); struct entry *addentry(); char *getconfvalue(); char *getdesc(); struct source *addsource(); char *encode(); char *decode(); struct suffixentry *addsuffix(); char *replace(); char *getword(); char *ruleparse(); char *getrule(); void badconnection(); void badsegviol(); void badtimeout(); int use_icons, indexsources, no_options, use_selection, docnum, version; int skip[MAXSTRLEN]; static char query_string[MAXSTRLEN], sorttype[MAXSTRLEN], swishbin[MAXSTRLEN], waisqbin[MAXSTRLEN], waissearchbin[MAXSTRLEN], selfurl[MAXSTRLEN], iconurl[MAXSTRLEN], useicons[MAXSTRLEN], pagetitle[MAXSTRLEN], selection[MAXSTRLEN], addrmask[MAXSTRLEN], unknown_icon[MAXSTRLEN], unknown_type[MAXSTRLEN], unknown_mime[MAXSTRLEN], srcdesc[MAXSTRLEN], source[MAXSTRLEN], sourcedir[MAXSTRLEN], maxhits[MAXSTRLEN], host[MAXSTRLEN], port[MAXSTRLEN], searchprog[MAXSTRLEN], keywords[MAXSTRLEN]; main () { int i, len; char *p, *method, *query, *addr; fclose(stderr); sorttype[0] = '\0'; selection[0] = '\0'; srcdesc[0] = '\0'; sourcelist = NULL; suffixlist = NULL; ruleslist = NULL; desclist = NULL; bodylist = NULL; use_icons = 0; use_selection = 0; indexsources = 0; docnum = -1; signal(SIGSEGV, badsegviol); signal(SIGPIPE, badconnection); signal(SIGALRM, badtimeout); /* First, get all the normal environment CGI things... */ method = (char *) getenv("REQUEST_METHOD"); if (method == NULL) progerr("Unknown method."); if (!strncmp(method, "POST", 4)) { len = atoi(getenv("CONTENT_LENGTH")); i = 0; while (len-- && i < MAXSTRLEN) query_string[i++] = fgetc(stdin); query_string[i] = '\0'; } else if (!strncmp(method, "GET", 3)) { query = (char *) getenv("QUERY_STRING"); if (query == NULL) query_string[0] = '\0'; else strcpy(query_string, query); } else progerr("Unknown method."); /* Does the user want version information? ** Is a document number associated with the request? ** Will the request be a WAIS source description? */ version = ((getvalue(VERSIONTXT, ""))[0] == '\0') ? 0 : 1; docnum = atoi(getvalue(DOCNUMTXT, "-1")); strcpy(srcdesc, (char *) getvalue(DESCTXT, srcdesc)); /* Read the config file and determine any selected pop-up option... */ strcpy(selection, (char *) getvalue(SELECTTXT, selection)); if ((p = (char *) getenv("WWWW_SELECTION")) != NULL) strcpy(selection, p); if (selection[0] == '\0' || selection[0] == NULL) use_selection = 0; if (!strcmp(selection, NO_SELECT)) no_options = 1; else no_options = 0; getdefaults(); /* Make sure the user's address is OK... */ addr = (char *) getenv("REMOTE_ADDR"); if (addr == NULL || !isokstring(addr, addrmask)) { printreject(); exit(0); } /* Grab all the normal variables. */ strcpy(maxhits, (char *) getvalue(MAXHITSTXT, maxhits)); if ((p = (char *) getenv("WWWW_MAXHITS")) != NULL) strcpy(maxhits, p); strcpy(sorttype, (char *) getvalue(SORTTYPETXT, sorttype)); if ((p = (char *) getenv("WWWW_SORTTYPE")) != NULL) strcpy(sorttype, p); strcpy(iconurl, (char *) getvalue(ICONURLTXT, iconurl)); if ((p = (char *) getenv("WWWW_ICONURL")) != NULL) strcpy(iconurl, p); strcpy(useicons, (char *) getvalue(USEICONSTXT, useicons)); if ((p = (char *) getenv("WWWW_USEICONS")) != NULL) strcpy(useicons, p); strcpy(keywords, (char *) getkeywords()); if (lstrstr(keywords, KEYWORDSTXT)) strcpy(keywords, ""); if ((p = (char *) getenv("WWWW_KEYWORDS")) != NULL) strcpy(keywords, p); /* If there is a pop-up selection, these variables (host, port, etc.) ** are overridden. */ if (!use_selection) { strcpy(source, (char *) getvalue(SOURCETXT, source)); if ((p = (char *) getenv("WWWW_SOURCE")) != NULL) strcpy(source, p); strcpy(sourcedir, (char *) getvalue(SOURCEDIRTXT, sourcedir)); if ((p = (char *) getenv("WWWW_SOURCEDIR")) != NULL) strcpy(sourcedir, p); strcpy(host, (char *) getvalue(HOSTTXT, host)); if ((p = (char *) getenv("WWWW_HOST")) != NULL) strcpy(host, p); strcpy(port, (char *) getvalue(PORTTXT, port)); if ((p = (char *) getenv("WWWW_PORT")) != NULL) strcpy(port, p); strcpy(searchprog, (char *) getvalue(SEARCHPROGTXT, searchprog)); if ((p = (char *) getenv("WWWW_SEARCHPROG")) != NULL) strcpy(searchprog, p); } entrylist = NULL; if (lstrstr(useicons, "yes")) use_icons = 1; else use_icons = 0; /* Do any searching that needs to be done. ** If there are no keywords, just print a form. */ if (srcdesc[0] != '\0') { alarm(TIMEOUT); descwaiss(); } else if (!keywords[0] && !version) { printheader(); printform(); return 0; } else { if (version) { printversion(); if (isfile(waisqbin)) dowaisq(); if (isfile(waissearchbin)) dowaiss(); if (isfile(swishbin)) doswish(); } else { alarm(TIMEOUT); if (!strcmp(searchprog, "waisq")) dowaisq(); else if (!strcmp(searchprog, "waissearch")) dowaiss(); else doswish(); printfooter(); } } return 0; } /* This gets a value for a certain variable from the environment, ** using PATH_INFO and POST and GET information. It returns a ** default if the variable is not found. */ char *getvalue(var, def) char *var; char *def; { int i; char *c, *argp, argstr[MAXSTRLEN]; static char value[MAXSTRLEN], tmpstr[MAXSTRLEN]; if (query_string[0] == '\0' || !lstrstr(query_string, var)) { argp = (char *) getenv("PATH_INFO"); if (argp == NULL || !lstrstr(argp, var)) { if (strlen(def) <= 1) return "\0"; strcpy(tmpstr, decode(def)); return tmpstr; } strcpy(argstr, argp); } else strcpy(argstr, query_string); for (i = 0, c = (char *) lstrstr(argstr, var) + strlen(var); *c && i < MAXSTRLEN && *c != '&'; c++) value[i++] = *c; value[i] = '\0'; if (i) { strcpy(tmpstr, decode(value)); return tmpstr; } if (strlen(def) <= 1) return "\0"; strcpy(tmpstr, decode(def)); return tmpstr; } /* Search for keywords, either normally or through ISINDEX. ** If there are only keywords in environment information, they are returned. */ char *getkeywords() { static char value[MAXSTRLEN], tmpvalue[MAXSTRLEN]; strcpy(value, getvalue(ISINDEXTXT, "")); if (!value[0]) { strcpy(value, getvalue(KEYWORDSTXT, "")); if (!value[0]) { if (!strchr(query_string, '&') && !strchr(query_string, '=')) { strcpy(tmpvalue, decode(query_string)); return tmpvalue; } else return "\0"; } } strcpy(tmpvalue, decode(value)); return tmpvalue; } /* Prints the header file or string. */ printheader() { char line[MAXSTRLEN]; FILE *fp; printf("Content-type: text/html\n\n"); if (lstrstr(pagetitle, ".html")) { if ((fp = fopen(pagetitle, "r")) != NULL) { while (fgets(line, MAXSTRLEN, fp) != NULL) printf("%s", line); fclose(fp); } else { printf("<title>%s</title>\n", WAISTITLE); printf("<h1>%s</h1>\n", WAISTITLE); } } else { printf("<title>%s</title>\n", pagetitle); printf("<h1>%s</h1>\n", pagetitle); } } /* Prints a link to the documentation. */ printfooter() { printf("<hr>\n"); printf("<i>This search was performed by <a href=\"%s\">wwwwais", DOCURL); printf(" %s</a>.</i>\n", VERSION); } /* The header for the version information page. */ printversion() { printf("Content-type: text/html\n\n"); printf("<title>%s</title>\n", VERSTITLE); printf("<h1>%s</h1>\n", VERSTITLE); printf("This is WWWWAIS version %s.\n<br>\n", VERSION); } /* Sets everything up for calling waisq and executes it. ** Spits out version information if requested. */ dowaisq() { int i, j, k; char *argline[MAXARGS], word[MAXSTRLEN]; int pipe0[2], pipe1[2]; FILE *fp0; argline[0] = waisqbin; if (version) { argline[1] = (char *) mystrdup("-V"); argline[2] = (char *) 0; } else { argline[1] = (char *) mystrdup("-s"); argline[2] = sourcedir; argline[3] = (char *) mystrdup("-f"); argline[4] = (char *) mystrdup("-"); argline[5] = (char *) mystrdup("-S"); argline[6] = source; argline[7] = (char *) mystrdup("-m"); argline[8] = maxhits; argline[9] = (char *) mystrdup("-g"); for (i = 0, k = 10; k < MAXARGS;) { for (j = 0; keywords[i] != '\0' && keywords[i] != ' ' && j < MAXSTRLEN; i++) word[j++] = keywords[i]; word[j] = '\0'; argline[k++] = (char *) mystrdup(word); if (keywords[i] == '\0') break; else if (keywords[i] == ' ') i++; } argline[k] = (char *) 0; } pipe(pipe0); pipe(pipe1); switch(fork()) { case -1: progerr("fork() call failed."); case 0: close(pipe0[1]); close(pipe1[0]); dup2(pipe0[0], 0); dup2(pipe1[1], 1); execv(waisqbin, argline); progerr("execv() call failed."); default: close(pipe0[0]); close(pipe1[1]); fp0 = fdopen(pipe1[0], "r"); read_from_waisq(fp0); if (!version) { printheader(); printform(); if (entrylist == NULL) { notfound(); return; } printf("Here is the result of your search using "); printf("the keyword(s) "); printf("<b>\"%s\"</b>:<p>\n", keywords); printf("<dl>\n"); printentries(entrylist); printf("</dl>\n"); } } } /* Sets everything up for calling waissearch and executes it. ** Spits out version information if requested. */ dowaiss() { int i, j, k; char *argline[MAXARGS], word[MAXSTRLEN]; int pipe0[2], pipe1[2]; FILE *fp0, *fp1; argline[0] = waissearchbin; if (version) { argline[1] = (char *) mystrdup("-v"); argline[2] = (char *) 0; } else { argline[1] = (char *) mystrdup("-h"); argline[2] = host; argline[3] = (char *) mystrdup("-p"); argline[4] = port; argline[5] = (char *) mystrdup("-d"); argline[6] = source; argline[7] = (char *) mystrdup("-m"); argline[8] = maxhits; for (i = 0, k = 9;;) { for (j = 0; keywords[i] != '\0' && keywords[i] != ' ' && j < MAXSTRLEN; i++) word[j++] = keywords[i]; word[j] = '\0'; argline[k++] = (char *) mystrdup(word); if (keywords[i] == '\0') break; else if (keywords[i] == ' ') i++; } argline[k] = (char *) 0; } pipe(pipe0); pipe(pipe1); switch(fork()) { case -1: progerr("fork() call failed."); case 0: close(pipe0[1]); close(pipe1[0]); dup2(pipe0[0], 0); dup2(pipe1[1], 1); execv(waissearchbin, argline); progerr("execv() call failed."); default: close(pipe0[0]); close(pipe1[1]); fp0 = fdopen(pipe1[0], "r"); fp1 = fdopen(pipe0[1], "w"); read_from_waissearch(fp0); if (!version) { fprintf(fp1, "q\n"); fflush(fp1); fprintf(fp1, "q\n"); fflush(fp1); printheader(); printform(); if (entrylist == NULL) { notfound(); return; } printf("Here is the result of your search using "); printf("the keyword(s) "); printf("<b>\"%s\"</b>:<p>\n", keywords); printf("<dl>\n"); printentries(entrylist); printf("</dl>\n"); } } } /* Sets everything up for calling waissearch and executes it. ** Here, waissearch is expected to return a source description or ** file. */ descwaiss() { int i, j, k; char *argline[MAXARGS], word[MAXSTRLEN]; int pipe0[2], pipe1[2]; FILE *fp0, *fp1; argline[0] = waissearchbin; argline[1] = (char *) mystrdup("-h"); argline[2] = host; argline[3] = (char *) mystrdup("-p"); argline[4] = port; argline[5] = (char *) mystrdup("-d"); argline[6] = source; argline[7] = (char *) mystrdup("-m"); argline[8] = maxhits; for (i = 0, k = 9;;) { for (j = 0; keywords[i] != '\0' && keywords[i] != ' ' && j < MAXSTRLEN; i++) word[j++] = keywords[i]; word[j] = '\0'; argline[k++] = (char *) mystrdup(word); if (keywords[i] == '\0') break; else if (keywords[i] == ' ') i++; } argline[k] = (char *) 0; pipe(pipe0); pipe(pipe1); switch(fork()) { case -1: progerr("fork() call failed."); case 0: close(pipe0[1]); close(pipe1[0]); dup2(pipe0[0], 0); dup2(pipe1[1], 1); execv(waissearchbin, argline); progerr("execv() call failed."); default: close(pipe0[0]); close(pipe1[1]); fp0 = fdopen(pipe1[0], "r"); fp1 = fdopen(pipe0[1], "w"); desc_waissearch(fp0, fp1); } } /* Sets everything up for calling swish and executes it. ** Spits out version information if requested. */ doswish() { int i, j, k; char *argline[MAXARGS], word[MAXSTRLEN], sourcepath[MAXSTRLEN]; int pipe0[2], pipe1[2]; FILE *fp0; argline[0] = swishbin; if (version) { argline[1] = (char *) mystrdup("-V"); argline[2] = (char *) 0; } else { sprintf(sourcepath, "%s%s%s", sourcedir, (sourcedir[strlen(sourcedir) - 1] == '/') ? "" : "/", source); argline[1] = (char *) mystrdup("-f"); argline[2] = sourcepath; argline[3] = (char *) mystrdup("-m"); argline[4] = maxhits; argline[5] = (char *) mystrdup("-w"); for (i = 0, k = 6; k < MAXARGS;) { for (j = 0; keywords[i] != '\0' && keywords[i] != ' ' && j < MAXSTRLEN; i++) word[j++] = keywords[i]; word[j] = '\0'; argline[k++] = (char *) mystrdup(word); if (keywords[i] == '\0') break; else if (keywords[i] == ' ') i++; } argline[k] = (char *) 0; } pipe(pipe0); pipe(pipe1); switch(fork()) { case -1: progerr("fork() call failed."); case 0: close(pipe0[1]); close(pipe1[0]); dup2(pipe0[0], 0); dup2(pipe1[1], 1); execv(swishbin, argline); progerr("execv() call failed."); default: close(pipe0[0]); close(pipe1[1]); fp0 = fdopen(pipe1[0], "r"); read_from_swish(fp0); if (!version) { printheader(); printform(); if (entrylist == NULL) { notfound(); return; } printf("Here is the result of your search using "); printf("the keyword(s) "); printf("<b>\"%s\"</b>:<p>\n", keywords); printf("<dl>\n"); printentries(entrylist); printf("</dl>\n"); } } } /* Malloc's a string; returns it. */ char *mystrdup(s) char *s; { char *p; p = (char *) emalloc(strlen(s) + 1); strcpy(p, s); return p; } /* Makes sure you have enough memory to continue... */ void *emalloc(i) int i; { void *p; if ((p = (void *) malloc(i)) == NULL) progerr("Ran out of memory."); return p; } /* Whoops, caught a problem! */ progerr(errstring) char *errstring; { printf("Content-type: text/html\n\n"); printf("<title>WWWWAIS Error</title>\n"); printf("<h1>WWWWAIS Error</h1>\n"); printf("This program encountered an error:<p>\n"); printf("<code>%s</code>\n<p>\n", errstring); exit(0); } /* Reads returned lines from waisq, grabs the relevant information, ** and sticks it all in the return information structure. */ read_from_waisq(fp) FILE *fp; { int score, lines, bytes, skipline; static char buffer[MAXSTRLEN], filename[MAXSTRLEN], title[MAXSTRLEN], type[MAXSTRLEN], icon[MAXSTRLEN]; skipline = 0; while (fgets(buffer, MAXSTRLEN, fp) != NULL) { if (strstr(buffer, "Information on database") || strstr(buffer, "Catalog for database")) skipline = 1; if (version) { printf("%s\n", buffer); break; } if (strstr(buffer, "Search produced no")) return; if (strstr(buffer, ":score") && !skipline) score = getnumber(buffer, 1); if (strstr(buffer, ":original-local-id") && !skipline) { strcpy(filename, (char *) getqfilename(buffer)); strcpy(type, (char *) gettype(filename)); if (use_icons) strcpy(icon, (char *) geticon(filename)); else strcpy(icon, NO_ICON); strcpy(title, (char *) gettitle(filename, -1)); } if (strstr(buffer, ":number-of-lines") && !skipline) lines = getnumber(buffer, 1); if (strstr(buffer, ":number-of-bytes")) { if (skipline) { skipline = 0; continue; } bytes = getnumber(buffer, 1); entrylist = (struct entry *) addentry(entrylist, score, lines, bytes, filename, title, type, icon, -1); } } } /* Reads returned lines from waissearch, grabs the relevant information, ** and sticks it all in the return information structure. */ read_from_waissearch(fp) FILE *fp; { int i, sdocnum, score, lines, bytes, found; static char buffer[MAXSTRLEN], filename[MAXSTRLEN], title[MAXSTRLEN], type[MAXSTRLEN], icon[MAXSTRLEN]; found = -1; while (fgets(buffer, MAXSTRLEN, fp) != NULL) { if (found == 0) return; if (version) { printf("%s\n", buffer); break; } if (strstr(buffer, "NumberOfRecordsReturned")) { for (i = 0; buffer[i] != ':'; i++) ; for (found = 0; buffer[i]; i++) if (isdigit(buffer[i])) found = (found * 10) + (buffer[i] - '0'); if (!found) return; } if (strstr(buffer, "Information on database") || strstr(buffer, "Catalog for database") || strstr(buffer, "Search produced no") || strstr(buffer, "is not available")) return; if (strstr(buffer, "View document") || strstr(buffer, "q to quit")) return; if (strstr(buffer, "Score:")) { found--; for (i = sdocnum = 0; buffer[i] != ':'; i++) if (isdigit(buffer[i])) sdocnum = (sdocnum * 10) + (buffer[i] - '0'); score = getnumber(buffer, 2); lines = getnumber(buffer, 3); strcpy(filename, (char *) getsfilename(buffer, sdocnum)); bytes = getsize(filename); strcpy(type, (char *) gettype(filename)); if (use_icons) strcpy(icon, (char *) geticon(filename)); else strcpy(icon, NO_ICON); strcpy(title, (char *) gettitle(filename, sdocnum)); entrylist = (struct entry *) addentry(entrylist, score, lines, bytes, filename, title, type, icon, sdocnum); } } } /* Reads lines returned from waissearch and grabs a source ** description or a file. */ desc_waissearch(fp, fp2) FILE *fp; FILE *fp2; { int i, end, srcline, found, isdesc, gotmatch; char *c, *d, buffer[MAXSTRLEN], filename[MAXSTRLEN], maintainer[MAXSTRLEN], cost[MAXSTRLEN], costunit[MAXSTRLEN]; found = -1; gotmatch = 0; while (fgets(buffer, MAXSTRLEN, fp) != NULL) { if (gotmatch && !strchr(buffer, ':')) break; if (strstr(buffer, "NumberOfRecordsReturned")) { found = getnumber(buffer, 1); if (!found) return; } if (strstr(buffer, "Information on database") || strstr(buffer, "Catalog for database") || strstr(buffer, "Search produced no") || strstr(buffer, "is not available")) return; if ((c = (char *) strstr(buffer, "lines:")) != NULL && !gotmatch) { for (i = srcline = 0; buffer[i] != ':'; i++) if (isdigit(buffer[i])) srcline = (srcline * 10) + (buffer[i] - '0'); strcpy(filename, getsfilename(buffer, srcline)); if (docnum == srcline) gotmatch = 1; } } fprintf(fp2, "%d\n", srcline); fflush(fp2); fgets(buffer, MAXSTRLEN, fp); if (lstrstr(filename, ".src")) { isdesc = 1; end = 0; while (fgets(buffer, MAXSTRLEN, fp) != NULL && !end) { if ((c = (char *) strstr(buffer, ":ip-name")) != NULL) { c += strlen(":ip-name"); strcpy(host, getword(c, &i)); } else if ((c = (char *) strstr(buffer, ":cost ")) != NULL) { c += strlen(":cost "); strcpy(cost, getword(c, &i)); } else if ((c = (char *) strstr(buffer, ":cost-unit :")) != NULL) { c += strlen(":cost-unit :"); strcpy(costunit, getword(c, &i)); } else if ((c = (char *) strstr(buffer, ":tcp-port")) != NULL) { c += strlen(":tcp-port"); strcpy(port, getword(c, &i)); } else if ((c = (char *) strstr(buffer, ":database-name")) != NULL) { c += strlen(":database-name"); strcpy(source, getword(c, &i)); } else if ((c = (char *) strstr(buffer, ":maintainer")) != NULL ) { c += strlen(":maintainer"); strcpy(maintainer, getword(c, &i)); } else if ((c = (char *) strstr(buffer, ":description")) != NULL) { strcpy(buffer, replace(buffer, "\\\"", "\'")); c = (char *) strchr(buffer, '\"'); while (c == NULL) { fgets(buffer, MAXSTRLEN, fp); c = (char *) strchr(buffer, '\"'); } c++; if (numchar(buffer, '\"') == 2 && (d = (char *) strrchr(buffer, '\"'))) { *d = '\0'; desclist = (struct source *) addsource(desclist, c); break; } desclist = (struct source *) addsource(desclist, c); while (fgets(buffer, MAXSTRLEN, fp) != NULL) { strcpy(buffer, replace(buffer, "\\\"", "\'")); if (c = (char *) strchr(buffer, '\"')) { *c = '\0'; desclist = (struct source *) addsource(desclist, buffer); end = 1; break; } desclist = (struct source *) addsource(desclist, buffer); } } } } else { isdesc = 0; while (fgets(buffer, 40, fp) != NULL) { if (!strncmp(buffer, "View doc", 8)) break; bodylist = (struct source *) addsource(bodylist, buffer); } } fprintf(fp2, "q\n"); fflush(fp2); fprintf(fp2, "q\n"); fflush(fp2); indexsources = 0; if (isdesc) { no_options = 1; printheader(); printform(); printf("<h2>Database name: %s</h2>\n<p>\n", source); printf("<b>Maintainer:</b> <a href=\"mailto:%s\">%s</a>\n<p>\n", maintainer, maintainer); printf("<b>Description:</b>\n<p>\n"); printf("<pre>\n"); while (desclist != NULL) { printf("%s", desclist->line); desclist = desclist->next; } printf("</pre>\n<p>\n"); printf("<b>Cost:</b> %s<br>\n", cost); printf("<b>Cost-unit:</b> %s<br>\n", costunit); printf("<b>Host:</b> %s<br>\n", host); printf("<b>Port:</b> %s<p>\n", port); printfooter(); } else { printf("Content-type: %s\n\n", getmime(filename)); while (bodylist != NULL) { printf("%s", bodylist->line); bodylist = bodylist->next; } } } /* Reads returned lines from swish, grabs the relevant information, ** and sticks it all in the return information structure. */ read_from_swish(fp) FILE *fp; { int i, j, score, bytes; static char buffer[MAXSTRLEN], filename[MAXSTRLEN], title[MAXSTRLEN], type[MAXSTRLEN], icon[MAXSTRLEN]; while (fgets(buffer, MAXSTRLEN, fp) != NULL) { if (version) { printf("%s version: %s\n", swishbin, buffer); break; } if (buffer[0] == '.' || buffer[0] == 'e') break; if (buffer[0] == '#' || buffer[0] == 's') continue; if (strstr(buffer, "no results")) return; for (i = score = 0; isdigit(buffer[i]); i++) score = (score * 10) + (buffer[i] - '0'); for (i++, j = 0; buffer[i] != ' '; i++) filename[j++] = buffer[i]; filename[j] = '\0'; for (i += 2, j = 0; buffer[i] != '\"'; i++) title[j++] = buffer[i]; title[j] = '\0'; for (i += 2, bytes = 0; isdigit(buffer[i]); i++) bytes = (bytes * 10) + (buffer[i] - '0'); strcpy(type, (char *) gettype(filename)); if (use_icons) strcpy(icon, (char *) geticon(filename)); else strcpy(icon, NO_ICON); entrylist = (struct entry *) addentry(entrylist, score, -1, bytes, filename, title, type, icon, -1); } } /* Prints the generic form for searching. */ printform() { printf("<hr><form method=\"POST\" action=\"%s\">\n", selfurl); printf("This is a searchable index of information.<br>\n"); printf("<b>Note:</b> <i>This service can only be used from a forms-"); printf("capable browser.</i><p>\n"); printf("Enter keyword(s): "); printf("<input type=text name=\"keywords\" value=\"%s\" size=30> ", keywords); printf("<input type=submit value=\" Search \"> "); printf("<input type=reset value=\" Reset \">\n<p>\n"); if (indexsources > 1) { printf("Select an index to search: "); printf("<select name=\"selection\">\n"); while (sourcelist != NULL) { printf("<option%s> %s\n", (lstrstr(sourcelist->line, selection)) ? " selected" : "", sourcelist->line); sourcelist = sourcelist->next; } printf("</select>\n<p>\n"); } printf("<input type=hidden name=message value=\"%s\">\n", "If you can see this, then your browser can't support hidden fields."); printf("<input type=hidden name=source value=\"%s\">\n", source); printf("<input type=hidden name=sourcedir value=\"%s\">\n", sourcedir); printf("<input type=hidden name=maxhits value=\"%s\">\n", maxhits); printf("<input type=hidden name=sorttype value=\"%s\">\n", sorttype); printf("<input type=hidden name=host value=\"%s\">\n", host); printf("<input type=hidden name=port value=\"%s\">\n", port); printf("<input type=hidden name=searchprog value=\"%s\">\n", searchprog); printf("<input type=hidden name=iconurl value=\"%s\">\n", iconurl); printf("<input type=hidden name=useicons value=\"%s\">\n", useicons); if (no_options) printf("<input type=hidden name=selection value=\"%s\">\n", NO_SELECT); printf("</form><hr>\n"); } /* Address authorization failed... */ printreject() { printheader(); printf("<hr>\nSorry, your site either does not have the proper "); printf("authorization to use this WAIS index or your "); printf("address could not be determined."); } /* Grabs a number from a particular field in a line returned ** by waisq or waissearch, usually. */ int getnumber(line, field) char *line; int field; { int i, j, k; for (i = k = 0; k != field; k++) { for (j = 0; line[i] && !isdigit(line[i]); i++) ; if (!line[i]) return 0; while (isdigit(line[i])) j = (j * 10) + (line[i++] - '0'); } return j; } /* Grabs filename information from waisq. */ char *getqfilename(line) char *line; { int i, num, spaces; static char filename[MAXSTRLEN]; char *c; c = (char *) strstr(line, "#(") + 2; for (i = num = spaces = 0; *c != '\0'; c++) { if (isdigit(*c)) { while (isdigit(*c)) { num = (num * 10) + (*c - '0'); c++; } if (spaces >= 2) filename[i++] = num; if (num == 32) spaces++; num = 0; } } filename[i] = '\0'; return filename; } /* Grabs filename information returned from waissearch. I don't ** like this very much... */ char *getsfilename(line, sdocnum) char *line; int sdocnum; { int i; char *c; static char filename[MAXSTRLEN], wholeline[MAXSTRLEN], suffix[MAXSTRLEN], prefix[MAXSTRLEN]; c = (char *) strchr(line, '\'') + 1; for (i = 0; *c && i < MAXSTRLEN && *c != '\''; c++) wholeline[i++] = *c; wholeline[i] = '\0'; if ((!strchr(wholeline, '/') || !strchr(wholeline, '.')) || sdocnum <= 0) return wholeline; c = (char *) strchr(line, '\'') + 1; for (i = 0; *c && i < MAXSTRLEN && *c != '\'' && !isspace(*c); c++) suffix[i++] = *c; suffix[i] = '\0'; if (strstr(suffix, "://")) return suffix; while (*c && isspace(*c)) c++; for (i = 0; *c && *c != '\'' && !isspace(*c) && i < MAXSTRLEN; c++) prefix[i++] = *c; prefix[i] = '\0'; sprintf(filename, "%s%s", prefix, suffix); return filename; } /* Depending on the suffix, gets the type of file. */ char *gettype(filename) char *filename; { struct suffixentry *tmplist; static char tmpsuffix[MAXSTRLEN], desc[MAXSTRLEN]; if (!strchr(filename, '.')) return unknown_type; tmplist = suffixlist; while (tmplist != NULL) { strcpy(tmpsuffix, strrchr(filename, '.')); if (lstrstr(tmpsuffix, tmplist->suffix) && strlen(tmpsuffix) == strlen(tmplist->suffix)) { strcpy(desc, tmplist->desc); return desc; } tmplist = tmplist->next; } return unknown_type; } /* Depending on the suffix, gets the right icon URL. */ char *geticon(filename) char *filename; { struct suffixentry *tmplist; static char tmpsuffix[MAXSTRLEN], url[MAXSTRLEN]; if (!strchr(filename, '.')) return unknown_icon; tmplist = suffixlist; while (tmplist != NULL) { strcpy(tmpsuffix, strrchr(filename, '.')); if (lstrstr(tmpsuffix, tmplist->suffix) && strlen(tmpsuffix) == strlen(tmplist->suffix)) { strcpy(url, tmplist->url); return url; } tmplist = tmplist->next; } return unknown_icon; } /* Depending on the suffix, gets the right MIME type. */ char *getmime(filename) char *filename; { struct suffixentry *tmplist; static char tmpsuffix[MAXSTRLEN], mime[MAXSTRLEN]; if (!strchr(filename, '.')) return unknown_mime; tmplist = suffixlist; while (tmplist != NULL) { strcpy(tmpsuffix, strrchr(filename, '.')); if (lstrstr(tmpsuffix, tmplist->suffix) && strlen(tmpsuffix) == strlen(tmplist->suffix)) { strcpy(mime, tmplist->mime); return mime; } tmplist = tmplist->next; } return unknown_mime; } /* From the returned filename, tries to extract a title of string of ** some sort for displaying on the page. This is the ugly part. ** If the file is a local HTML file, this extracts the title if ** it exists. */ char *gettitle(filename, sdocnum) char *filename; int sdocnum; { int i, j; static char title[MAXTITLELEN], tmpline[MAXSTRLEN]; FILE *fp; if (sdocnum > 0 && strstr(filename, " ") && strchr(filename, '/')) { for (i = j = 0; filename[i] && !isspace(filename[i]); i++) tmpline[j++] = filename[i]; tmpline[j] = '\0'; return tmpline; } if (strrchr(filename, '/') && filename[strlen(filename)] != '/') strcpy(tmpline, (char *) strrchr(filename, '/') + 1); else strcpy(tmpline, filename); if (!lstrstr(tmpline, ".html")) return tmpline; if ((fp = fopen(filename, "r")) == NULL) return tmpline; strcpy(title, parsetitle(fp)); fclose(fp); if (strlen(title) > 0) return title; return tmpline; } /* Extract information within <title> tags, case insensitive, ** can be over multiple lines... */ char *parsetitle(fp) FILE *fp; { register char c, *p, *q; char title[MAXTITLELEN], tag[MAXTITLELEN]; int lines, status; lines = status = 0; p = title; *p = '\0'; for (; lines < TITLETOPLINES ; ) { c = getc(fp); if (c == '\n') lines++; if (feof(fp)) return title; switch(c) { case '<': tag[0] = c; status = TI_OPEN; for (q = tag + 1;; q++) { *q = getc(fp); if (*q == '>') { q++; break; } } *q = '\0'; q = tag; if (lstrstr(q, "</title>")) { status = TI_CLOSE; *p = '\0'; return title; } else { if (lstrstr(q, "<title>")) status = TI_FOUND; } break; default: if (status == TI_FOUND) { *p = c; p++; } else { if (status == TI_CLOSE) return title; } } } return title; } /* Decodes URL-encoded strings. */ char *decode(s) char *s; { int i, j, ascint; char firstnum, secondnum; static char newstr[MAXSTRLEN]; for (i = j = 0; s[i]; i++) { if (s[i] == '%') { firstnum = s[++i]; secondnum = s[++i]; ascint = (getascii(firstnum) * 16) + getascii(secondnum); if (ascint == 10 || ascint == 13) ascint = 32; newstr[j++] = (char) ascint; continue; } else if (s[i] == '+') newstr[j++] = ' '; else newstr[j++] = s[i]; } newstr[j] = '\0'; return newstr; } /* Returns the right ASCII code for a hex value. */ int getascii(hex) char hex; { if ((int) hex >= 48 && (int) hex <= 57) return (hex - 48); else return (hex - 65 + 10); } /* Encodes strings so they can be put in URLs. */ char *encode(s) char *s; { int i; char hexstr[HEXLEN]; static char line[MAXSTRLEN]; for (i = 0; *s; s++) if (*s == ' ') line[i++] = '+'; else if (isdigit(*s) || isalpha(*s)) line[i++] = *s; else { sprintf(hexstr, "%0X", *s); line[i++] = '%'; line[i++] = hexstr[0]; line[i] = hexstr[1]; if (line[i] == '\0') { line[i] = line[i - 1]; line[i - 1] = '0'; } i++; } line[i] = '\0'; return line; } /* lstrstr() is the Boyer-Moore algorithm from Sedgewick. Where else? :) */ initskip(s, len) char *s; int len; { int i, j; for (i = 0; i < MAXSTRLEN; i++) skip[i] = len; for (j = 0; j <= len - 1; j++) skip[lstrindex(s[j])] = len - j - 1; } int lstrindex(c) char c; { char d; d = tolower(c); if (d >= 'a' && d <= 'z') return (d - 'a' + 1); else return 0; } char *lstrstr(s, t) char *s; char *t; { int i, j, k, slen, tlen; slen = strlen(s); tlen = strlen(t); initskip(t, tlen); for (i = j = tlen - 1; j > 0; i--, j--) { while (tolower(s[i]) != tolower(t[j])) { k = skip[lstrindex(s[i])]; i += (tlen - j > k) ? tlen - j : k; if (i >= slen) return NULL; j = tlen - 1; } } return (s + i); } /* Add information returned from waisq and waissearch into a binary tree ** so it can be sorted and displayed nicely. */ struct entry *addentry(e, score, lines, bytes, filename, title, type, icon, docnum) struct entry *e; int score; int lines; int bytes; char *filename; char *title; char *type; char *icon; int docnum; { int isbigger; if (strstr(filename, "--------")) return e; if (e == NULL) { e = (struct entry *) emalloc(sizeof(struct entry)); e->score = score; e->lines = lines; e->bytes = bytes; e->docnum = docnum; e->filename = (char *) mystrdup(filename); e->title = (char *) mystrdup(title); e->type = (char *) mystrdup(type); e->icon = (char *) mystrdup(icon); e->left = e->right = NULL; } else { if (!strcmp(sorttype, "score")) isbigger = (e->score >= score) ? 1 : 0; else if (!strcmp(sorttype, "lines")) isbigger = (e->lines >= lines) ? 1 : 0; else if (!strcmp(sorttype, "bytes")) isbigger = (e->bytes >= bytes) ? 1 : 0; else if (!strcmp(sorttype, "title")) isbigger = (strcmp(e->title, title) < 0) ? 1 : 0; else if (!strcmp(sorttype, "type")) isbigger = (strcmp(e->type, type) < 0) ? 1 : 0; if (isbigger) e->left = addentry(e->left, score, lines, bytes, filename, title, type, icon, docnum); else e->right = addentry(e->right, score, lines, bytes, filename, title, type, icon, docnum); } return e; } /* Prints everything in the entry structures and adds extra information ** in the URLs so we know what to do next time. */ printentries(e) struct entry *e; { static int number; static char newfilename[MAXSTRLEN], tmpfilename[MAXSTRLEN]; if (e != NULL) { printentries(e->right); number++; printf("<dt> <b>%d: </b>", number); if (use_icons) printf("<img src=\"%s\" align=\"bottom\" alt=\"\">\n ", e->icon); if (ruleslist != NULL) { strcpy(newfilename, ruleparse(e->filename)); strcpy(tmpfilename, newfilename); sprintf(newfilename, replace(tmpfilename, KEYWORDVAR, encode(keywords))); } else strcpy(newfilename, e->filename); if (lstrstr(e->filename, ".src")) { strcpy(tmpfilename, encode(keywords)); printf("<a href=\"%s?%s%s&%s%s&%s%s&%s%s&%s%s&%s%s", selfurl, DESCTXT, "yes", HOSTTXT, host, PORTTXT, port, SOURCETXT, source, SEARCHPROGTXT, "waissearch", SELECTTXT, NO_SELECT); printf("&%s%d&%s%s\">", DOCNUMTXT, e->docnum, KEYWORDSTXT, tmpfilename); } else if (e->docnum != -1 && !strstr(newfilename, "://")) { strcpy(tmpfilename, encode(keywords)); printf("<a href=\"%s?%s%s&%s%s&%s%s&%s%s&%s%s&", selfurl, DESCTXT, "yes", HOSTTXT, host, PORTTXT, port, SOURCETXT, source, SEARCHPROGTXT, "waissearch"); printf("%s%s&%s%d&%s%s\">", SELECTTXT, NO_SELECT, DOCNUMTXT, e->docnum, KEYWORDSTXT, tmpfilename); } else printf("<a href=\"%s\">", newfilename); printf("%s</a>\n", e->title); printf("<dd> Score: <b>%d</b>", e->score); if (e->lines >= 0) printf(", Lines: <b>%d</b>", e->lines); if (e->bytes < 0) printf(""); else if (e->bytes <= 1000) printf(", Size: <b>%d bytes", e->bytes); else printf(", Size: <b>%d kbytes", e->bytes / 1000); printf("</b>"); printf(", Type: <b>%s</b>\n", e->type); printentries(e->left); } } /* Parses lines according to the SourceRules directives. */ char *ruleparse(line) char *line; { char rule[MAXSTRLEN]; static char tmpline[MAXSTRLEN], newtmpline[MAXSTRLEN]; static char line1[MAXSTRLEN], line2[MAXSTRLEN]; struct source *tmplist; tmplist = ruleslist; strcpy(tmpline, line); while(1) { strcpy(rule, getrule()); if (rule[0] == '\0') { ruleslist = tmplist; return tmpline; } else { if (lstrstr(rule, "replace")) { strcpy(line1, getrule()); strcpy(line2, getrule()); strcpy(newtmpline, replace(tmpline, line1, line2)); } else if (lstrstr(rule, "append")) sprintf(newtmpline, "%s%s", tmpline, getrule()); else if (lstrstr(rule, "prepend")) sprintf(newtmpline, "%s%s", getrule(), tmpline); strcpy(tmpline, newtmpline); } } } /* Grabs the next rule from the list. */ char *getrule() { static char rule[MAXSTRLEN]; if (ruleslist == NULL) return "\0"; strcpy(rule, ruleslist->line); ruleslist = ruleslist->next; return rule; } /* Couldn't find something... */ notfound() { printf("Sorry, I didn't find any documents that matched your "); printf("search for \"<b>%s</b>\"!", keywords); } /* What is the physical size of a file? */ int getsize(path) char *path; { struct stat stbuf; if (stat(path, &stbuf)) return -1; return stbuf.st_size; } /* Does a file exist? */ int isfile(path) char *path; { struct stat stbuf; if (stat(path, &stbuf)) return 0; return ((stbuf.st_mode & S_IFMT) == S_IFREG) ? 1 : 0; } /* Split up multiple address masks and check them. */ int isokstring(string, mask) char *string; char *mask; { int i; char *s, *t; if (lstrstr(mask, "all")) return 1; i = 0; t = (char *) mystrdup(mask); while (1) { s = (char *) strtok((i++) ? NULL : t, ","); if (s == NULL) break; if (isinname(string, s)) { free(t); return 1; } } free(t); return 0; } /* Does an address mask fit the user's address? */ int isinname(string, mask) char *string; char *mask; { int i, j; char firstchar, lastchar, *tempmask; if (!strcmp(mask, "*")) return 1; firstchar = mask[0]; lastchar = mask[(strlen(mask) - 1)]; tempmask = (char *) emalloc(strlen(mask)); for (i = j = 0; mask[i]; i++) if (mask[i] != '*') tempmask[j++] = mask[i]; tempmask[j] = '\0'; if (firstchar == '*') { if (lastchar == '*') { if ((char *) strstr(string, tempmask)) { free(tempmask); return 1; } } else { if ((char *) strstr(string, tempmask) == string + strlen(string) - strlen(tempmask)) { free(tempmask); return 1; } } } else if (lastchar == '*') { if ((char *) strstr(string, tempmask) == string) { free(tempmask); return 1; } } else { if (!strcmp(string, tempmask)) { free(tempmask); return 1; } } free(tempmask); return 0; } /* Reads the config file and grabs all the values it can find. */ getdefaults() { int found, skiplen; char *c, line[MAXSTRLEN], value[MAXSTRLEN], sourcepath[MAXSTRLEN], lineselection[MAXSTRLEN], suffix[MAXSTRLEN], desc[MAXSTRLEN], url[MAXSTRLEN], mime[MAXSTRLEN], rule[MAXSTRLEN]; FILE *fp; found = 0; strcpy(lineselection, selection); if ((fp = fopen(CONFFILE, "r")) == NULL) progerr("Couldn't open configuration file."); while (fgets(line, MAXSTRLEN, fp) != NULL) { if (line[0] == '#' || line[0] == '\n') continue; if (getconfvalue(line, "pagetitle", value) != NULL) strcpy(pagetitle, value); else if (getconfvalue(line, "selfurl", value) != NULL) strcpy(selfurl, value); else if (getconfvalue(line, "maxhits", value) != NULL) strcpy(maxhits, value); else if (getconfvalue(line, "addrmask", value) != NULL) strcpy(addrmask, value); else if (getconfvalue(line, "iconurl", value) != NULL) strcpy(iconurl, value); else if (getconfvalue(line, "sorttype", value) != NULL) strcpy(sorttype, value); else if (getconfvalue(line, "swishbin", value) != NULL) strcpy(swishbin, value); else if (getconfvalue(line, "waisqbin", value) != NULL) strcpy(waisqbin, value); else if (getconfvalue(line, "waissearchbin", value) != NULL) strcpy(waissearchbin, value); else if (getconfvalue(line, "useicons", value) != NULL) strcpy(useicons, value); else if ((c = (char *) lstrstr(line, "sourcerules")) && found == 1) { c += strlen("sourcerules"); while (1) { strcpy(rule, getword(c, &skiplen)); if (!skiplen | rule[0] == '\0' || rule[0] == '\n') break; else { c += skiplen; ruleslist = (struct source *) addsource(ruleslist, rule); } } } else if (c = (char *) lstrstr(line, "typedef")) { c += strlen("typedef"); strcpy(suffix, getword(c, &skiplen)); c += skiplen; strcpy(desc, getword(c, &skiplen)); c += skiplen; strcpy(url, getword(c, &skiplen)); c += skiplen; strcpy(mime, getword(c, &skiplen)); suffixlist = (struct suffixentry *) addsuffix(suffixlist, suffix, desc, url, mime); } else if (c = (char *) lstrstr(line, "waissource")) { if (no_options) continue; indexsources++; sourcelist = (struct source *) addsource(sourcelist, getdesc(line)); if (found > 0) { found++; continue; } if ((lineselection[0] == '\0') || lstrstr(line, lineselection)) found = use_selection = 1; if (iswqsource(line)) { strcpy(searchprog, "waisq"); c += strlen("waissource"); strcpy(sourcepath, getword(c, &skiplen)); c += skiplen; strcpy(selection, getword(c, &skiplen)); if (strchr(sourcepath, '/') == NULL) { sourcedir[0] = '\0'; strcpy(source, sourcepath); } else { strcpy(source, strrchr(sourcepath, '/') + 1); strncpy(sourcedir, sourcepath, strlen(sourcepath) - strlen(source)); } } else { strcpy(searchprog, "waissearch"); strcpy(sourcedir, ""); c += strlen("waissource"); strcpy(host, getword(c, &skiplen)); c += skiplen; strcpy(port, getword(c, &skiplen)); c += skiplen; strcpy(source, getword(c, &skiplen)); c += skiplen; strcpy(selection, getword(c, &skiplen)); } } else if (c = (char *) lstrstr(line, "swishsource")) { if (no_options) continue; indexsources++; sourcelist = (struct source *) addsource(sourcelist, getdesc(line)); if (found > 0) { found++; continue; } if ((lineselection[0] == '\0') || lstrstr(line, lineselection)) found = use_selection = 1; strcpy(searchprog, "swish"); c += strlen("swishsource"); strcpy(sourcepath, getword(c, &skiplen)); c += skiplen; strcpy(selection, getword(c, &skiplen)); if (strchr(sourcepath, '/') == NULL) { sourcedir[0] = '\0'; strcpy(source, sourcepath); } else { strcpy(source, strrchr(sourcepath, '/') + 1); strncpy(sourcedir, sourcepath, strlen(sourcepath) - strlen(source)); } } } fclose(fp); } /* Is a waissource line describing a waisq source or a waissearch source? */ int iswqsource(line) char *line; { int skiplen; char *c, tmpline[MAXSTRLEN]; c = line; c += strlen("waissource"); strcpy(tmpline, getword(c, &skiplen)); c += skiplen; strcpy(tmpline, getword(c, &skiplen)); if (isnum(tmpline)) return 0; else return 1; } /* Is a string a number? */ int isnum(line) char *line; { int i; for (i = 0; line[i]; i++) if (!isdigit(line[i])) return 0; return 1; } /* Grabs values from lines with variables. If the line is in quotes, ** spaces are counted as part of the value. */ char *getconfvalue(line, var, value) char *line; char *var; char *value; { int i; char *c; static char tmpvalue[MAXSTRLEN]; if ((c = (char *) lstrstr(line, var)) != NULL) { if (c != line) return NULL; c += strlen(var); while (isspace(*c) || *c == '\"') c++; if (*c == '\0') return NULL; for (i = 0; *c != '\0' && *c != '\"' && *c != '\n' && i < MAXSTRLEN; c++) tmpvalue[i++] = *c; tmpvalue[i] = '\0'; strcpy(value, tmpvalue); return tmpvalue; } else return NULL; } /* Grabs a source description (for the pop-up menu) for sources ** specified in the config file. */ char *getdesc(line) char *line; { int i; char *c; static char desc[MAXSTRLEN]; if ((c = (char *) strchr(line, '\"')) == NULL) return NO_DESC; c++; for (i = 0; *c && *c != '\"' && i < MAXSTRLEN; c++) desc[i++] = *c; desc[i] = '\0'; return desc; } /* Generic list for storing files, source descriptions, and rules. */ struct source *addsource(sp, line) struct source *sp; char *line; { struct source *tempnode, *newnode; newnode = (struct source *) emalloc(sizeof(struct source)); newnode->line = (char *) mystrdup(line); newnode->next = NULL; if (sp == NULL) sp = newnode; else { for (tempnode = sp; tempnode->next != NULL; tempnode = tempnode->next) ; tempnode->next = newnode; } return sp; } /* The list that holds all the suffixes for checking against filenames. */ struct suffixentry *addsuffix(sp, suffix, desc, url, mime) struct suffixentry *sp; char *suffix; char *desc; char *url; char *mime; { struct suffixentry *tempnode, *newnode; newnode = (struct suffixentry *) emalloc(sizeof(struct suffixentry)); newnode->suffix = (char *) mystrdup(suffix); newnode->desc = (char *) mystrdup(desc); newnode->url = (char *) mystrdup(replace(url, ICONVAR, iconurl)); newnode->mime = (char *) mystrdup(mime); newnode->next = NULL; if (!strcmp(suffix, ".??")) { strcpy(unknown_icon, replace(url, ICONVAR, iconurl)); strcpy(unknown_type, desc); strcpy(unknown_mime, mime); } if (sp == NULL) sp = newnode; else { for (tempnode = sp; tempnode->next != NULL; tempnode = tempnode->next) ; tempnode->next = newnode; } return sp; } /* In a string, replaces all occurrences of "oldpiece" with "newpiece". ** Not sure if this is bulletproof yet. */ char *replace(string, oldpiece, newpiece) char *string; char *oldpiece; char *newpiece; { int i, j, limit; char *c; char beforestring[MAXSTRLEN], afterstring[MAXSTRLEN]; static char newstring[MAXSTRLEN]; if ((c = (char *) strstr(string, oldpiece)) == NULL) return string; limit = c - string; for (i = 0; i < limit; i++) beforestring[i] = string[i]; beforestring[i] = '\0'; i += strlen(oldpiece); for (j = 0; string[i] != '\0'; i++) afterstring[j++] = string[i]; afterstring[j] = '\0'; sprintf(newstring, "%s%s%s", beforestring, newpiece, afterstring); while (strstr(newstring, oldpiece)) strcpy(newstring, replace(newstring, oldpiece, newpiece)); return newstring; } /* From a line, grabs the next word and returns it. If the word is ** in quotes, spaces (and other characters) are counted as part of the word. */ char *getword(line, skiplen) char *line; int *skiplen; { int i, inquotes; char *start; static char word[MAXSTRLEN]; start = line; if (!(*line)) return "\0"; while (isspace(*line)) line++; if (!(*line)) return "\0"; if (*line == '\"') { inquotes = 1; line++; } else inquotes = 0; for (i = 0; *line && i < MAXSTRLEN && ((inquotes) ? (*line != '\"') : (!isspace(*line))); line++) word[i++] = *line; word[i] = '\0'; if (!(*line)) return "\0"; if (*line == '\"') line++; *skiplen = line - start; return word; } /* How many times does the a character appear in a line? */ int numchar(line, c) char *line; char c; { int i; for (i = 0; *line; line++) if (*line == c) i++; return i; } /* Error messages for broken pipes, SIGSEGV, and timing out. */ void badconnection() { progerr("Can't connect to this WAIS server (it is probably down)."); } void badsegviol() { progerr("Caught a memory violation (probably a parsing error)."); } void badtimeout() { char message[MAXSTRLEN]; sprintf(message, "This service timed out (%d seconds) - it may be too busy.", TIMEOUT); progerr(message); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.