Initial import
[umurmur.git] / src / main.c
1 /* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
3
4    All rights reserved.
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9
10    - Redistributions of source code must retain the above copyright notice,
11      this list of conditions and the following disclaimer.
12    - Redistributions in binary form must reproduce the above copyright notice,
13      this list of conditions and the following disclaimer in the documentation
14      and/or other materials provided with the distribution.
15    - Neither the name of the Developers nor the names of its contributors may
16      be used to endorse or promote products derived from this software without
17      specific prior written permission.
18
19    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <signal.h>
39 #include <sched.h>
40 #include <errno.h>
41
42 #include "server.h"
43 #include "ssl.h"
44 #include "channel.h"
45 #include "log.h"
46 #include "client.h"
47 #include "conf.h"
48
49 #define UMURMUR_VERSION "0.1.0"
50
51 void lockfile(const char *pidfile)
52 {
53         int lfp;
54         char str[16];
55         
56         lfp = open(pidfile, O_RDWR|O_CREAT, 0640);
57         
58         if (lfp < 0)
59                 Log_fatal("Cannot open PID-file %s for writing", pidfile);
60         sprintf(str,"%d\n",getpid());
61         write(lfp, str, strlen(str)); /* record pid to lockfile */
62         Log_info("PID-file: %s", pidfile);
63 }
64
65
66 void signal_handler(int sig)
67 {
68         switch(sig) {
69         case SIGHUP:
70                 /* XXX - do stuff? */
71                 Log_info("HUP signal");
72                 break;
73         case SIGTERM:
74                 Log_info("TERM signal. Shutting down.");
75                 Server_shutdown();
76                 break;
77         }
78 }
79
80 void daemonize()
81 {
82         int i;
83         
84         if (getppid() == 1)
85                 return; /* already a daemon */
86         i = fork();
87         if ( i < 0) {
88                 fprintf(stderr, "Fork error. Exiting\n");
89                 exit(1); /* fork error */
90         }
91         if ( i > 0)
92                 exit(0); /* parent exits */
93         
94         /* child (daemon) continues */
95         setsid(); /* obtain a new process group */
96         for (i = getdtablesize(); i >= 0; --i)
97                 close(i); /* close all descriptors */
98         
99         i = open("/dev/null",O_RDWR);
100         dup(i);
101         dup(i);
102         
103         umask(027); /* set newly created file permissions */
104         chdir("/");
105                 
106 }
107
108 void setscheduler()
109 {
110         int rc;
111         struct sched_param sp;
112
113         sp.sched_priority = sched_get_priority_min(SCHED_RR); /* Should suffice */
114         Log_info("Setting SCHED_RR prio %d", sp.sched_priority);
115         rc = sched_setscheduler(0, SCHED_RR, &sp);
116         if (rc < 0)
117                 Log_warn("Failed to set scheduler: %s", strerror(errno));
118 }
119
120 void printhelp()
121 {
122         printf("uMurmur version %s. Mumble protocol %d\n", UMURMUR_VERSION, MESSAGE_STREAM_VERSION);
123         printf("Usage: umurmurd [-d] [-p <pidfile>] [-c <conf file>] [-h]\n");
124         printf("       -d             - Do not deamonize\n");
125         printf("       -p <pidfile>   - Write PID to this file\n");
126         printf("       -c <conf file> - Specify configuration file\n");
127         printf("       -h             - Print this help\n");
128         exit(0);
129 }
130
131 int main(int argc, char **argv)
132 {
133         bool_t nodaemon = false;
134         char *conffile = NULL, *pidfile = NULL;
135         int c;
136         
137         /* Arguments */
138         while ((c = getopt(argc, argv, "dp:c:h")) != EOF) {
139                 switch(c) {
140                 case 'c':
141                         conffile = optarg;
142                         break;
143                 case 'p':
144                         pidfile = optarg;
145                         break;
146                 case 'd':
147                         nodaemon = true;
148                         break;
149                 case 'h':
150                         printhelp();
151                         break;
152                 default:
153                         fprintf(stderr, "Unrecognized option\n");
154                         printhelp();
155                         break;
156                 }
157         }
158         
159         if (Conf_init(conffile) != 0) {
160                 fprintf(stderr, "Configuration error\n");
161                 exit(1);
162         }
163                 
164         if (!nodaemon) {
165                 Log_init(false);
166                 daemonize();
167                 if (pidfile != NULL)
168                         lockfile(pidfile);
169         }
170         else
171                 Log_init(true);
172         
173         signal(SIGCHLD, SIG_IGN); /* ignore child */
174         signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
175         signal(SIGTTOU, SIG_IGN);
176         signal(SIGTTIN, SIG_IGN);
177         signal(SIGHUP, signal_handler); /* catch hangup signal */
178         signal(SIGTERM, signal_handler); /* catch kill signal */
179
180         /* Initializing */
181         SSL_init();
182         Chan_init();
183         Client_init();
184
185         setscheduler();
186         Server_run();
187         
188         SSL_deinit();
189         Chan_free();
190         Log_free();
191         Conf_deinit();
192         
193         if (pidfile != NULL)
194                 unlink(pidfile);
195         
196         return 0;
197 }