37de05810dcfd1e494b3793485899b001a099d96
[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 void
31 version (void)
32 {
33   printf (
34           "  Regex Policy Daemon ("PACKAGE_STRING")\n\n"
35           "  Copyright (C)\n"
36           "    2007,               Christian Thaeter <ct@pipapo.org>\n\n"
37           "  This is free software.  You may redistribute copies of it under the terms of\n"
38           "  the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n"
39           "  There is NO WARRANTY, to the extent permitted by law.\n\n"
40           "  http://www.pipapo.org/pipawiki/RegexPolicyDaemon\n"
41           );
42 }
43
44 void
45 usage (void)
46 {
47   printf (
48     "rxpd [OPTIONS] RULES..\n"
49     " -v          increase verbosity level\n"
50     " -V          show version\n"
51     " -d          daemonize into background\n"
52     " -D          debug mode\n"
53     " -b dir      basedir for rules\n"
54     " -q          be quiet\n"
55     " -t port     listen on tcp port\n"
56     //" -u name     unix\n"
57     " -p policy   define a list for access policies\n"
58     //" -i          case insensitive\n"
59     //" -4          ipv4\n"
60     //" -6          ipv6\n"
61     //" -r          resolve names\n"
62     //" -l log      log hits to logfile\n"
63     " -h          this usage information\n"
64     //" -U user     switch to user\n"
65     );
66 }
67
68
69 int
70 main (int argc, char** argv)
71 {
72   if (pth_init() == FALSE)
73     rxpd_fail (NULL, "pth initialization failed\n");
74
75   struct rxpd_base* rxpd;
76
77   openlog (PACKAGE_NAME, LOG_PID, LOG_DAEMON);
78
79   rxpd = rxpd_init ();
80
81   opterr = 0;
82   int opt;
83
84   while ((opt = getopt (argc, argv, "vVdDb:qt:u:p:i46rl:h")) != -1)
85     switch (opt)
86       {
87       case 'v':
88         if (rxpd->verbosity < LOG_DEBUG)
89           ++rxpd->verbosity;
90         break;
91       case 'V':
92         version ();
93         exit (EXIT_SUCCESS);
94       case 'd':
95         rxpd->daemonize = 1;
96         break;
97       case 'D':
98         if (rxpd->verbosity < LOG_INFO)
99           rxpd->verbosity = LOG_INFO;
100         rxpd->daemonize = 0;
101         break;
102       case 'b':
103         if (!rxpd->basedir)
104           rxpd->basedir = rxpd_strdup (optarg);
105         else
106           rxpd_fail (rxpd, "basedir already set\n");
107         break;
108       case 'q':
109         rxpd->verbosity = LOG_ALERT;
110         break;
111       case 't':
112         {
113           int port = atoi (optarg);
114           if (port > 0 && port < 65536)
115             {
116               rxpd_socket_new_tcp4 (rxpd, NULL, port);
117               // TODO error handling
118             }
119           else
120             rxpd_fail (rxpd, "Illegal port number\n");
121         }
122         // TODO rxpd_socket_new_tcp6 (rxpd, NULL, 2374)
123         break;
124 #if 0 /*not yet implemented*/
125       case 'u':
126         //rxpd_socket_new_unix (rxpd, NULL, 2374);
127         break;
128 #endif
129       case 'p':
130         if (!rxpd->policy)
131           rxpd->policy = rxpd_file_new (rxpd, optarg);
132         else
133           rxpd_fail (rxpd, "policy already set\n");
134         break;
135       case 'i':
136         rxpd->regflags |= REG_ICASE; 
137         break;
138 #if 0 /*not yet implemented*/
139       case '4':
140         break;
141       case '6':
142         break;
143       case 'r':
144         break;
145       case 'l:':
146         break;
147 #endif
148       case 'h':
149         usage ();
150         exit (0);
151         break;
152       default:
153         rxpd_fail (rxpd, "Unknown option '-%c'\n", opt);
154       }
155
156   if (!rxpd->basedir)
157     rxpd_fail (rxpd, "Basedir not set (use -b BASEDIR)\n");
158
159   if (llist_is_empty (&rxpd->sockets))
160     rxpd_fail (rxpd, "No listening sockets given (use -t TCP or -u UNIX)\n");
161
162   if (rxpd->policy)
163     {
164       if (rxpd_file_load (rxpd->policy))
165         rxpd_log (rxpd, LOG_INFO, "Loaded policy '%s'\n", rxpd->policy->filename);
166       else
167         rxpd_fail (rxpd, "Failed loading policy '%s'\n", rxpd->policy->filename);
168     }
169
170   for (int i = optind; i < argc; ++i)
171     {
172       if (!rxpd_file_load (rxpd_file_new (rxpd, argv[i])))
173         rxpd_fail (rxpd, "Failed loading file '%s'\n", argv[i]);
174     }
175
176   if (rxpd->daemonize && daemon(1, 0))
177     rxpd_fail (rxpd, "Couldn't daemonize\n");
178
179   rxpd_log (rxpd, LOG_NOTICE, PACKAGE_STRING" starting up\n");
180
181   LLIST_FOREACH (&rxpd->sockets, n)
182     {
183       struct rxpd_socket* socket = (struct rxpd_socket*)n;
184       rxpd_socket_spawn (socket);
185     }
186
187   rxpd_log (rxpd, LOG_NOTICE, PACKAGE_STRING" running\n");
188
189   LLIST_WHILE_HEAD (&rxpd->sockets, n)
190     {
191       struct rxpd_socket* socket = (struct rxpd_socket*)n;
192       rxpd_socket_delete (rxpd_socket_join (socket));
193     }
194
195   rxpd_log (rxpd, LOG_NOTICE, PACKAGE_STRING" exited\n");
196   rxpd_destroy ();
197
198   return EXIT_SUCCESS;
199 }