logging improvement
[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"
43           );
44 }
45
46 void
47 usage (void)
48 {
49   /*
50     rxpd [OPTIONS] RULES..
51     -v          verbosity
52     -V          version
53     -d          daemonize
54     -D          debug
55     -b dir      basedir for rules
56     -q          quiet
57     -t port     tcp
58     -u name     unix
59     -p policy   access policies
60     -i          case insensitive
61     -4          ipv4
62     -6          ipv6
63     -r          resolve names
64     -l log      log hits to logfile
65     -h          usage
66
67     -U user     switch to user
68   */
69
70 }
71
72
73 int
74 main (int argc, char** argv)
75 {
76   struct rxpd_base* rxpd;
77
78   openlog (PACKAGE_NAME, LOG_PID, LOG_DAEMON);
79
80   rxpd = rxpd_init (event_init ());
81
82   rxpd_log (rxpd, LOG_NOTICE, PACKAGE_STRING" starting up\n");
83
84   // parse commandline args
85   opterr = 0;
86
87   int opt;
88
89   while ((opt = getopt (argc, argv, "vVdDb:qt:u:p:i46rl:h")) != -1)
90     switch (opt)
91       {
92       case 'v':
93         if (rxpd->verbosity < LOG_DEBUG)
94           ++rxpd->verbosity;
95         break;
96       case 'V':
97         version ();
98         exit (EXIT_SUCCESS);
99       case 'd':
100         rxpd->daemonize = 1;
101         break;
102       case 'D':
103         if (rxpd->verbosity < LOG_NOTICE)
104           rxpd->verbosity = LOG_NOTICE;
105         rxpd->daemonize = 0;
106         break;
107       case 'b':
108         if (!rxpd->basedir)
109           rxpd->basedir = rxpd_strdup (optarg);
110         else
111           rxpd_die ("basedir already set\n");
112         break;
113       case 'q':
114         rxpd->verbosity = LOG_ALERT;
115         break;
116       case 't':
117         {
118           int port = atoi (optarg);
119           if (port > 0 && port < 65536)
120             {
121               rxpd_socket_new_tcp4 (rxpd, NULL, port);
122               // TODO error handling
123             }
124           else
125             {
126               rxpd_log (rxpd, LOG_ALERT, "Illegal port number\n");
127               exit (EXIT_FAILURE);
128             }
129         }
130         // TODO rxpd_socket_new_tcp6 (rxpd, NULL, 2374)
131         break;
132 #if 0 /*not yet implemented*/
133       case 'u':
134         //rxpd_socket_new_unix (rxpd, NULL, 2374);
135         break;
136 #endif
137       case 'p':
138         if (!rxpd->policy)
139           rxpd->policy = rxpd_file_new (rxpd, optarg);
140         else
141           rxpd_die ("policy already set\n");
142         break;
143       case 'i':
144         rxpd->regflags |= REG_ICASE; 
145         break;
146 #if 0 /*not yet implemented*/
147       case '4':
148         break;
149       case '6':
150         break;
151       case 'r':
152         break;
153       case 'l:':
154         break;
155 #endif
156       case 'h':
157         usage ();
158         exit (0);
159         break;
160       default:
161         rxpd_log (rxpd, LOG_ALERT, "Unknown option\n");
162         exit (EXIT_FAILURE);
163       }
164
165   for (int i = optind; i < argc; ++i)
166     {
167       if (!rxpd_file_load (rxpd_file_new (rxpd, argv[i])))
168         {
169           //rxpd_log (rxpd, LOG_ALERT, "Failed loading file '%s'\n");
170           exit (EXIT_FAILURE);
171         }
172     }
173
174   if (rxpd->daemonize && daemon(0, 0))
175     rxpd_die ("Couldn't daemonize\n");
176
177   if (!rxpd->basedir)
178     {
179       rxpd_log (rxpd, LOG_ALERT, "Basedir not set (use -b BASEDIR)\n");
180       exit (EXIT_FAILURE);
181     }
182
183   if (llist_is_empty (&rxpd->sockets))
184     {
185       rxpd_log (rxpd, LOG_ALERT, "No listening sockets (use -t TCP or -u UNIX)\n");
186       exit (EXIT_FAILURE);
187     }
188
189   if (rxpd->policy && !rxpd_file_load (rxpd->policy))
190     {
191       rxpd_log (rxpd, LOG_ALERT, "Failed loading policy file\n");
192       exit (EXIT_FAILURE);
193     }
194
195   LLIST_FOREACH (&rxpd->sockets, n)
196     {
197       struct rxpd_socket* socket = (struct rxpd_socket*)n;
198       rxpd_socket_schedule (socket);
199     }
200
201
202   // eventloop
203   event_dispatch ();
204
205   rxpd_log (rxpd, LOG_NOTICE, PACKAGE_STRING" exited\n");
206   rxpd_destroy ();
207   return EXIT_SUCCESS;
208 }