1 #ident "$Id: conf_mg.c,v 4.19 2009/03/19 15:13:53 gert Exp $ Copyright (c) Gert Doering"
2 
3 /* conf_mg.c
4  *
5  * configuration defaults / configuration reading code for mgetty
6  */
7 
8 #include <stdio.h>
9 #include <string.h>
10 #include <unistd.h>
11 
12 #include "mgetty.h"
13 #include "policy.h"
14 #include "syslibs.h"
15 #include "tio.h"
16 
17 #include "config.h"
18 #include "conf_mg.h"
19 
20 #include "version.h"
21 char * mgetty_version = VERSION_LONG;		/* version.h */
22 
23 #ifndef MODEM_CHECK_TIME
24 # define MODEM_CHECK_TIME -1		/* no check */
25 #endif
26 
27 #ifndef FAX_RECV_SWITCHBD
28 #define FAX_RECV_SWITCHBD 0		/* no switching */
29 #endif
30 
31 #ifndef FAX_FILE_MODE
32 #define FAX_FILE_MODE	-1		/* controlled by umask */
33 #endif
34 
35 /* initialize the modem - MODEM_INIT_STRING defined in policy.h
36  */
37 static char * def_init_chat_seq[] = { "",
38 			    "\\dATQ0V1H0", "OK",
39 			    MODEM_INIT_STRING, "OK",
40                             NULL };
41 
42 /* "force init" the modem (DLE ETX for voice modems, +++ATH0 for all others)
43  */
44 static char * def_force_init_chat_seq[] = { "",
45 			    "\\d\020\03\\d\\d\\d+++\\d\\d\\d\r\\dATQ0V1H0",
46 			    "OK", NULL };
47 
48 /* default way to answer the phone...
49  */
50 static char * def_answer_chat_seq[] =
51 			    { "", "ATA", "CONNECT", "\\c", "\n", NULL };
52 
53 /* this is the default configuration...
54  */
55 
56 struct conf_data_mgetty c = {
57 	{ "speed", {DEFAULT_PORTSPEED}, CT_INT, C_PRESET },
58 	{ "switchbd", {FAX_RECV_SWITCHBD}, CT_INT, C_PRESET },
59 	{ "direct", {FALSE}, CT_BOOL, C_PRESET },
60 	{ "blocking", {FALSE}, CT_BOOL, C_PRESET },
61 
62 	{ "port-owner", {(p_int) DEVICE_OWNER}, CT_STRING, C_PRESET },
63 #ifdef DEVICE_GROUP
64 	{ "port-group", {(p_int) DEVICE_GROUP}, CT_STRING, C_PRESET },
65 #else
66 	{ "port-group", {0}, CT_STRING, C_EMPTY },
67 #endif
68 	{ "port-mode", {FILE_MODE}, CT_INT, C_PRESET },
69 
70 	{ "toggle-dtr", {TRUE}, CT_BOOL, C_PRESET },
71 	{ "toggle-dtr-waittime", {500}, CT_INT, C_PRESET },
72 	{ "need-dsr", {FALSE}, CT_BOOL, C_PRESET },
73 	{ "data-only", {FALSE}, CT_BOOL, C_PRESET },
74 	{ "fax-only", {FALSE}, CT_BOOL, C_PRESET },
75 	{ "modem-type", {(p_int) DEFAULT_MODEMTYPE}, CT_STRING, C_PRESET },
76 	{ "modem-quirks", {0}, CT_INT, C_EMPTY },
77 	{ "init-chat", {0}, CT_CHAT, C_EMPTY },
78 	{ "force-init-chat", {0}, CT_CHAT, C_EMPTY },
79 	{ "post-init-chat", {0}, CT_CHAT, C_EMPTY },
80 	{ "data-flow", {DATA_FLOW}, CT_FLOWL, C_PRESET },
81 	{ "fax-send-flow", {FAXSEND_FLOW}, CT_FLOWL, C_PRESET },
82 	{ "fax-rec-flow", {FAXREC_FLOW}, CT_FLOWL, C_PRESET },
83 
84 	{ "modem-check-time", {MODEM_CHECK_TIME}, CT_INT, C_PRESET },
85 	{ "rings", {1}, CT_INT, C_PRESET },
86 	{ "msn-list", {(p_int) NULL}, CT_CHAT, C_EMPTY },
87 	{ "get-cnd-chat", {0}, CT_CHAT, C_EMPTY },
88 	{ "cnd-program", {(p_int) NULL}, CT_STRING, C_EMPTY },
89 	{ "answer-chat", {0}, CT_CHAT, C_EMPTY },
90 	{ "answer-chat-timeout", {80}, CT_INT, C_PRESET },
91 	{ "autobauding", {FALSE}, CT_BOOL, C_PRESET },
92 
93 	{ "ringback", {FALSE}, CT_BOOL, C_PRESET },
94 	{ "ringback-time", {30}, CT_INT, C_PRESET },
95 
96 	{ "ignore-carrier", {FALSE}, CT_BOOL, C_PRESET },
97 	{ "issue-file", {(p_int)"/etc/issue"}, CT_STRING, C_PRESET },
98 	{ "prompt-waittime", {500}, CT_INT, C_PRESET },
99 	{ "login-prompt", {(p_int) LOGIN_PROMPT}, CT_STRING, C_PRESET },
100 #ifdef MAX_LOGIN_TIME
101 	{ "login-time", {MAX_LOGIN_TIME}, CT_INT, C_PRESET },
102 #else
103 	{ "login-time", {0}, CT_INT, C_EMPTY },
104 #endif
105 	{ "fido-send-emsi", {TRUE}, CT_BOOL, C_PRESET },
106 	{ "login-env-ttyprompt-hack", {FALSE}, CT_BOOL, C_PRESET },
107 
108 #ifdef LOGIN_CFG_FILE
109 	{ "login-conf-file", {(p_int) LOGIN_CFG_FILE}, CT_STRING, C_PRESET },
110 #else
111 	{ "login-conf-file", {0}, CT_STRING, C_EMPTY },
112 #endif
113 
114 	{ "fax-id", {(p_int)FAX_STATION_ID}, CT_STRING, C_PRESET },
115 	{ "fax-min-speed", {0}, CT_INT, C_PRESET },
116 	{ "fax-max-speed", {14400}, CT_INT, C_PRESET },
117 	{ "fax-server-file", {0}, CT_STRING, C_EMPTY },
118 	{ "diskspace", {MINFREESPACE}, CT_INT, C_PRESET },
119 #ifdef MAIL_TO
120 	{ "notify", {(p_int)MAIL_TO}, CT_STRING, C_PRESET },
121 #else
122 	{ "notify", {0}, CT_STRING, C_EMPTY },
123 #endif
124 	{ "fax-owner", {(p_int)FAX_IN_OWNER}, CT_STRING, C_PRESET },
125 #ifdef FAX_IN_GROUP
126 	{ "fax-group", {(p_int)FAX_IN_GROUP}, CT_STRING, C_PRESET },
127 #else
128 	{ "fax-group", {0}, CT_STRING, C_EMPTY },
129 #endif
130 	{ "fax-mode", {FAX_FILE_MODE}, CT_INT, C_PRESET },
131 #ifdef __STDC__
132 	{ "fax-spool-in", {(p_int) FAX_SPOOL_IN ":/tmp"}, CT_STRING, C_PRESET },
133 #else
134 	{ "fax-spool-in", {(p_int) FAX_SPOOL_IN}, CT_STRING, C_PRESET },
135 #endif
136 
137 	{ "debug", {LOG_LEVEL}, CT_INT, C_PRESET },
138 
139 	{ "statistics-chat", {0}, CT_CHAT, C_EMPTY },
140 	{ "statistics-file", {0}, CT_STRING, C_EMPTY },
141 	{ "gettydefs", {(p_int)GETTYDEFS_DEFAULT_TAG}, CT_STRING, C_PRESET },
142 	{ "term", {0}, CT_STRING, C_EMPTY },
143 
144 	{ NULL, {0}, CT_STRING, C_EMPTY }};
145 
146 /*
147  *	exit_usage() - exit with usage display
148  */
149 
150 void exit_usage _P1((code), int code )
151 {
152 #ifdef USE_GETTYDEFS
153     lprintf( L_FATAL, "Usage: mgetty [-x debug] [-s speed] [-r] line [gettydefentry]" );
154 #else
155     lprintf( L_FATAL, "Usage: mgetty [-x debug] [-s speed] [-r] line" );
156 #endif
157     exit(code);
158 }
159 
160 int mgetty_parse_args _P2( (argc,argv), int argc, char ** argv )
161 {
162 int opt;
163 #ifdef USE_GETTYDEFS
164 extern boolean verbose;
165 #endif
166 
167     /* sanity check:
168      * make sure that structs-in-struct can be handled exactly as if
169      * packed in array (get_config relies on it!)
170      */
171 conf_data c_a[2];
172     if ( ( (char *)&c_a[1] - (char *)&c_a[0] )  !=
173 	 ( (char *)&c.switchbd - (char *)&c.speed ) )
174     {
175 	fprintf( stderr, "ERROR: config table size mixup. contact author\n" );
176 	exit(99);
177     }
178 
179     /* initialize a few things that can't be done statically */
180     c.init_chat.d.p = (void *) def_init_chat_seq;
181     c.init_chat.flags = C_PRESET;
182 
183     c.force_init_chat.d.p = (void *) def_force_init_chat_seq;
184     c.force_init_chat.flags = C_PRESET;
185 
186     c.answer_chat.d.p = (void *) def_answer_chat_seq;
187     c.answer_chat.flags = C_PRESET;
188 
189 
190     /* get command line arguments */
191 
192     /* some magic done by the command's name */
193     if ( strcmp( get_basename( argv[0] ), "getty" ) == 0 )
194     {
195 	conf_set_bool( &c.blocking, TRUE );
196 	conf_set_bool( &c.direct_line, TRUE );
197     }
198 
199     while ((opt = getopt(argc, argv, "c:x:s:rp:n:R:i:DC:FS:k:m:I:baV")) != EOF)
200     {
201 	switch (opt)
202 	{
203 	  case 'c':			/* check */
204 #ifdef USE_GETTYDEFS
205 	    verbose = TRUE;
206 	    dumpgettydefs(optarg);
207 	    exit(0);
208 #else
209 	    lprintf( L_FATAL, "gettydefs not supported\n");
210 	    exit_usage(2);
211 #endif
212 	  case 'k':			/* kbytes free on disk */
213 	    conf_set_int( &c.diskspace, atol(optarg) );
214 	    break;
215 	  case 'x':			/* log level */
216 	    conf_set_int( &c.debug, atoi(optarg) );
217 	    log_set_llevel( c_int(debug) );
218 	    break;
219 	  case 's':			/* port speed */
220 	    conf_set_int( &c.speed, atoi(optarg) );
221 	    break;
222 	  case 'r':			/* direct line (nullmodem) */
223 	    conf_set_int( &c.direct_line, TRUE );
224 	    break;
225 	  case 'p':			/* login prompt */
226 	    conf_set_string( &c.login_prompt, optarg );
227 	    break;
228 	  case 'n':			/* ring counter */
229 	    conf_set_int( &c.rings_wanted, atoi(optarg) );
230 	    break;
231 	  case 'R':			/* ringback timer */
232 	    conf_set_bool( &c.ringback, TRUE );
233 	    conf_set_int( &c.ringback_time, atoi(optarg) );
234 	    break;
235 	  case 'i':			/* use different issue file */
236 	    conf_set_string( &c.issue_file, optarg );
237 	    break;
238 	  case 'D':			/* switch off fax */
239 	    conf_set_bool( &c.data_only, TRUE );
240 	    break;
241 	  case 'F':			/* switch off data-mode (security!) */
242 	    conf_set_bool( &c.fax_only, TRUE );
243 	    break;
244 	  case 'C':			/* set modem mode (fax/data) */
245 	    conf_set_string( &c.modem_type, optarg );
246 	    break;
247 	  case 'S':			/* fax poll file to send */
248 	    conf_set_string( &c.fax_server_file, optarg );
249 	    break;
250 	  case 'I':			/* local station ID */
251 	    conf_set_string( &c.station_id, optarg);
252 	    break;
253 	  case 'b':			/* open port in blocking mode */
254 	    conf_set_bool( &c.blocking, TRUE );
255 	    break;
256 	  case 'a':			/* autobauding */
257 	    conf_set_bool( &c.autobauding, TRUE );
258 	    break;
259 	  case 'm':			/* modem init sequence */
260 	    c.init_chat.flags = C_OVERRIDE;
261 	    c.init_chat.d.p = conf_get_chat( optarg );
262 	    break;
263 	  case 'V':			/* show version number */
264 	    printf("\nmgetty+sendfax by Gert Doering\n%s\n\n",
265 		    mgetty_version);
266 	    printf("log file written to '");
267 	    printf(LOG_PATH, "<ttyX>");
268 #ifdef MGETTY_CONFIG
269             printf("'\nconfig file read from '%s",
270 			makepath( MGETTY_CONFIG, CONFDIR ));
271 #endif
272 	    printf("'\n\n");
273 	    exit(0);
274 	  case '?':
275 	    exit_usage(2);
276 	    break;
277 	}
278     }
279 
280     return NOERROR;
281 }
282 
283 
284 /* get mgetty configuration from file (if configured)
285  */
286 void mgetty_get_config _P1( (port), char * port )
287 {
288 #ifdef MGETTY_CONFIG
289     lprintf( L_NOISE, "reading configuration data for port '%s'", port );
290     get_config( makepath( MGETTY_CONFIG, CONFDIR ),
291 		(conf_data *)&c, "port", port );
292 #else
293     lprintf( L_NOISE, "not reading config file, not configured" );
294 #endif
295 
296     /* tell log subsystem about new log level */
297     log_set_llevel( c_int(debug) );
298 
299     /* tell getdisk.c about desired disk space (in kbytes) */
300     minfreespace = c_int(diskspace);
301 
302     /* sanity checks */
303     if ( tio_check_speed( c_int(speed) ) < 0 )
304     {
305 	lprintf( L_FATAL, "invalid port speed: %d", c_int(speed));
306 	exit_usage(2);
307     }
308     if ( c_isset(switchbd) && c_int(switchbd) != 0 && !c_bool(data_only) &&
309 	 tio_check_speed( c_int(switchbd) ) < 0 )
310     {
311 	lprintf( L_FATAL, "invalid fax reception switch speed: %d",
312 		 c_int(switchbd) );
313 	exit_usage(2);
314     }
315 
316     if ( c_int(rings_wanted) == 0 ) conf_set_int( &c.rings_wanted, 1 );
317 
318     if ( c_int(ringback_time) < 30 ) conf_set_int( &c.ringback_time, 30);
319 
320     if ( c_int(modem_check_time) >= 0 &&
321 	 c_int(modem_check_time) < 900 )
322     {
323 	lprintf( L_NOISE, "increasing modem_check_time to 900 sec." );
324 	conf_set_int( &c.modem_check_time, 900 );
325     }
326 
327     if ( c_isset(modem_quirks) )
328     {
329         lprintf( L_NOISE, "set modem_quirks: 0x%04x", c_int(modem_quirks));
330 	modem_quirks = c_int(modem_quirks);
331     }
332 }
333