Add bind address and port to cmdline arguments. Add log of address and port.
[umurmur.git] / src / main.c
1 /* Copyright (C) 2009-2010, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2010, 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 <sys/utsname.h>
38 #include <fcntl.h>
39 #include <signal.h>
40 #include <sched.h>
41 #include <errno.h>
42 #include <string.h>
43 #include <stdlib.h>
44
45 #include "server.h"
46 #include "ssl.h"
47 #include "channel.h"
48 #include "log.h"
49 #include "client.h"
50 #include "conf.h"
51 #include "version.h"
52
53 char system_string[64], version_string[64];
54 int bindport;
55 char *bindaddr;
56
57 void lockfile(const char *pidfile)
58 {
59         int lfp;
60         char str[16];
61         
62         lfp = open(pidfile, O_RDWR|O_CREAT, 0640);
63         
64         if (lfp < 0)
65                 Log_fatal("Cannot open PID-file %s for writing", pidfile);
66         sprintf(str,"%d\n", getpid());
67         write(lfp, str, strlen(str)); /* record pid to lockfile */
68         Log_info("PID-file: %s", pidfile);
69 }
70
71
72 void signal_handler(int sig)
73 {
74         switch(sig) {
75         case SIGHUP:
76                 /* XXX - do stuff? */
77                 Log_info("HUP signal");
78                 break;
79         case SIGTERM:
80                 Log_info("TERM signal. Shutting down.");
81                 Server_shutdown();
82                 break;
83         }
84 }
85
86 void daemonize()
87 {
88         int i;
89         
90         if (getppid() == 1)
91                 return; /* already a daemon */
92         i = fork();
93         if ( i < 0) {
94                 fprintf(stderr, "Fork error. Exiting\n");
95                 exit(1); /* fork error */
96         }
97         if ( i > 0)
98                 exit(0); /* parent exits */
99         
100         /* child (daemon) continues */
101         setsid(); /* obtain a new process group */
102         for (i = getdtablesize(); i >= 0; --i)
103                 close(i); /* close all descriptors */
104         
105         i = open("/dev/null",O_RDWR);
106         dup(i);
107         dup(i);
108         
109         umask(027); /* set newly created file permissions */
110         chdir("/");
111                 
112 }
113
114 void setscheduler()
115 {
116         int rc;
117         struct sched_param sp;
118
119         sp.sched_priority = sched_get_priority_min(SCHED_RR); /* Should suffice */
120         Log_info("Setting SCHED_RR prio %d", sp.sched_priority);
121         rc = sched_setscheduler(0, SCHED_RR, &sp);
122         if (rc < 0)
123                 Log_warn("Failed to set scheduler: %s", strerror(errno));
124 }
125
126 void printhelp()
127 {
128         printf("uMurmur version %s. Mumble protocol %d.%d.%d\n", UMURMUR_VERSION, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
129         printf("Usage: umurmurd [-d] [-p <pidfile>] [-c <conf file>] [-h]\n");
130         printf("       -d             - Do not deamonize\n");
131         printf("       -p <pidfile>   - Write PID to this file\n");
132         printf("       -c <conf file> - Specify configuration file\n");
133         printf("       -r             - Run with realtime priority\n");
134         printf("       -a <address>   - Bind to IP address\n");
135         printf("       -b <port>      - Bind to port\n");
136         printf("       -h             - Print this help\n");
137         exit(0);
138 }
139
140 int main(int argc, char **argv)
141 {
142         bool_t nodaemon = false;
143         bool_t realtime = false;
144         char *conffile = NULL, *pidfile = NULL;
145         int c;
146         struct utsname utsbuf;
147         
148         /* Arguments */
149         while ((c = getopt(argc, argv, "drp:c:a:b:h")) != EOF) {
150                 switch(c) {
151                 case 'c':
152                         conffile = optarg;
153                         break;
154                 case 'p':
155                         pidfile = optarg;
156                         break;
157                 case 'a':
158                         bindaddr = optarg;
159                         break;
160                 case 'b':
161                         bindport = atoi(optarg);
162                         break;
163                 case 'd':
164                         nodaemon = true;
165                         break;
166                 case 'h':
167                         printhelp();
168                         break;
169                 case 'r':
170                         realtime = true;
171                         break;
172                 default:
173                         fprintf(stderr, "Unrecognized option\n");
174                         printhelp();
175                         break;
176                 }
177         }
178         
179         if (Conf_init(conffile) != 0) {
180                 fprintf(stderr, "Configuration error\n");
181                 exit(1);
182         }
183                 
184         if (!nodaemon) {
185                 Log_init(false);
186                 daemonize();
187                 if (pidfile != NULL)
188                         lockfile(pidfile);
189         }
190         else
191                 Log_init(true);
192         
193         signal(SIGCHLD, SIG_IGN); /* ignore child */
194         signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
195         signal(SIGTTOU, SIG_IGN);
196         signal(SIGTTIN, SIG_IGN);
197         signal(SIGPIPE, SIG_IGN);
198         signal(SIGHUP, signal_handler); /* catch hangup signal */
199         signal(SIGTERM, signal_handler); /* catch kill signal */
200         
201         /* Build system string */
202         if (uname(&utsbuf) == 0) {
203                 snprintf(system_string, 64, "%s %s", utsbuf.sysname, utsbuf.machine);
204                 snprintf(version_string, 64, "%s", utsbuf.release);
205         }
206         else {
207                 snprintf(system_string, 64, "unknown unknown");
208                 snprintf(version_string, 64, "unknown");
209         }
210         
211         /* Initializing */
212         SSLi_init();
213         Chan_init();
214         Client_init();
215
216         if (realtime)
217                 setscheduler();
218         
219         Server_run();
220         
221         SSLi_deinit();
222         Chan_free();
223         Log_free();
224         Conf_deinit();
225         
226         if (pidfile != NULL)
227                 unlink(pidfile);
228         
229         return 0;
230 }