/* * Parse command-line arguments */ void parse_args(state *st, int argc, char *argv[]) { FILE *fp; static const char readme[] = README; static const char license[] = LICENSE; struct stat file; char buf[BUFSIZE]; int opt; /* Parse args */ while ((opt = getopt(argc, argv, "h:p:r:t:g:a:c:u:m:l:w:o:s:i:k:f:e:R:D:L:A:P:n:db?-")) != ERROR) { switch(opt) { case 'h': sstrlcpy(st->server_host, optarg); break; case 'p': st->server_port = atoi(optarg); break; case 'r': sstrlcpy(st->server_root, optarg); break; case 't': st->default_filetype = *optarg; break; case 'g': sstrlcpy(st->map_file, optarg); break; case 'a': sstrlcpy(st->map_file, optarg); break; case 'c': sstrlcpy(st->cgi_file, optarg); break; case 'u': sstrlcpy(st->user_dir, optarg); break; case 'm': /* obsolete, replaced by -l */ case 'l': sstrlcpy(st->log_file, optarg); break; case 'w': st->out_width = atoi(optarg); break; case 'o': if (sstrncasecmp(optarg, "UTF-8") == MATCH) st->out_charset = UTF_8; if (sstrncasecmp(optarg, "ISO-8859-1") == MATCH) st->out_charset = ISO_8859_1; break; case 's': st->session_timeout = atoi(optarg); break; case 'i': st->session_max_kbytes = abs(atoi(optarg)); break; case 'k': st->session_max_hits = abs(atoi(optarg)); break; case 'f': sstrlcpy(st->filter_dir, optarg); break; case 'e': add_ftype_mapping(st, optarg); break; case 'R': add_rewrite_mapping(st, optarg); break; case 'D': sstrlcpy(st->server_description, optarg); break; case 'L': sstrlcpy(st->server_location, optarg); break; case 'A': sstrlcpy(st->server_admin, optarg); break; case 'n': if (*optarg == 'v') { st->opt_vhost = FALSE; break; } if (*optarg == 'l') { st->opt_parent = FALSE; break; } if (*optarg == 'h') { st->opt_header = FALSE; break; } if (*optarg == 'f') { st->opt_footer = FALSE; break; } if (*optarg == 'd') { st->opt_date = FALSE; break; } if (*optarg == 'c') { st->opt_magic = FALSE; break; } if (*optarg == 'o') { st->opt_iconv = FALSE; break; } if (*optarg == 'q') { st->opt_query = FALSE; break; } if (*optarg == 's') { st->opt_syslog = FALSE; break; } if (*optarg == 'a') { st->opt_caps = FALSE; break; } if (*optarg == 'm') { st->opt_shm = FALSE; break; } if (*optarg == 'r') { st->opt_root = FALSE; break; } break; case 'd': st->debug = TRUE; break; case 'b': puts(license); exit(EXIT_SUCCESS); default : puts(readme); exit(EXIT_SUCCESS); } } /* Sanitize options */ if (st->out_width > MAX_WIDTH) st->out_width = MAX_WIDTH; if (st->out_width < MIN_WIDTH) st->out_width = MIN_WIDTH; if (st->out_width < MIN_WIDTH + DATE_WIDTH) st->opt_date = FALSE; if (!st->opt_syslog) st->debug = FALSE; /* Primary vhost directory must exist or we disable vhosting */ if (st->opt_vhost) { snprintf(buf, sizeof(buf), "%s/%s", st->server_root, st->server_host); if (stat(buf, &file) == ERROR) st->opt_vhost = FALSE; } /* If -D arg looks like a file load the file contents */ if (*st->server_description == '/') { if ((fp = fopen(st->server_description , "r"))) { fgets(st->server_description, sizeof(st->server_description), fp); chomp(st->server_description); fclose(fp); } else strclear(st->server_description); } /* If -L arg looks like a file load the file contents */ if (*st->server_location == '/') { if ((fp = fopen(st->server_location , "r"))) { fgets(st->server_location, sizeof(st->server_location), fp); chomp(st->server_location); fclose(fp); } else strclear(st->server_location); } }
/* * Handle gophermaps */ int gophermap(state *st, char *mapfile, int depth) { FILE *fp; struct stat file; char line[BUFSIZE]; #ifdef HAVE_POPEN char command[BUFSIZE]; #endif char *selector; char *name; char *host; char *c; char type; int port; int exe; /* Prevent include loops */ if (depth > 4) return OK; /* Try to figure out whether the map is executable */ if (stat(mapfile, &file) == OK) { if ((file.st_mode & S_IXOTH)) { #ifdef HAVE_POPEN /* Quote the command in case path has spaces */ snprintf(command, sizeof(command), "'%s'", mapfile); #endif exe = TRUE; } else exe = FALSE; } /* This must be a shell include */ else { #ifdef HAVE_POPEN /* Let's assume the shell command runs as is without quoting */ sstrlcpy(command, mapfile); #endif exe = TRUE; } /* Debug output */ if (st->debug) { if (exe) syslog(LOG_INFO, "parsing executable gophermap \"%s\"", mapfile); else syslog(LOG_INFO, "parsing static gophermap \"%s\"", mapfile); } /* Try to execute or open the mapfile */ #ifdef HAVE_POPEN if (exe) { setenv_cgi(st, mapfile); if ((fp = popen(command, "r")) == NULL) return OK; } else #endif if ((fp = fopen(mapfile, "r")) == NULL) return OK; /* Read lines one by one */ while (fgets(line, sizeof(line) - 1, fp)) { /* Parse type & name */ chomp(line); type = line[0]; name = line + 1; /* Ignore #comments */ if (type == '#') continue; /* Stop handling gophermap? */ if (type == '*') return OK; if (type == '.') return QUIT; /* Print a list of users with public_gopher */ if (type == '~') { #ifdef HAVE_PASSWD userlist(st); #endif continue; } /* Print a list of available virtual hosts */ if (type == '%') { if (st->opt_vhost) vhostlist(st); continue; } /* Hide files in menus */ if (type == '-') { if (st->hidden_count < MAX_HIDDEN) sstrlcpy(st->hidden[st->hidden_count++], name); continue; } /* Override filetype mappings */ if (type == ':') { add_ftype_mapping(st, name); continue; } /* Include gophermap or shell exec */ if (type == '=') { gophermap(st, name, depth + 1); continue; } /* Title resource */ if (type == TYPE_TITLE) { info(st, name, TYPE_TITLE); continue; } /* Print out non-resources as info text */ if (!strchr(line, '\t')) { info(st, line, TYPE_INFO); continue; } /* Parse selector */ selector = EMPTY; if ((c = strchr(name, '\t'))) { *c = '\0'; selector = c + 1; } if (!*selector) selector = name; /* Parse host */ host = st->server_host; if ((c = strchr(selector, '\t'))) { *c = '\0'; host = c + 1; } /* Parse port */ port = st->server_port; if ((c = strchr(host, '\t'))) { *c = '\0'; port = atoi(c + 1); } /* Handle remote, absolute and hURL gopher resources */ if (sstrncmp(selector, "URL:") == MATCH || selector[0] == '/' || host != st->server_host) { printf("%c%s\t%s\t%s\t%i" CRLF, type, name, selector, host, port); } /* Handle relative resources */ else { printf("%c%s\t%s%s\t%s\t%i" CRLF, type, name, st->req_selector, selector, host, port); /* Automatically hide manually defined selectors */ #ifdef ENABLE_AUTOHIDING if (st->hidden_count < MAX_HIDDEN) sstrlcpy(st->hidden[st->hidden_count++], selector); #endif } } /* Clean up & return */ #ifdef HAVE_POPEN if (exe) pclose(fp); else #endif fclose(fp); return QUIT; }