コード例 #1
0
ファイル: file.c プロジェクト: unisx/gophernicus
/*
 * Print hURL redirect page
 */
void url_redirect(state *st)
{
	char dest[BUFSIZE];
	char *c;

	/* Basic security checking */
	sstrlcpy(dest, st->req_selector + 4);

	if (sstrncmp(dest, "http://") != MATCH &&
	    sstrncmp(dest, "ftp://") != MATCH &&
	    sstrncmp(dest, "mailto:") != MATCH)
		die(st, ERR_ACCESS, "Refusing to HTTP redirect unsafe protocols");

	if ((c = strchr(dest, '"'))) *c = '\0';
	if ((c = strchr(dest, '?'))) *c = '\0';

	/* Log the redirect */
	if (st->opt_syslog) {
		syslog(LOG_INFO, "request for \"gopher://%s:%i/h%s\" from %s",
			st->server_host,
			st->server_port,
			st->req_selector,
			st->req_remote_addr);
	}
	log_combined(st, HTTP_OK);

	/* Output HTML */
	printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"
		"<HTML>\n<HEAD>\n"
		"  <META HTTP-EQUIV=\"Refresh\" content=\"1;URL=%1$s\">\n"
		"  <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;charset=iso-8859-1\">\n"
		"  <TITLE>URL Redirect page</TITLE>\n"
		"</HEAD>\n<BODY>\n"
		"<STRONG>Redirecting to <A HREF=\"%1$s\">%1$s</A></STRONG>\n"
		"<PRE>\n", dest);
	footer(st);
	printf("</PRE>\n</BODY>\n</HTML>\n");
}
コード例 #2
0
ファイル: ex5-5.c プロジェクト: m-varadhan/CUnixProgramming
main()
{
	char s[100],t[100];
	int n,k;
	
	printf("Enter Two Strings : ");
	scanf("%s%s",s,t);
	printf("Enter Value for n : ");
	scanf("%d",&n);
	k=sstrncmp(s,t,n);
	if(k==0)
		printf("\nThe strings are equal\n");
	else
		printf("\nThe strings are not equal\n");
//	sstrncpy(s,t,n);
//	printf("\nThe Copied String from %s to %s\n",t,s);
//	sstrncat(s,t,n);
//	printf("\nThe concatenated strings %s\n",s);
}	
コード例 #3
0
ファイル: gophernicus.c プロジェクト: unisx/gophernicus
/*
 * Get remote peer IP address
 */
char *get_peer_address(void)
{
#ifdef HAVE_IPv4
	struct sockaddr_in addr;
	socklen_t addrsize = sizeof(addr);
#endif
#ifdef HAVE_IPv6
	struct sockaddr_in6 addr6;
	socklen_t addr6size = sizeof(addr6);
	static char address[INET6_ADDRSTRLEN];
#endif
	char *c;

	/* Are we a CGI script? */
	if ((c = getenv("REMOTE_ADDR"))) return c;
	/* if ((c = getenv("REMOTE_HOST"))) return c; */

	/* Try IPv4 first */
#ifdef HAVE_IPv4
	if (getpeername(0, (struct sockaddr *) &addr, &addrsize) == OK) {
		c = inet_ntoa(addr.sin_addr);
		if (strlen(c) > 0 && *c != '0') return c;
	}
#endif

	/* IPv4 didn't work - try IPv6 */
#ifdef HAVE_IPv6
	if (getpeername(0, (struct sockaddr *) &addr6, &addr6size) == OK) {
		if (inet_ntop(AF_INET6, &addr6.sin6_addr, address, sizeof(address))) {

			/* Strip ::ffff: IPv4-in-IPv6 prefix */
			if (sstrncmp(address, "::ffff:") == MATCH) return (address + 7);
			else return address;
		}
	}
#endif

	/* Nothing works... I'm out of ideas */
	return DEFAULT_ADDR;
}
コード例 #4
0
ファイル: styfile.c プロジェクト: clerkma/texlive-mobile
/*   compare strings   */
static int scompare(char *buff1, const char *buff2)
{
	int i;

	if (sstrlen(buff1) == sstrlen(buff2)) {
		if (sstrcmp(buff1,buff2) == 0) {
			if (fgets(buff1,4095,fp)==NULL) return -1;
			return 0;
		}
		return -1;
	}
	for (i=0;i<sstrlen(buff1)-sstrlen(buff2);i++) {
		if (buff1[i]==' ' || buff1[i]=='\t') {
			continue;
		}
		else if ((sstrncmp(&buff1[i],buff2,sstrlen(buff2))==0)
			&&((buff1[i+strlen(buff2)]==' ')||(buff1[i+strlen(buff2)]=='\t')||(buff1[i+strlen(buff2)]=='\n'))) {
			return i+strlen(buff2);
		}
		else return -1;
	}
	return -1;
}
コード例 #5
0
ファイル: gophernicus.c プロジェクト: unisx/gophernicus
/*
 * Main
 */
int main(int argc, char *argv[])
{
	struct stat file;
	state st;
	char self[64];
	char selector[BUFSIZE];
	char buf[BUFSIZE];
	char *dest;
	char *c;
#ifdef HAVE_SHMEM
	struct shmid_ds shm_ds;
	shm_state *shm;
	int shmid;
#endif

	/* Get the name of this binary */
	if ((c = strrchr(argv[0], '/'))) sstrlcpy(self, c + 1);
	else sstrlcpy(self, argv[0]);

	/* Initialize state */
#ifdef HAVE_LOCALES
	setlocale(LC_TIME, DATE_LOCALE);
#endif
	init_state(&st);
	srand(time(NULL) / (getpid() + getppid()));

	/* Handle command line arguments */
	parse_args(&st, argc, argv);

	/* Open syslog() */
	if (st.opt_syslog) openlog(self, LOG_PID, LOG_DAEMON);

	/* Make sure the computer is turned on */
#ifdef __HAIKU__
	if (is_computer_on() != TRUE)
		die(&st, ERR_ACCESS, "Please turn on the computer first");
#endif

	/* Refuse to run as root */
#ifdef HAVE_PASSWD
	if (st.opt_root && getuid() == 0)
		die(&st, ERR_ACCESS, "Refusing to run as root");
#endif

	/* Try to get shared memory */
#ifdef HAVE_SHMEM
	if ((shmid = shmget(SHM_KEY, sizeof(shm_state), IPC_CREAT | SHM_MODE)) == ERROR) {

		/* Getting memory failed -> delete the old allocation */
		shmctl(shmid, IPC_RMID, &shm_ds);
		shm = NULL;
	}
	else {
		/* Map shared memory */
		if ((shm = (shm_state *) shmat(shmid, (void *) 0, 0)) == (void *) ERROR)
			shm = NULL;

		/* Initialize mapped shared memory */
		if (shm && shm->start_time == 0) {
			shm->start_time = time(NULL);

			/* Keep server platform & description in shm */
			platform(&st);
			sstrlcpy(shm->server_platform, st.server_platform);
			sstrlcpy(shm->server_description, st.server_description);
		}
	}

	/* For debugging shared memory issues */
	if (!st.opt_shm) shm = NULL;

	/* Get server platform and description */
	if (shm) {
		sstrlcpy(st.server_platform, shm->server_platform);

		if (!*st.server_description)
			sstrlcpy(st.server_description, shm->server_description);
	}
	else
#endif
		platform(&st);

	/* Read selector */
	if (fgets(selector, sizeof(selector) - 1, stdin) == NULL)
		selector[0] = '\0';

	/* Remove trailing CRLF */
	chomp(selector);

	if (st.debug) syslog(LOG_INFO, "client sent us \"%s\"", selector);

	/* Handle hURL: redirect page */
	if (sstrncmp(selector, "URL:") == MATCH) {
		st.req_filetype = TYPE_HTML;
		sstrlcpy(st.req_selector, selector);
		url_redirect(&st);
		return OK;
	}

	/* Handle gopher+ root requests (UMN gopher client is seriously borken) */
	if (sstrncmp(selector, "\t$") == MATCH) {
		printf("+-1" CRLF);
		printf("+INFO: 1Main menu\t\t%s\t%i" CRLF,
			st.server_host,
			st.server_port);
		printf("+VIEWS:" CRLF " application/gopher+-menu: <512b>" CRLF);
		printf("." CRLF);

		if (st.debug) syslog(LOG_INFO, "got a request for gopher+ root menu");
		return OK;
	}

	/* Convert HTTP request to gopher (respond using headerless HTTP/0.9) */
	if (sstrncmp(selector, "GET ") == MATCH ||
	    sstrncmp(selector, "POST ") == MATCH ) {

		if ((c = strchr(selector, ' '))) sstrlcpy(selector, c + 1);
		if ((c = strchr(selector, ' '))) *c = '\0';

		st.req_protocol = PROTO_HTTP;

		if (st.debug) syslog(LOG_INFO, "got HTTP request for \"%s\"", selector);
	}

	/* Save default server_host & fetch session data (including new server_host) */
	sstrlcpy(st.server_host_default, st.server_host);
#ifdef HAVE_SHMEM
	if (shm) get_shm_session(&st, shm);
#endif

	/* Loop through the selector, fix it & separate query_string */
	dest = st.req_selector;
	if (selector[0] != '/') *dest++ = '/';

	for (c = selector; *c;) {

		/* Skip duplicate slashes and /./ */
		while (*c == '/' && *(c + 1) == '/') c++;
		if (*c == '/' && *(c + 1) == '.' && *(c + 2) == '/') c += 2;

		/* Start of a query string (either type 7 or HTTP-style)? */
		if (*c == '\t' || (st.opt_query && *c == '?')) {
			sstrlcpy(st.req_query_string, c + 1);
			if ((c = strchr(st.req_query_string, '\t'))) *c = '\0';
			break;
		}

		/* Start of virtual host hint? */
		if (*c == ';') {
			if (st.opt_vhost) sstrlcpy(st.server_host, c + 1);

			/* Skip vhost on selector */
			while (*c && *c != '\t') c++;
			continue;
		}

		/* Copy valid char */
		*dest++ = *c++;
	}
	*dest = '\0';

	/* Remove encodings from selector */
	strndecode(st.req_selector, st.req_selector, sizeof(st.req_selector));

	/* Deny requests for Slashdot and /../ hackers */
	if (strstr(st.req_selector, "/."))
		die(&st, ERR_ACCESS, "Refusing to serve out dotfiles");

	/* Handle /server-status requests */
#ifdef HAVE_SHMEM
	if (sstrncmp(st.req_selector, SERVER_STATUS) == MATCH) {
		if (shm) server_status(&st, shm, shmid);
		return OK;
	}
#endif

	/* Remove possible extra cruft from server_host */
	if ((c = strchr(st.server_host, '\t'))) *c = '\0';

	/* Guess request filetype so we can die() with style... */
	st.req_filetype = gopher_filetype(&st, st.req_selector, FALSE);

	/* Convert seletor to path & stat() */
	selector_to_path(&st);
	if (st.debug) syslog(LOG_INFO, "path to resource is \"%s\"", st.req_realpath);

	if (stat(st.req_realpath, &file) == ERROR) {

		/* Handle virtual /caps.txt requests */
		if (st.opt_caps && sstrncmp(st.req_selector, CAPS_TXT) == MATCH) {
#ifdef HAVE_SHMEM
			caps_txt(&st, shm);
#else
			caps_txt(&st, NULL);
#endif
			return OK;
		}

		/* Requested file not found - die() */
		die(&st, ERR_NOTFOUND, NULL);
	}

	/* Fetch request filesize from stat() */
	st.req_filesize = file.st_size;

	/* Everyone must have read access but no write access */
	if ((file.st_mode & S_IROTH) == 0)
		die(&st, ERR_ACCESS, "File or directory not world-readable");
	if ((file.st_mode & S_IWOTH) != 0)
		die(&st, ERR_ACCESS, "File or directory world-writeable");

	/* If stat said it was a dir then it's a menu */
	if ((file.st_mode & S_IFMT) == S_IFDIR) st.req_filetype = TYPE_MENU;

	/* Not a dir - let's guess the filetype again... */
	else if ((file.st_mode & S_IFMT) == S_IFREG)
		st.req_filetype = gopher_filetype(&st, st.req_realpath, st.opt_magic);

	/* Menu selectors must end with a slash */
	if (st.req_filetype == TYPE_MENU && strlast(st.req_selector) != '/')
		sstrlcat(st.req_selector, "/");

	/* Change directory to wherever the resource was */
	sstrlcpy(buf, st.req_realpath);

	if ((file.st_mode & S_IFMT) != S_IFDIR) c = dirname(buf);
	else c = buf;

	if (chdir(c) == ERROR) die(&st, ERR_ACCESS, NULL);

	/* Keep count of hits and data transfer */
#ifdef HAVE_SHMEM
	if (shm) {
		shm->hits++;
		shm->kbytes += st.req_filesize / 1024;

		/* Update user session */
		update_shm_session(&st, shm);
	}
#endif

	/* Log the request */
	if (st.opt_syslog) {
		syslog(LOG_INFO, "request for \"gopher://%s:%i/%c%s\" from %s",
			st.server_host,
			st.server_port,
			st.req_filetype,
			st.req_selector,
			st.req_remote_addr);
	}

	/* Check file type & act accordingly */
	switch (file.st_mode & S_IFMT) {
		case S_IFDIR:
			log_combined(&st, HTTP_OK);
			gopher_menu(&st);
			break;

		case S_IFREG:
			log_combined(&st, HTTP_OK);
			gopher_file(&st);
			break;

		default:
			die(&st, ERR_ACCESS, "Refusing to serve out special files");
	}

	/* Clean exit */
	return OK;
}
コード例 #6
0
ファイル: gophernicus.c プロジェクト: unisx/gophernicus
/*
 * Convert gopher selector to an absolute path
 */
void selector_to_path(state *st)
{
	DIR *dp;
	struct dirent *dir;
	struct stat file;
#ifdef HAVE_PASSWD
	struct passwd *pwd;
	char *path = EMPTY;
	char *c;
#endif
	char buf[BUFSIZE];
	int i;

	/* Handle selector rewriting */
	for (i = 0; i < st->rewrite_count; i++) {

		/* Match found? */
		if (strstr(st->req_selector, st->rewrite[i].match) == st->req_selector) {

			/* Replace match with a new string */
			snprintf(buf, sizeof(buf), "%s%s",
				st->rewrite[i].replace,
				st->req_selector + strlen(st->rewrite[i].match));

			if (st->debug) {
				syslog(LOG_INFO, "rewriting selector \"%s\" -> \"%s\"",
					st->req_selector, buf);
			}

			sstrlcpy(st->req_selector, buf);
		}
	}

#ifdef HAVE_PASSWD
	/* Virtual userdir (~user -> /home/user/public_gopher)? */
	if (*(st->user_dir) && sstrncmp(st->req_selector, "/~") == MATCH) {

		/* Parse userdir login name & path */;
		sstrlcpy(buf, st->req_selector + 2);
		if ((c = strchr(buf, '/'))) {
			*c = '\0';
			path = c + 1;
		}

		/* Check user validity */
		if ((pwd = getpwnam(buf)) == NULL)
			die(st, ERR_NOTFOUND, "User not found");
		if (pwd->pw_uid < PASSWD_MIN_UID)
			die(st, ERR_NOTFOUND, "User found but UID too low");

		/* Generate absolute path to users own gopher root */
		snprintf(st->req_realpath, sizeof(st->req_realpath),
			"%s/%s/%s", pwd->pw_dir, st->user_dir, path);

		/* Check ~public_gopher access rights */
		if (stat(st->req_realpath, &file) == ERROR)
			die(st, ERR_NOTFOUND, NULL);
		if ((file.st_mode & S_IROTH) == 0)
			die(st, ERR_ACCESS, "~/public_gopher not world-readable");
		if (file.st_uid != pwd->pw_uid)
			die(st, ERR_ACCESS, "~/ and ~/public_gopher owned by different users");

		/* Userdirs always come from the default vhost */
		if (st->opt_vhost)
			sstrlcpy(st->server_host, st->server_host_default);
		return;
	}
#endif

	/* Virtual hosting */
	if (st->opt_vhost) {

		/* Try looking for the selector from the current vhost */
		snprintf(st->req_realpath, sizeof(st->req_realpath), "%s/%s%s",
			st->server_root, st->server_host, st->req_selector);
		if (stat(st->req_realpath, &file) == OK) return;

		/* Loop through all vhosts looking for the selector */
		if ((dp = opendir(st->server_root)) == NULL) die(st, ERR_NOTFOUND, NULL);
		while ((dir = readdir(dp))) {

			/* Skip .hidden dirs and . & .. */
			if (dir->d_name[0] == '.') continue;

			/* Special case - skip lost+found (don't ask) */
			if (sstrncmp(dir->d_name, "lost+found") == MATCH) continue;

			/* Generate path to the found vhost */
			snprintf(st->req_realpath, sizeof(st->req_realpath), "%s/%s%s",
				st->server_root, dir->d_name, st->req_selector);

			/* Did we find the selector under this vhost? */
			if (stat(st->req_realpath, &file) == OK) {

				/* Virtual host found - update state & return */
				sstrlcpy(st->server_host, dir->d_name);
				return;
			}
		}
		closedir(dp);
	}

	/* Handle normal selectors */
	snprintf(st->req_realpath, sizeof(st->req_realpath),
		"%s%s", st->server_root, st->req_selector);
}
コード例 #7
0
ファイル: menu.c プロジェクト: unisx/gophernicus
/*
 * 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;
}
コード例 #8
0
ファイル: menu.c プロジェクト: unisx/gophernicus
/*
 * Return gopher filetype for a file
 */
char gopher_filetype(state *st, char *file, char magic)
{
	FILE *fp;
	char buf[BUFSIZE];
	char *c;
	int i;

	/* If it ends with an slash it's a menu */
	if (!*file) return st->default_filetype;
	if (strlast(file) == '/') return TYPE_MENU;

	/* Get file suffix */
	if ((c = strrchr(file, '.'))) {
		c++;

		/* Loop through the filetype array looking for a match*/
		for (i = 0; i < st->filetype_count; i++)
			if (strcasecmp(st->filetype[i].suffix, c) == MATCH)
				return st->filetype[i].type;
	}

	/* Are we allowed to look inside files? */
	if (!magic) return st->default_filetype;

	/* Read data from the file */
	if ((fp = fopen(file , "r")) == NULL) return st->default_filetype;
	i = fread(buf, 1, sizeof(buf) - 1, fp);
	buf[i] = '\0';
	fclose(fp);

	/* GIF images */
	if (sstrncmp(buf, "GIF89a") == MATCH || 
	    sstrncmp(buf, "GIF87a") == MATCH) return TYPE_GIF;

	/* JPEG images */
	if (sstrncmp(buf, "\377\330\377\340") == MATCH) return TYPE_IMAGE;

	/* PNG images */
	if (sstrncmp(buf, "\211PNG") == MATCH) return TYPE_IMAGE;

	/* mbox */
	if (strstr(buf, "\nFrom: ") &&
	    strstr(buf, "\nSubject: ")) return TYPE_MIME;

	/* MIME */
	if (strstr(buf, "\nContent-Type: ")) return TYPE_MIME;

	/* HTML files */
	if (buf[0] == '<' &&
	    (strstr(buf, "<html") ||
	     strstr(buf, "<HTML"))) return TYPE_HTML;

	/* PDF and PostScript */
	if (sstrncmp(buf, "%PDF-") == MATCH ||
	    sstrncmp(buf, "%!") == MATCH) return TYPE_DOC;

	/* compress and gzip */
	if (sstrncmp(buf, "\037\235\220") == MATCH ||
	    sstrncmp(buf, "\037\213\010") == MATCH) return TYPE_GZIP;

	/* Unknown content - binary or text? */
	if (memchr(buf, '\0', i)) return TYPE_BINARY;
	return st->default_filetype;
}