Install and distribute new manual page.
[fwd] / fw.c
1 /* -*-c-*-
2 *
3 * $Id: fw.c,v 1.1 1999/07/01 08:56:23 mdw Exp $
4 *
5 * Port forwarding thingy
6 *
7 * (c) 1999 Mark Wooding
8 */
9
10 /*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of the `fw' port forwarder.
13 *
14 * `fw' is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * `fw' is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with `fw'; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29 /*----- Revision history --------------------------------------------------*
30 *
31 * $Log: fw.c,v $
32 * Revision 1.1 1999/07/01 08:56:23 mdw
33 * Initial revision
34 *
35 */
36
37 /*----- Header files ------------------------------------------------------*/
38
39 #include "config.h"
40
41 #include <ctype.h>
42 #include <errno.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46
47 #include <unistd.h>
48 #include <syslog.h>
49
50 #include <mLib/mdwopt.h>
51 #include <mLib/quis.h>
52 #include <mLib/report.h>
53 #include <mLib/sel.h>
54 #include <mLib/sub.h>
55
56 #include "acl.h"
57 #include "bres.h"
58 #include "conf.h"
59 #include "listener.h"
60 #include "scan.h"
61
62 /*----- Static variables --------------------------------------------------*/
63
64 sel_state *sel; /* Multiplexor for nonblocking I/O */
65
66 /*----- Main code ---------------------------------------------------------*/
67
68 /* --- Standard GNU help options --- */
69
70 static void version(FILE *fp)
71 {
72 fprintf(fp, "%s version " VERSION "\n", QUIS);
73 }
74
75 static void usage(FILE *fp)
76 {
77 fprintf(stderr, "Usage: %s [-d] [-f file] [config statements...]\n",
78 QUIS);
79 }
80
81 static void help(FILE *fp)
82 {
83 version(fp);
84 fputc('\n', fp);
85 usage(fp);
86 fputs("\n\
87 A fairly full-featured port-forwarder. Options available are:\n\
88 \n\
89 -h, --help Display this help message.\n\
90 -v, --version Display the program's version number.\n\
91 -u, --usage Display a terse usage summary.\n\
92 \n\
93 -f, --file=FILE Read configuration from a file.\n\
94 -d, --dump Dump the configuration to standard output.\n\
95 \n\
96 Configuration may be supplied in one or more configuration files, or on\n\
97 the command line (or both). If no `-f' option is present, and no\n\
98 configuration is given on the command line, the standard input stream is\n\
99 read.\n\
100 \n\
101 Configuration is free-form. Comments begin with a `#' character and\n\
102 continue to the end of the line. When reading from the command line,\n\
103 each argument is considered a separate line. See the manual page for the\n\
104 complete syntax.\n\
105 ", fp);
106 }
107
108 /* --- @main@ --- *
109 *
110 * Arguments: @int argc@ = number of command line arguments
111 * @char *argv[]@ = vector of argument strings
112 *
113 * Returns: ---
114 *
115 * Use: Simple port-forwarding server.
116 */
117
118 int main(int argc, char *argv[])
119 {
120 unsigned f = 0;
121 sel_state sst;
122
123 enum {
124 f_bogus = 1,
125 f_file = 2,
126 f_dump = 4,
127 f_fork = 8
128 };
129
130 /* --- Initialize things --- */
131
132 ego(argv[0]);
133 sel = &sst;
134 sel_init(sel);
135 sub_init();
136 bres_init(sel);
137
138 /* --- Parse command line options --- */
139
140 for (;;) {
141 static struct option opts[] = {
142
143 /* --- Standard GNU help options --- */
144
145 { "help", 0, 0, 'h' },
146 { "version", 0, 0, 'v' },
147 { "usage", 0, 0, 'u' },
148
149 /* --- Other useful arguments --- */
150
151 { "file", OPTF_ARGREQ, 0, 'f' },
152 { "dump", 0, 0, 'd' },
153 { "fork", 0, 0, 'b' },
154 { "background", 0, 0, 'b' },
155
156 /* --- Magic terminator --- */
157
158 { 0, 0, 0, 0 }
159 };
160 int i = mdwopt(argc, argv, "hvu f:db", opts, 0, 0, 0);
161
162 if (i < 0)
163 break;
164 switch (i) {
165 case 'h':
166 help(stdout);
167 exit(0);
168 break;
169 case 'v':
170 version(stdout);
171 exit(0);
172 break;
173 case 'u':
174 usage(stdout);
175 exit(0);
176 break;
177 case 'f': {
178 scan_filectx ctx;
179 FILE *fp;
180 if ((fp = fopen(optarg, "r")) == 0)
181 die(1, "couldn't open file `%s': %s", optarg, strerror(errno));
182 scan_fileinit(&ctx, fp, optarg);
183 conf_parse(&ctx);
184 fclose(fp);
185 f |= f_file;
186 } break;
187 case 'd':
188 f |= f_dump;
189 break;
190 case 'b':
191 f |= f_fork;
192 break;
193 default:
194 f |= f_bogus;
195 break;
196 }
197 }
198
199 if (f & f_bogus) {
200 usage(stderr);
201 exit(1);
202 }
203
204 /* --- Deal with the remaining arguments --- */
205
206 if (optind == argc) {
207 if (f & f_file)
208 /* Cool */;
209 else if (isatty(STDIN_FILENO)) {
210 moan("no configuration given and stdin is a terminal.");
211 moan("type `%s --help' for usage information.", QUIS);
212 exit(1);
213 } else {
214 scan_filectx ctx;
215 scan_fileinit(&ctx, stdin, "<stdin>");
216 conf_parse(&ctx);
217 }
218 } else {
219 scan_argvctx ctx;
220 scan_argvinit(&ctx, argv + optind);
221 conf_parse(&ctx);
222 }
223
224 /* --- Dump out the state --- */
225
226 if (f & f_dump) {
227 sel_file *s;
228 fputs("global acl:\n", stdout);
229 acl_dump(0, stdout);
230 for (s = sel->files; s; s = s->next)
231 listener_dump((listener *)s, stdout);
232 exit(0);
233 }
234
235 /* --- Fork into the background --- */
236
237 if (f & f_fork) {
238 pid_t kid;
239
240 kid = fork();
241 if (kid == -1)
242 die(1, "couldn't fork: %s", strerror(errno));
243 if (kid != 0)
244 _exit(0);
245
246 close(0); close(1); close(2);
247 setsid();
248
249 kid = fork();
250 if (kid != 0)
251 _exit(0);
252 }
253
254 /* --- Let rip --- */
255
256 openlog(QUIS, 0, LOG_DAEMON);
257 for (;;)
258 sel_select(sel);
259 return (0);
260 }
261
262 /*----- That's all, folks -------------------------------------------------*/