Exemple #1
0
static void
systray(void *arg)
{
	WNDCLASS	cls;
	HWND		hWnd;
	MSG		msg;

	(void) memset(&cls, 0, sizeof(cls));

	cls.lpfnWndProc = (WNDPROC) WindowProc; 
	cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	cls.lpszClassName = "shttpd v." VERSION; 

	if (!RegisterClass(&cls)) 
		_shttpd_elog(E_FATAL, NULL, "RegisterClass: %d", ERRNO);
	else if ((hWnd = CreateWindow(cls.lpszClassName, "",
	    WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, arg)) == NULL)
		_shttpd_elog(E_FATAL, NULL, "CreateWindow: %d", ERRNO);
	ShowWindow(hWnd, SW_HIDE);
	
	ni.cbSize = sizeof(ni);
	ni.uID = ID_TRAYICON;
	ni.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
	ni.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	ni.hWnd = hWnd;
	_shttpd_snprintf(ni.szTip, sizeof(ni.szTip), "SHTTPD web server");
	ni.uCallbackMessage = WM_USER;
	Shell_NotifyIcon(NIM_ADD, &ni);

	while (GetMessage(&msg, hWnd, 0, 0)) { 
		TranslateMessage(&msg); 
		DispatchMessage(&msg); 
	}
}
Exemple #2
0
int
_shttpd_spawn_process(struct conn *c, const char *prog, char *envblk,
		char *envp[], int sock, const char *dir)
{
	int		ret;
	pid_t		pid;
	const char	*p, *interp = c->ctx->options[OPT_CGI_INTERPRETER];

	envblk = NULL;	/* unused */

	if ((pid = vfork()) == -1) {

		ret = -1;
		_shttpd_elog(E_LOG, c, "redirect: fork: %s", strerror(errno));

	} else if (pid == 0) {

		/* Child */

		(void) chdir(dir);
		(void) dup2(sock, 0);
		(void) dup2(sock, 1);
		(void) closesocket(sock);

		/* If error file is specified, send errors there */
		if (c->ctx->error_log)
			(void) dup2(fileno(c->ctx->error_log), 2);

		if ((p = strrchr(prog, '/')) != NULL)
			p++;
		else
			p = prog;

		/* Execute CGI program */
		if (interp == NULL) {
			(void) execle(p, p, NULL, envp);
			_shttpd_elog(E_FATAL, c, "redirect: exec(%s)", prog);
		} else {
			(void) execle(interp, interp, p, NULL, envp);
			_shttpd_elog(E_FATAL, c, "redirect: exec(%s %s)",
			    interp, prog);
		}

		/* UNREACHED */
		exit(EXIT_FAILURE);

	} else {

		/* Parent */
		ret = 0;
		(void) closesocket(sock);
	}

	return (ret);
}
Exemple #3
0
static void WINAPI
ServiceMain(int argc, char *argv[]) 
{
	char	path[MAX_PATH], *p, *av[] = {"shttpd_service", path, NULL};
	struct shttpd_ctx	*ctx;

	ss.dwServiceType      = SERVICE_WIN32; 
	ss.dwCurrentState     = SERVICE_RUNNING; 
	ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;

	hStatus = RegisterServiceCtrlHandler(SERVICE_NAME, ControlHandler);
	SetServiceStatus(hStatus, &ss); 

	GetModuleFileName(NULL, path, sizeof(path));

	if ((p = strrchr(path, DIRSEP)) != NULL)
		*++p = '\0';

	strcat(path, CONFIG_FILE);	/* woo ! */

	ctx = shttpd_init(NELEMS(av) - 1, av);
	if ((ctx = shttpd_init(NELEMS(av) - 1, av)) == NULL)
		_shttpd_elog(E_FATAL, NULL, "Cannot initialize SHTTP context");

	while (ss.dwCurrentState == SERVICE_RUNNING)
		shttpd_poll(ctx, INT_MAX);
	shttpd_fini(ctx);

	ss.dwCurrentState  = SERVICE_STOPPED; 
	ss.dwWin32ExitCode = -1; 
	SetServiceStatus(hStatus, &ss); 
}
Exemple #4
0
int
_shttpd_set_nt_service(struct shttpd_ctx *ctx, const char *action)
{
	SC_HANDLE	hSCM, hService;
	char		path[FILENAME_MAX], key[128];
	HKEY		hKey;
	DWORD		dwData;


	if (!strcmp(action, "install")) {
		if ((hSCM = OpenSCManager(NULL, NULL,
		    SC_MANAGER_ALL_ACCESS)) == NULL)
			_shttpd_elog(E_FATAL, NULL, "Error opening SCM (%d)", ERRNO);

		GetModuleFileName(NULL, path, sizeof(path));

		hService = CreateService(hSCM, SERVICE_NAME, SERVICE_NAME,
		    SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
		    SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, path,
		    NULL, NULL, NULL, NULL, NULL);

		if (!hService)
			_shttpd_elog(E_FATAL, NULL,
			    "Error installing service (%d)", ERRNO);

		ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION,
		    &service_descr);
		_shttpd_elog(E_FATAL, NULL, "Service successfully installed");


	} else if (!strcmp(action, "uninstall")) {

		if ((hSCM = OpenSCManager(NULL, NULL,
		    SC_MANAGER_ALL_ACCESS)) == NULL) {
			_shttpd_elog(E_FATAL, NULL, "Error opening SCM (%d)", ERRNO);
		} else if ((hService = OpenService(hSCM,
		    SERVICE_NAME, DELETE)) == NULL) {
			_shttpd_elog(E_FATAL, NULL,
			    "Error opening service (%d)", ERRNO);
		} else if (!DeleteService(hService)) {
			_shttpd_elog(E_FATAL, NULL,
			    "Error deleting service (%d)", ERRNO);
		} else {
			_shttpd_elog(E_FATAL, NULL, "Service deleted");
		}

	} else {
		_shttpd_elog(E_FATAL, NULL, "Use -service <install|uninstall>");
	}

	/* NOTREACHED */
	return (TRUE);
}
Exemple #5
0
int
main(int argc, char *argv[])
{
	struct shttpd_ctx	*ctx;

#if !defined(NO_AUTH)
	if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'A') {
		if (argc != 6)
			_shttpd_usage(argv[0]);
		exit(_shttpd_edit_passwords(argv[2],argv[3],argv[4],argv[5]));
	}
#endif /* NO_AUTH */

	if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")))
		_shttpd_usage(argv[0]);

#if defined(_WIN32)
	try_to_run_as_nt_service();
#endif /* _WIN32 */

#ifndef _WIN32
	(void) signal(SIGCHLD, signal_handler);
	(void) signal(SIGPIPE, SIG_IGN);
#endif /* _WIN32 */

	(void) signal(SIGTERM, signal_handler);
	(void) signal(SIGINT, signal_handler);

	if ((ctx = shttpd_init(argc, argv)) == NULL)
		_shttpd_elog(E_FATAL, NULL, "%s",
		    "Cannot initialize SHTTPD context");

	_shttpd_elog(E_LOG, NULL, "shttpd %s started on port(s) %s, serving %s",
	    VERSION, ctx->options[OPT_PORTS], ctx->options[OPT_ROOT]);

	while (exit_flag == 0)
		shttpd_poll(ctx, 10 * 1000);

	_shttpd_elog(E_LOG, NULL, "Exit on signal %d", exit_flag);
	shttpd_fini(ctx);

	return (EXIT_SUCCESS);
}
Exemple #6
0
static int
read_cgi(struct stream *stream, void *buf, size_t len)
{
	struct headers	parsed;
	char		status[4];
	int		n;

	assert(stream->chan.sock != -1);
	assert(stream->flags & FLAG_R);

	stream->flags &= ~FLAG_DONT_CLOSE;

	n = recv(stream->chan.sock, buf, len, 0);

	if (stream->flags & FLAG_HEADERS_PARSED)
		return (n);

	if (n <= 0 && ERRNO != EWOULDBLOCK) {
		_shttpd_send_server_error(stream->conn, 500,
		    "Error running CGI");
		return (n);
	}

	/*
	 * CGI script may output Status: and Location: headers, which
	 * may alter the status code. Buffer in headers, parse
	 * them, send correct status code and then forward all data
	 * from CGI script back to the remote end.
	 * Reply line was alredy appended to the IO buffer in
	 * decide_what_to_do(), with blank status code.
	 */

	stream->flags |= FLAG_DONT_CLOSE;
	io_inc_head(&stream->io, n);

	stream->headers_len = _shttpd_get_headers_len(stream->io.buf,
	    stream->io.head);
	if (stream->headers_len < 0) {
		stream->flags &= ~FLAG_DONT_CLOSE;
		_shttpd_send_server_error(stream->conn, 500,
		    "Bad headers sent");
		_shttpd_elog(E_LOG, stream->conn,
		    "CGI script sent invalid headers: "
		    "[%.*s]", stream->io.head - CGI_REPLY_LEN,
		    stream->io.buf + CGI_REPLY_LEN);
		return (0);
	}

	/*
	 * If we did not received full headers yet, we must not send any
	 * data read from the CGI back to the client. Suspend sending by
	 * setting tail = head, which tells that there is no data in IO buffer
	 */

	if (stream->headers_len == 0) {
		stream->io.tail = stream->io.head;
		return (0);
	}

	/* Received all headers. Set status code for the connection. */
	(void) memset(&parsed, 0, sizeof(parsed));
	_shttpd_parse_headers(stream->io.buf, stream->headers_len, &parsed);
	stream->content_len = parsed.cl.v_big_int;
	stream->conn->status = (int) parsed.status.v_big_int;

	/* If script outputs 'Location:' header, set status code to 302 */
	if (parsed.location.v_vec.len > 0)
		stream->conn->status = 302;

	/*
	 * If script did not output neither 'Location:' nor 'Status' headers,
	 * set the default status code 200, which means 'success'.
	 */
	if (stream->conn->status == 0)
		stream->conn->status = 200;

	/* Append the status line to the beginning of the output */
	(void) _shttpd_snprintf(status,
	    sizeof(status), "%3d", stream->conn->status);
	(void) memcpy(stream->io.buf + 9, status, 3);
	DBG(("read_cgi: content len %lu status %s",
	    stream->content_len, status));

	/* Next time, pass output directly back to the client */
	assert((big_int_t) stream->headers_len <= stream->io.total);
	stream->io.total -= stream->headers_len;
	stream->io.tail = 0;
	stream->flags |= FLAG_HEADERS_PARSED;

	/* Return 0 because we've already shifted the head */
	return (0);
}
Exemple #7
0
int
_shttpd_spawn_process(struct conn *c, const char *prog, char *envblk,
		char *envp[], int sock, const char *dir)
{
	HANDLE	a[2], b[2], h[2], me;
	DWORD	flags;
	char	*p, *interp, cmdline[FILENAME_MAX], line[FILENAME_MAX];
	FILE	*fp;
	STARTUPINFOA		si;
	PROCESS_INFORMATION	pi;

	me = GetCurrentProcess();
	flags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS;

	/* FIXME add error checking code here */
	CreatePipe(&a[0], &a[1], NULL, 0);
	CreatePipe(&b[0], &b[1], NULL, 0);
	DuplicateHandle(me, a[0], me, &h[0], 0, TRUE, flags);
	DuplicateHandle(me, b[1], me, &h[1], 0, TRUE, flags);
	
	(void) memset(&si, 0, sizeof(si));
	(void) memset(&pi, 0, sizeof(pi));

	/* XXX redirect CGI errors to the error log file */
	si.cb		= sizeof(si);
	si.dwFlags	= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
	si.wShowWindow	= SW_HIDE;
	si.hStdOutput	= h[1];
	si.hStdInput	= h[0];

	/* If CGI file is a script, try to read the interpreter line */
	interp = c->ctx->options[OPT_CGI_INTERPRETER];
	if (interp == NULL) {
		if ((fp = fopen(prog, "r")) != NULL) {
			(void) fgets(line, sizeof(line), fp);
			if (memcmp(line, "#!", 2) != 0)
				line[2] = '\0';
			/* Trim whitespaces from interpreter name */
			for (p = &line[strlen(line) - 1]; p > line &&
			    isspace(*p); p--)
				*p = '\0';
			(void) fclose(fp);
		}
		interp = line + 2;
		(void) _shttpd_snprintf(cmdline, sizeof(cmdline), "%s%s%s",
		    line + 2, line[2] == '\0' ? "" : " ", prog);
	}

	if ((p = strrchr(prog, '/')) != NULL)
		prog = p + 1;

	(void) _shttpd_snprintf(cmdline, sizeof(cmdline), "%s %s", interp, prog);

	(void) _shttpd_snprintf(line, sizeof(line), "%s", dir);
	fix_directory_separators(line);
	fix_directory_separators(cmdline);

	/*
	 * Spawn reader & writer threads before we create CGI process.
	 * Otherwise CGI process may die too quickly, loosing the data
	 */
	spawn_stdio_thread(sock, b[0], stdinput, 0);
	spawn_stdio_thread(sock, a[1], stdoutput, c->rem.content_len);

	if (CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
	    CREATE_NEW_PROCESS_GROUP, envblk, line, &si, &pi) == 0) {
		_shttpd_elog(E_LOG, c,
		    "redirect: CreateProcess(%s): %d", cmdline, ERRNO);
		return (-1);
	} else {
		CloseHandle(h[0]);
		CloseHandle(h[1]);
		CloseHandle(pi.hThread);
		CloseHandle(pi.hProcess);
	}

	return (0);
}