1 /*
2 * Copyright 2000, 2001, 2002 Brian S. Dean <bsd@bsdhome.com>
3 * All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY BRIAN S. DEAN ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRIAN S. DEAN BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
25 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26 * DAMAGE.
27 *
28 */
29
30 /*
31 * Name : comservd
32 *
33 * Purpose : Program for communicating with terminal server devices,
34 * such as the Xyplex MAXserver 1600. This program allows
35 * programs like 'tip' to connect to serial devices
36 * connected to the terminal server by providing an
37 * interface between pseudo ttys and network terminal server
38 * serial ports.
39 *
40 * Author : Brian Dean, bsd@FreeBSD.org, bsd@bsdhome.com
41 * Date : 25 June, 2000
42 *
43 */
44
45
46 /* $Id: main.c,v 1.20 2002/04/30 15:34:33 bsd Exp $ */
47
48
49 #include <stdio.h>
50 #include <unistd.h>
51 #include <limits.h>
52 #include <string.h>
53 #include <syslog.h>
54 #include <stdlib.h>
55 #include <errno.h>
56 #include <string.h>
57 #include <signal.h>
58
59 #include "comserv.h"
60 #include "endp.h"
61 #include "evloop.h"
62 #include "log.h"
63
64
65 #ifdef LIBEFENCE
66 /* for controlling ElectricFence */
67 extern int EF_PROTECT_FREE;
68 extern int EF_PROTECT_BELOW;
69 extern int EF_ALIGNMENT;
70 extern int EF_ALLOW_MALLOC_0;
71 extern int EF_FILL;
72 #endif
73
74
75
76 COMSERV_PORT * comserv_ports=NULL; /* linked list of defined terminal
77 server ports that we know about */
78
79 COMSERV_PORT global;
80
81 int maxfd; /* max file descriptor currently in use */
82
83 fd_set master_rd; /* the master set of file descriptor bits that are
84 selected for readability */
85 fd_set master_wr; /* the master set of file descriptor bits that are
86 selected for writeability */
87
88 #ifdef ENABLE_TELNET_PORT
89 int lsock; /* listening socket for telnet command interface */
90 #endif
91
92 int config_fd; /* file descriptor for the configuration file */
93
94 char * progname;
95
96 char * cvsvers = "$Id: main.c,v 1.20 2002/04/30 15:34:33 bsd Exp $";
97
98 char module_timestamp[64];
99
100 int verbose = 0;
101
102 unsigned int debug_flags = 0;
103
104 volatile int hupped = 0;
105
106
107 char prog_img [ PATH_MAX ];
108 char ** prog_argv;
109
110 char * main_versionid = "$Id: main.c,v 1.20 2002/04/30 15:34:33 bsd Exp $";
111
112 extern char * cmd_versionid;
113 extern char * comserv_versionid;
114 extern char * endp_versionid;
115 extern char * evloop_versionid;
116 extern char * log_versionid;
117 extern char * main_versionid;
118 extern char * pty_versionid;
119
120 #define N_MODULES 7
121 char ** modules[N_MODULES] = {
122 &cmd_versionid,
123 &comserv_versionid,
124 &endp_versionid,
125 &evloop_versionid,
126 &log_versionid,
127 &main_versionid,
128 &pty_versionid
129 };
130
131
132 int print_module_versions(FILE * outf, char * timestamp);
133
134
sighup(int sig)135 void sighup(int sig)
136 {
137 hupped = 1;
138 }
139
140
141
sigpipe(int sig)142 void sigpipe(int sig)
143 {
144 msgout("caught SIGPIPE!\n");
145 return;
146 }
147
148
149
150
main(int argc,char * argv[])151 int main(int argc, char * argv [])
152 {
153 int rc;
154 int c;
155
156 #ifdef LIBEFENCE
157 EF_PROTECT_FREE=1;
158 EF_PROTECT_BELOW=1;
159 #endif
160
161 progname = rindex(argv[0],'/');
162 if (progname) {
163 progname++;
164 }
165 else {
166 progname = argv[0];
167 }
168
169 prog_argv = argv;
170 if (realpath(argv[0], prog_img) == NULL) {
171 prog_img[0] = 0;
172 }
173
174 memset(&global, 0, sizeof(global));
175 global.flags = OPT_DEFAULT;
176
177 strncpy(config_file, DEFAULT_CONFIG, PATH_MAX);
178 config_file[PATH_MAX-1] = 0;
179
180 while ((c = getopt(argc, argv, "f:")) != -1) {
181 switch (c) {
182 case 'f':
183 strncpy(config_file, optarg, PATH_MAX);
184 config_file[PATH_MAX-1] = 0;
185 break;
186
187 case '?':
188 default :
189 fprintf(stderr, "%s: invalid command line option \"%s\"\n",
190 progname, argv[optind]);
191 exit(1);
192 break;
193 }
194 }
195
196 #if CONSOLE == 0
197 openlog(progname, LOG_PID, LOG_DAEMON);
198
199 rc = daemon(0, 0);
200 if (rc) {
201 msgout("can't become daemon: %s\n", strerror(errno));
202 exit(1);
203 }
204 #endif
205
206 strcpy(module_timestamp, "indeterminate");
207
208 msgout("starting\n");
209 print_module_versions(stderr, module_timestamp);
210 msgout("revision timestamp %s\n", module_timestamp);
211
212 rc = access(prog_img, X_OK);
213 if (rc < 0) {
214 msgout("can't determine image file; restart feature won't work\n");
215 prog_img[0] = 0;
216 }
217 else {
218 msgout("image file = %s\n", prog_img);
219 }
220
221 /*
222 * initialize command interface
223 */
224 cmd_init();
225
226 /*
227 * initialize endpoints
228 */
229 rc = endp_init();
230 if (rc < 0) {
231 msgout("terminating\n");
232 exit(1);
233 }
234
235 msgout("max # endpoints is %d\n", max_endpoint);
236
237 #ifdef ENABLE_TELNET_PORT
238 lsock = sock_bind_service(COMSERV, 0);
239 if (lsock < 0) {
240 if (lsock == -1) {
241 msgout("can't establish service for \"%s\"\n", COMSERV);
242 msgout("add service \"%s N/tcp\" to /etc/services\n", COMSERV);
243 }
244 else {
245 msgout("failed to establish telnet command interface\n");
246 msgout("telnet command interface is disabled\n");
247 }
248 lsock = -1;
249 }
250 #endif
251
252 comserv_ports = NULL;
253
254 signal(SIGHUP, sighup);
255 signal(SIGPIPE, sigpipe);
256
257 event_loop();
258
259 msgout("exiting\n");
260
261 return 0;
262 }
263
264
265
parse_cvsid(char * cvsid,char * name,char * rev,char * datetime)266 int parse_cvsid(char * cvsid, char * name, char * rev, char * datetime)
267 {
268 int i, j;
269
270 if (!((strncmp(cvsid,"$Id: ",5) != 0) ||
271 (strncmp(cvsid,"$FreeBSD: ",10) != 0)))
272 return -1;
273
274 name[0] = 0;
275 rev[0] = 0;
276 datetime[0] = 0;
277
278 i = 0;
279 j = 0;
280 while (cvsid[j] && cvsid[j] != ' ')
281 j++;
282
283 while (cvsid[j] && cvsid[j] != ',')
284 name[i++] = cvsid[j++];
285 name[i] = 0;
286
287 while (cvsid[j] && cvsid[j] != ' ')
288 j++;
289
290 if (cvsid[j])
291 j++;
292
293 i = 0;
294 while (cvsid[j] && cvsid[j] != ' ')
295 rev[i++] = cvsid[j++];
296 rev[i] = 0;
297
298 if (cvsid[j])
299 j++;
300
301 i = 0;
302 while (cvsid[j] && cvsid[j] != ' ')
303 datetime[i++] = cvsid[j++];
304 if (cvsid[j] == ' ') {
305 datetime[i++] = cvsid[j++];
306 while (cvsid[j] && cvsid[j] != ' ')
307 datetime[i++] = cvsid[j++];
308 }
309 datetime[i] = 0;
310
311 return 0;
312 }
313
314
print_module_versions(FILE * outf,char * timestamp)315 int print_module_versions(FILE * outf, char * timestamp)
316 {
317 char name[64], rev[16], datetime[64];
318 int y, m, d, h, min, s;
319 int i;
320 int rc;
321 int maxtime;
322 struct tm t;
323 time_t now;
324
325 maxtime = 0;
326 for (i=0; i<N_MODULES; i++) {
327 parse_cvsid(*modules[i], name, rev, datetime);
328 rc = sscanf(datetime, "%d/%d/%d %d:%d:%d", &y, &m, &d, &h, &min, &s);
329 if (rc != 6) {
330 fprintf(stderr, "%s: module version scan error, rc=%d\n", progname, rc);
331 }
332 else if (timestamp) {
333 now = time(NULL);
334 gmtime_r(&now, &t);
335 t.tm_sec = s;
336 t.tm_min = min;
337 t.tm_hour = h;
338 t.tm_mday = d;
339 t.tm_mon = m-1;
340 t.tm_year = y-1900;
341 now = timegm(&t);
342 if (now > maxtime) {
343 maxtime = now;
344 strcpy(timestamp, datetime);
345 strcat(timestamp, " GMT");
346 }
347 }
348 if (outf)
349 fprintf(outf, " %-10s %-5s %s\n", name, rev, datetime);
350 }
351
352 if (outf)
353 fprintf(outf, "\n");
354
355 if (outf)
356 fprintf(outf, "\n");
357
358 return 0;
359 }
360
361
362
363