Add commandline switch for turning on SCHED_RR. Update version to 0.1.3
[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.3"
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("       -r             - Run with realtime priority\n");
128         printf("       -h             - Print this help\n");
129         exit(0);
130 }
131
132 int main(int argc, char **argv)
133 {
134         bool_t nodaemon = false;
135         bool_t realtime = false;
136         char *conffile = NULL, *pidfile = NULL;
137         int c;
138         
139         /* Arguments */
140         while ((c = getopt(argc, argv, "drp:c:h")) != EOF) {
141                 switch(c) {
142                 case 'c':
143                         conffile = optarg;
144                         break;
145                 case 'p':
146                         pidfile = optarg;
147                         break;
148                 case 'd':
149                         nodaemon = true;
150                         break;
151                 case 'h':
152                         printhelp();
153                         break;
154                 case 'r':
155                         realtime = true;
156                         break;
157                 default:
158                         fprintf(stderr, "Unrecognized option\n");
159                         printhelp();
160                         break;
161                 }
162         }
163         
164         if (Conf_init(conffile) != 0) {
165                 fprintf(stderr, "Configuration error\n");
166                 exit(1);
167         }
168                 
169         if (!nodaemon) {
170                 Log_init(false);
171                 daemonize();
172                 if (pidfile != NULL)
173                         lockfile(pidfile);
174         }
175         else
176                 Log_init(true);
177         
178         signal(SIGCHLD, SIG_IGN); /* ignore child */
179         signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
180         signal(SIGTTOU, SIG_IGN);
181         signal(SIGTTIN, SIG_IGN);
182         signal(SIGHUP, signal_handler); /* catch hangup signal */
183         signal(SIGTERM, signal_handler); /* catch kill signal */
184
185         /* Initializing */
186         SSL_init();
187         Chan_init();
188         Client_init();
189
190         if (realtime)
191                 setscheduler();
192         
193         Server_run();
194         
195         SSL_deinit();
196         Chan_free();
197         Log_free();
198         Conf_deinit();
199         
200         if (pidfile != NULL)
201                 unlink(pidfile);
202         
203         return 0;
204 }