74c33e40834c3cc17cbcbe46f919e8891a1045c9
[rxpd] / src / main.c
1 /*
2     main.c - regex policy daemon
3
4   Copyright (C)
5     2007,               Christian Thaeter <ct@pipapo.org>
6
7   This program is free software; you can redistribute it and/or
8   modify it under the terms of the GNU General Public License as
9   published by the Free Software Foundation; either version 2 of the
10   License, or (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "rxpd.h"
23
24 #include <string.h>
25 #include <sys/time.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29
30 #include <event.h>
31
32
33 void
34 version (void)
35 {
36   printf (
37           "  Regex Policy Daemon ("PACKAGE_STRING")\n\n"
38           "  Copyright (C)\n"
39           "    2007,               Christian Thaeter <ct@pipapo.org>\n\n"
40           "  This is free software.  You may redistribute copies of it under the terms of\n"
41           "  the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n"
42           "  There is NO WARRANTY, to the extent permitted by law.\n\n"
43           "  http://www.pipapo.org/pipawiki/RegexPolicyDaemon\n"
44           );
45 }
46
47 void
48 usage (void)
49 {
50   /*
51     rxpd [OPTIONS] RULES..
52     -v          verbosity
53     -V          version
54     -d          daemonize
55     -D          debug
56     -b dir      basedir for rules
57     -q          quiet
58     -t port     tcp
59     -u name     unix
60     -p policy   access policies
61     -i          case insensitive
62     -4          ipv4
63     -6          ipv6
64     -r          resolve names
65     -l log      log hits to logfile
66     -h          usage
67
68     -U user     switch to user
69   */
70
71 }
72
73
74 int
75 main (int argc, char** argv)
76 {
77   if (pth_init() == FALSE)
78     rxpd_die ("pth initialization failed\n");
79
80   struct rxpd_base* rxpd;
81
82   openlog (PACKAGE_NAME, LOG_PID, LOG_DAEMON);
83
84   rxpd = rxpd_init ();
85
86   rxpd_log (rxpd, LOG_NOTICE, PACKAGE_STRING" starting up\n");
87
88   // parse commandline args
89   opterr = 0;
90
91   int opt;
92
93   while ((opt = getopt (argc, argv, "vVdDb:qt:u:p:i46rl:h")) != -1)
94     switch (opt)
95       {
96       case 'v':
97         if (rxpd->verbosity < LOG_DEBUG)
98           ++rxpd->verbosity;
99         break;
100       case 'V':
101         version ();
102         exit (EXIT_SUCCESS);
103       case 'd':
104         rxpd->daemonize = 1;
105         break;
106       case 'D':
107         if (rxpd->verbosity < LOG_INFO)
108           rxpd->verbosity = LOG_INFO;
109         rxpd->daemonize = 0;
110         break;
111       case 'b':
112         if (!rxpd->basedir)
113           rxpd->basedir = rxpd_strdup (optarg);
114         else
115           rxpd_die ("basedir already set\n");
116         break;
117       case 'q':
118         rxpd->verbosity = LOG_ALERT;
119         break;
120       case 't':
121         {
122           int port = atoi (optarg);
123           if (port > 0 && port < 65536)
124             {
125               rxpd_socket_new_tcp4 (rxpd, NULL, port);
126               // TODO error handling
127             }
128           else
129             {
130               rxpd_log (rxpd, LOG_ALERT, "Illegal port number\n");
131               exit (EXIT_FAILURE);
132             }
133         }
134         // TODO rxpd_socket_new_tcp6 (rxpd, NULL, 2374)
135         break;
136 #if 0 /*not yet implemented*/
137       case 'u':
138         //rxpd_socket_new_unix (rxpd, NULL, 2374);
139         break;
140 #endif
141       case 'p':
142         if (!rxpd->policy)
143           rxpd->policy = rxpd_file_new (rxpd, optarg);
144         else
145           rxpd_die ("policy already set\n");
146         break;
147       case 'i':
148         rxpd->regflags |= REG_ICASE; 
149         break;
150 #if 0 /*not yet implemented*/
151       case '4':
152         break;
153       case '6':
154         break;
155       case 'r':
156         break;
157       case 'l:':
158         break;
159 #endif
160       case 'h':
161         usage ();
162         exit (0);
163         break;
164       default:
165         rxpd_log (rxpd, LOG_ALERT, "Unknown option\n");
166         exit (EXIT_FAILURE);
167       }
168
169   if (!rxpd->basedir)
170     {
171       rxpd_log (rxpd, LOG_ALERT, "Basedir not set (use -b BASEDIR)\n");
172       exit (EXIT_FAILURE);
173     }
174
175   if (llist_is_empty (&rxpd->sockets))
176     {
177       rxpd_log (rxpd, LOG_ALERT, "No listening sockets (use -t TCP or -u UNIX)\n");
178       exit (EXIT_FAILURE);
179     }
180
181   if (rxpd->policy)
182     {
183       if (rxpd_file_load (rxpd->policy))
184         rxpd_log (rxpd, LOG_INFO, "Loaded policy '%s'\n", rxpd->policy->filename);
185       else
186         {
187           rxpd_log (rxpd, LOG_ALERT, "Failed loading policy file\n");
188           exit (EXIT_FAILURE);
189         }
190     }
191
192   for (int i = optind; i < argc; ++i)
193     {
194       if (!rxpd_file_load (rxpd_file_new (rxpd, argv[i])))
195         {
196           //rxpd_log (rxpd, LOG_ALERT, "Failed loading file '%s'\n");
197           exit (EXIT_FAILURE);
198         }
199     }
200
201   if (rxpd->daemonize && daemon(1, 0))
202     rxpd_die ("Couldn't daemonize\n");
203
204   LLIST_FOREACH (&rxpd->sockets, n)
205     {
206       struct rxpd_socket* socket = (struct rxpd_socket*)n;
207       rxpd_socket_spawn (socket);
208     }
209
210   LLIST_FOREACH (&rxpd->sockets, n)
211     {
212       struct rxpd_socket* socket = (struct rxpd_socket*)n;
213       rxpd_socket_delete (rxpd_socket_join (socket));
214     }
215
216
217   rxpd_log (rxpd, LOG_NOTICE, PACKAGE_STRING" exited\n");
218   rxpd_destroy ();
219
220   return EXIT_SUCCESS;
221 }