version 0.2.0
[fms.git] / libs / shttpd / standalone.c
1 /*
2  * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
3  * All rights reserved
4  *
5  * "THE BEER-WARE LICENSE" (Revision 42):
6  * Sergey Lyubka wrote this file.  As long as you retain this notice you
7  * can do whatever you want with this stuff. If we meet some day, and you think
8  * this stuff is worth it, you can buy me a beer in return.
9  */
10
11 #include "defs.h"
12
13 static const char       *config_file = CONFIG;
14 static int              exit_flag;
15
16 static void
17 signal_handler(int sig_num)
18 {
19         switch (sig_num) {
20 #ifndef _WIN32
21         case SIGCHLD:
22                 while (waitpid(-1, &sig_num, WNOHANG) > 0) ;
23                 break;
24 #endif /* !_WIN32 */
25         default:
26                 exit_flag = sig_num;
27                 break;
28         }
29 }
30
31 int
32 main(int argc, char *argv[])
33 {
34         struct shttpd_ctx       *ctx;
35
36         current_time = time(NULL);
37         if (argc > 1 && argv[argc - 2][0] != '-' && argv[argc - 1][0] != '-')
38                 config_file = argv[argc - 1];
39
40 #if !defined(NO_AUTH)
41         if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'A') {
42                 if (argc != 6)
43                         usage(argv[0]);
44                 exit(edit_passwords(argv[2],argv[3],argv[4],argv[5]));
45         }
46 #endif /* NO_AUTH */
47
48         ctx = init_from_argc_argv(config_file, argc, argv);
49
50 #ifndef _WIN32
51         /* Switch to alternate UID, it is safe now, after shttpd_listen() */
52         if (ctx->uid != NULL) {
53                 struct passwd   *pw;
54
55                 if ((pw = getpwnam(ctx->uid)) == NULL)
56                         elog(E_FATAL, 0, "main: unknown user [%s]", ctx->uid);
57                 else if (setgid(pw->pw_gid) == -1)
58                         elog(E_FATAL, NULL, "main: setgid(%s): %s",
59                             ctx->uid, strerror(errno));
60                 else if (setuid(pw->pw_uid) == -1)
61                         elog(E_FATAL, NULL, "main: setuid(%s): %s",
62                             ctx->uid, strerror(errno));
63         }
64         (void) signal(SIGCHLD, signal_handler);
65         (void) signal(SIGPIPE, SIG_IGN);
66 #endif /* _WIN32 */
67
68         (void) signal(SIGTERM, signal_handler);
69         (void) signal(SIGINT, signal_handler);
70
71         if (ctx->inetd_mode) {
72                 (void) freopen("/dev/null", "a", stderr);
73                 shttpd_add_socket(ctx, fileno(stdin));
74         } else {
75                 open_listening_ports(ctx);
76         }
77
78         elog(E_LOG, NULL, "shttpd %s started on port(s) %s, serving %s",
79             VERSION, ctx->ports, ctx->document_root);
80
81         while (exit_flag == 0)
82                 shttpd_poll(ctx, 5000);
83
84         elog(E_LOG, NULL, "%d requests %.2lf Mb in %.2lf Mb out. "
85             "Exit on signal %d", ctx->nrequests, (double) (ctx->in / 1048576),
86             (double) ctx->out / 1048576, exit_flag);
87
88         shttpd_fini(ctx);
89
90         return (EXIT_SUCCESS);
91 }