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