Exemple #1
0
p_link
newlink()
{	register link *rval;

	if (Lcache) {
	 	rval = Lcache;
		Lcache = Lcache->l_next;
		strclear((char *) rval, sizeof(link));
	} else if ((rval = (link * ) calloc(1, sizeof(link))) == 0)
		nomem();
	return rval;
}
Exemple #2
0
/*
 * Print gopher menu line
 */
void info(state *st, char *str, char type)
{
	char buf[BUFSIZE];
	char selector[16];

	/* Convert string to output charset */
	if (st->opt_iconv) sstrniconv(st->out_charset, buf, str);
	else sstrlcpy(buf, str);

	/* Handle gopher title resources */
	strclear(selector);
	if (type == TYPE_TITLE) {
		sstrlcpy(selector, "TITLE");
		type = TYPE_INFO;
	}

	/* Output info line */
	strcut(buf, st->out_width);
	printf("%c%s\t%s\t%s" CRLF,
		type, buf, selector, DUMMY_HOST);
}
Exemple #3
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);
	}
}
Exemple #4
0
/*
 * Get OS name, version & architecture we're running on
 */
void platform(state *st)
{
#ifdef HAVE_UNAME
#if defined(_AIX) || defined(__linux) || defined(__APPLE__)
	FILE *fp;
#endif
#if defined(__arm__) || defined(__mips__) || defined(__APPLE__)
	char buf[BUFSIZE];
#endif
#ifdef __linux
	struct stat file;
#endif
	struct utsname name;
	char sysname[64];
	char release[64];
	char machine[64];
	char *c;

	/* Fetch system information */
	uname(&name);

	strclear(sysname);
	strclear(release);
	strclear(machine);

	/* AIX-specific */
#ifdef _AIX

	/* Fix uname() results */
	sstrlcpy(machine, "powerpc");
	snprintf(release, sizeof(release), "%s.%s",
		name.version,
		name.release);

	/* Get CPU type */
	if ((fp = popen("/usr/sbin/getsystype -i", "r"))) {
		fgets(machine, sizeof(machine), fp);
		pclose(fp);

		strreplace(machine, ' ', '_');
	}

	/* Get hardware name using shell uname */
	if (!*st->server_description &&
	    (fp = popen("/usr/bin/uname -M", "r"))) {

		fgets(st->server_description,
			sizeof(st->server_description), fp);
		pclose(fp);

		strreplace(st->server_description, ',', ' ');
		chomp(st->server_description);
	}
#endif

	/* Mac OS X, just like Unix but totally different... */
#ifdef __APPLE__

	/* Hardcode OS name */
	sstrlcpy(sysname, "MacOSX");

	/* Get OS X version */
	if ((fp = popen("/usr/bin/sw_vers -productVersion", "r"))) {
		fgets(release, sizeof(release), fp);
		pclose(fp);
	}

	/* Get hardware name */
	if (!*st->server_description &&
	    (fp = popen("/usr/sbin/sysctl -n hw.model", "r"))) {

		/* Read hardware name */
		fgets(buf, sizeof(buf), fp);
		pclose(fp);

		/* Clones are gone now so we'll hardcode the manufacturer */
		sstrlcpy(st->server_description, "Apple ");
		sstrlcat(st->server_description, buf);

		/* Remove hardware revision */
		for (c = st->server_description; *c; c++)
			if (*c >= '0' && *c <= '9') { *c = '\0'; break; }
	}
#endif

	/* Linux uname() just says Linux/2.6 - let's dig deeper... */
#ifdef __linux

	/* Most Linux ARM/MIPS boards have hardware name in /proc/cpuinfo */
#if defined(__arm__) || defined(__mips__)
	if (!*st->server_description && (fp = fopen("/proc/cpuinfo" , "r"))) {

		while (fgets(buf, sizeof(buf), fp)) {
#ifdef __arm__
			if ((c = strkey(buf, "Hardware"))) {
#else
			if ((c = strkey(buf, "machine"))) {
#endif
				sstrlcpy(st->server_description, c);
				chomp(st->server_description);
				break;
			}
		}
		fclose(fp);
	}
#endif

	/* Identify RedHat */
	if (!*sysname && (fp = fopen("/etc/redhat-release", "r"))) {
		fgets(sysname, sizeof(sysname), fp);
		fclose(fp);

		if ((c = strstr(sysname, "release "))) sstrlcpy(release, c + 8);
		if ((c = strchr(release, ' '))) *c = '\0';

		if ((c = strchr(sysname, ' '))) *c = '\0';
		if (strcmp(sysname, "Red") == MATCH) sstrlcpy(sysname, "RedHat");
	}

	/* Identify Slackware */
	if (!*sysname && (fp = fopen("/etc/slackware-version", "r"))) {
		fgets(sysname, sizeof(sysname), fp);
		fclose(fp);

		if ((c = strchr(sysname, ' '))) {
			sstrlcpy(release, c + 1);
			*c = '\0';
		}
	}

	/* Uh-oh.... how about a standard Linux with lsb_release? */
	if (stat("/usr/bin/lsb_release", &file) == OK && (file.st_mode & S_IXOTH)) {

		if (!*sysname && (fp = popen("/usr/bin/lsb_release -i -s", "r"))) {
			fgets(sysname, sizeof(sysname), fp);
			pclose(fp);
		}

		if (!*release && (fp = popen("/usr/bin/lsb_release -r -s", "r"))) {
			fgets(release, sizeof(release), fp);
			pclose(fp);
		}
	}

	/* OK, nothing worked - let's try /etc/issue for sysname */
	if (!*sysname && (fp = fopen("/etc/issue", "r"))) {
		fgets(sysname, sizeof(sysname), fp);
		fclose(fp);

		if ((c = strchr(sysname, ' '))) *c = '\0';
		if ((c = strchr(sysname, '\\'))) *c = '\0';
	}

	/* Debian version should be in /etc/debian_version */
	if (!*release && (fp = fopen("/etc/debian_version", "r"))) {
		fgets (release, sizeof(release), fp);
		fclose(fp);

		if ((c = strchr(release, '/'))) *c = '\0';
	}
#endif

	/* Haiku OS */
#ifdef __HAIKU__

	/* Fix release name */
	snprintf(release, sizeof(release), "R%s", name.release);
#endif

	/* Fill in the blanks using uname() data */
	if (!*sysname) sstrlcpy(sysname, name.sysname);
	if (!*release) sstrlcpy(release, name.release);
	if (!*machine) sstrlcpy(machine, name.machine);

	/* I always liked weird Perl-only functions */
	chomp(sysname);
	chomp(release);
	chomp(machine);

	/* We're only interested in major.minor version */
	if ((c = strchr(release, '.'))) if ((c = strchr(c + 1, '.'))) *c = '\0';
	if ((c = strchr(release, '-'))) *c = '\0';
	if ((c = strchr(release, '/'))) *c = '\0';

	/* Create a nicely formatted platform string */
	snprintf(st->server_platform, sizeof(st->server_platform), "%s/%s %s",
	         sysname,
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
	         machine,
	         release);
#else
	         release,
	         machine);
#endif 

	/* Debug */
	if (st->debug) {
		syslog(LOG_INFO, "generated platform string \"%s\"",
			st->server_platform);
	}

#else
	/* Fallback reply */
	sstrlcpy(st->server_platform, "Unknown computer-like system");
#endif
}


/*
 * Return current CPU load
 */
float loadavg(void)
{
	FILE *fp;
	char buf[BUFSIZE];

	/* Faster Linux version */
#ifdef __linux
	buf[0] = '\0';
	if ((fp = fopen("/proc/loadavg" , "r")) == NULL) return 0;
	fgets(buf, sizeof(buf), fp);
	fclose(fp);

	return (float) atof(buf);

	/* Generic slow version - parse the output of uptime */
#else
#ifdef HAVE_POPEN
	char *c;

	if ((fp = popen("/usr/bin/uptime", "r"))) {
		fgets(buf, sizeof(buf), fp);
		pclose(fp);

		if ((c = strstr(buf, "average: ")) || (c = strstr(buf, "averages: ")))
			return (float) atof(c + 10);
	}
#endif

	/* Fallback reply */
	return 0;
#endif
}
Exemple #5
0
/*
 * Initialize state struct to default/empty values
 */
void init_state(state *st)
{
	static const char *filetypes[] = { FILETYPES };
	char buf[BUFSIZE];
	char *c;
	int i;

	/* Request */
	strclear(st->req_selector);
	strclear(st->req_realpath);
	strclear(st->req_query_string);
	strclear(st->req_referrer);
	sstrlcpy(st->req_local_addr, get_local_address());
	sstrlcpy(st->req_remote_addr, get_peer_address());
	/* strclear(st->req_remote_host); */
	st->req_filetype = DEFAULT_TYPE;
	st->req_protocol = PROTO_GOPHER;
	st->req_filesize = 0;

	/* Output */
	st->out_width = DEFAULT_WIDTH;
	st->out_charset = DEFAULT_CHARSET;

	/* Settings */
	sstrlcpy(st->server_root, DEFAULT_ROOT);
	sstrlcpy(st->server_host_default, DEFAULT_HOST);

	if ((c = getenv("HOSTNAME")))
		sstrlcpy(st->server_host, c);
	else if ((gethostname(buf, sizeof(buf))) != ERROR)
		sstrlcpy(st->server_host, buf);

	st->server_port = DEFAULT_PORT;

	st->default_filetype = DEFAULT_TYPE;
	sstrlcpy(st->map_file, DEFAULT_MAP);
	sstrlcpy(st->tag_file, DEFAULT_TAG);
	sstrlcpy(st->cgi_file, DEFAULT_CGI);
	sstrlcpy(st->user_dir, DEFAULT_USERDIR);
	strclear(st->log_file);

	st->hidden_count = 0;
	st->filetype_count = 0;
	strclear(st->filter_dir);
	st->rewrite_count = 0;

	strclear(st->server_description);
	strclear(st->server_location);
	strclear(st->server_platform);
	strclear(st->server_admin);

	/* Session */
	st->session_timeout = DEFAULT_SESSION_TIMEOUT;
	st->session_max_kbytes = DEFAULT_SESSION_MAX_KBYTES;
	st->session_max_hits = DEFAULT_SESSION_MAX_HITS;

	/* Feature options */
	st->opt_vhost = TRUE;
	st->opt_parent = TRUE;
	st->opt_header = TRUE;
	st->opt_footer = TRUE;
	st->opt_date = TRUE;
	st->opt_syslog = TRUE;
	st->opt_magic = TRUE;
	st->opt_iconv = TRUE;
	st->opt_query = TRUE;
	st->opt_caps = TRUE;
	st->opt_shm = TRUE;
	st->opt_root = TRUE;
	st->debug = FALSE;

	/* Load default suffix -> filetype mappings */
	for (i = 0; filetypes[i]; i += 2) {
		if (st->filetype_count < MAX_FILETYPES) {
			sstrlcpy(st->filetype[st->filetype_count].suffix, filetypes[i]);
			st->filetype[st->filetype_count].type = *filetypes[i + 1];
			st->filetype_count++;
		}
	}
}