Пример #1
0
/*
 * 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);
	}
}
Пример #2
0
/*
 * 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;
}