]> andersk Git - openssh.git/blame_incremental - servconf.c
- (djm) Clean up. Strip some unnecessary differences with OpenBSD's code,
[openssh.git] / servconf.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3 * All rights reserved
4 *
5 * As far as I am concerned, the code I have written for this software
6 * can be used freely for any purpose. Any derived versions of this
7 * software must be clearly marked as such, and if the derived work is
8 * incompatible with the protocol description in the RFC file, it must be
9 * called by a name other than "ssh" or "Secure Shell".
10 */
11
12#include "includes.h"
13RCSID("$OpenBSD: servconf.c,v 1.51 2000/09/07 20:27:53 deraadt Exp $");
14
15#include "ssh.h"
16#include "servconf.h"
17#include "xmalloc.h"
18#include "compat.h"
19
20/* add listen address */
21void add_listen_addr(ServerOptions *options, char *addr);
22
23/* Initializes the server options to their default values. */
24
25void
26initialize_server_options(ServerOptions *options)
27{
28 memset(options, 0, sizeof(*options));
29 options->num_ports = 0;
30 options->ports_from_cmdline = 0;
31 options->listen_addrs = NULL;
32 options->host_key_file = NULL;
33 options->host_dsa_key_file = NULL;
34 options->pid_file = NULL;
35 options->server_key_bits = -1;
36 options->login_grace_time = -1;
37 options->key_regeneration_time = -1;
38 options->permit_root_login = -1;
39 options->ignore_rhosts = -1;
40 options->ignore_user_known_hosts = -1;
41 options->print_motd = -1;
42 options->check_mail = -1;
43 options->x11_forwarding = -1;
44 options->x11_display_offset = -1;
45 options->xauth_location = NULL;
46 options->strict_modes = -1;
47 options->keepalives = -1;
48 options->log_facility = (SyslogFacility) - 1;
49 options->log_level = (LogLevel) - 1;
50 options->rhosts_authentication = -1;
51 options->rhosts_rsa_authentication = -1;
52 options->rsa_authentication = -1;
53 options->dsa_authentication = -1;
54#ifdef KRB4
55 options->kerberos_authentication = -1;
56 options->kerberos_or_local_passwd = -1;
57 options->kerberos_ticket_cleanup = -1;
58#endif
59#ifdef AFS
60 options->kerberos_tgt_passing = -1;
61 options->afs_token_passing = -1;
62#endif
63 options->password_authentication = -1;
64#ifdef SKEY
65 options->skey_authentication = -1;
66#endif
67 options->permit_empty_passwd = -1;
68 options->use_login = -1;
69 options->num_allow_users = 0;
70 options->num_deny_users = 0;
71 options->num_allow_groups = 0;
72 options->num_deny_groups = 0;
73 options->ciphers = NULL;
74 options->protocol = SSH_PROTO_UNKNOWN;
75 options->gateway_ports = -1;
76 options->num_subsystems = 0;
77 options->max_startups_begin = -1;
78 options->max_startups_rate = -1;
79 options->max_startups = -1;
80}
81
82void
83fill_default_server_options(ServerOptions *options)
84{
85 if (options->num_ports == 0)
86 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
87 if (options->listen_addrs == NULL)
88 add_listen_addr(options, NULL);
89 if (options->host_key_file == NULL)
90 options->host_key_file = HOST_KEY_FILE;
91 if (options->host_dsa_key_file == NULL)
92 options->host_dsa_key_file = HOST_DSA_KEY_FILE;
93 if (options->pid_file == NULL)
94 options->pid_file = SSH_DAEMON_PID_FILE;
95 if (options->server_key_bits == -1)
96 options->server_key_bits = 768;
97 if (options->login_grace_time == -1)
98 options->login_grace_time = 600;
99 if (options->key_regeneration_time == -1)
100 options->key_regeneration_time = 3600;
101 if (options->permit_root_login == -1)
102 options->permit_root_login = 1; /* yes */
103 if (options->ignore_rhosts == -1)
104 options->ignore_rhosts = 1;
105 if (options->ignore_user_known_hosts == -1)
106 options->ignore_user_known_hosts = 0;
107 if (options->check_mail == -1)
108 options->check_mail = 0;
109 if (options->print_motd == -1)
110 options->print_motd = 1;
111 if (options->x11_forwarding == -1)
112 options->x11_forwarding = 0;
113 if (options->x11_display_offset == -1)
114 options->x11_display_offset = 10;
115#ifdef XAUTH_PATH
116 if (options->xauth_location == NULL)
117 options->xauth_location = XAUTH_PATH;
118#endif /* XAUTH_PATH */
119 if (options->strict_modes == -1)
120 options->strict_modes = 1;
121 if (options->keepalives == -1)
122 options->keepalives = 1;
123 if (options->log_facility == (SyslogFacility) (-1))
124 options->log_facility = SYSLOG_FACILITY_AUTH;
125 if (options->log_level == (LogLevel) (-1))
126 options->log_level = SYSLOG_LEVEL_INFO;
127 if (options->rhosts_authentication == -1)
128 options->rhosts_authentication = 0;
129 if (options->rhosts_rsa_authentication == -1)
130 options->rhosts_rsa_authentication = 0;
131 if (options->rsa_authentication == -1)
132 options->rsa_authentication = 1;
133 if (options->dsa_authentication == -1)
134 options->dsa_authentication = 1;
135#ifdef KRB4
136 if (options->kerberos_authentication == -1)
137 options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
138 if (options->kerberos_or_local_passwd == -1)
139 options->kerberos_or_local_passwd = 1;
140 if (options->kerberos_ticket_cleanup == -1)
141 options->kerberos_ticket_cleanup = 1;
142#endif /* KRB4 */
143#ifdef AFS
144 if (options->kerberos_tgt_passing == -1)
145 options->kerberos_tgt_passing = 0;
146 if (options->afs_token_passing == -1)
147 options->afs_token_passing = k_hasafs();
148#endif /* AFS */
149 if (options->password_authentication == -1)
150 options->password_authentication = 1;
151#ifdef SKEY
152 if (options->skey_authentication == -1)
153 options->skey_authentication = 1;
154#endif
155 if (options->permit_empty_passwd == -1)
156 options->permit_empty_passwd = 0;
157 if (options->use_login == -1)
158 options->use_login = 0;
159 if (options->protocol == SSH_PROTO_UNKNOWN)
160 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
161 if (options->gateway_ports == -1)
162 options->gateway_ports = 0;
163 if (options->max_startups == -1)
164 options->max_startups = 10;
165 if (options->max_startups_rate == -1)
166 options->max_startups_rate = 100; /* 100% */
167 if (options->max_startups_begin == -1)
168 options->max_startups_begin = options->max_startups;
169}
170
171/* Keyword tokens. */
172typedef enum {
173 sBadOption, /* == unknown option */
174 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
175 sPermitRootLogin, sLogFacility, sLogLevel,
176 sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
177#ifdef KRB4
178 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
179#endif
180#ifdef AFS
181 sKerberosTgtPassing, sAFSTokenPassing,
182#endif
183#ifdef SKEY
184 sSkeyAuthentication,
185#endif
186 sPasswordAuthentication, sListenAddress,
187 sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
188 sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
189 sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
190 sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
191 sGatewayPorts, sDSAAuthentication, sXAuthLocation, sSubsystem, sMaxStartups
192} ServerOpCodes;
193
194/* Textual representation of the tokens. */
195static struct {
196 const char *name;
197 ServerOpCodes opcode;
198} keywords[] = {
199 { "port", sPort },
200 { "hostkey", sHostKeyFile },
201 { "hostdsakey", sHostDSAKeyFile },
202 { "pidfile", sPidFile },
203 { "serverkeybits", sServerKeyBits },
204 { "logingracetime", sLoginGraceTime },
205 { "keyregenerationinterval", sKeyRegenerationTime },
206 { "permitrootlogin", sPermitRootLogin },
207 { "syslogfacility", sLogFacility },
208 { "loglevel", sLogLevel },
209 { "rhostsauthentication", sRhostsAuthentication },
210 { "rhostsrsaauthentication", sRhostsRSAAuthentication },
211 { "rsaauthentication", sRSAAuthentication },
212 { "dsaauthentication", sDSAAuthentication },
213#ifdef KRB4
214 { "kerberosauthentication", sKerberosAuthentication },
215 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
216 { "kerberosticketcleanup", sKerberosTicketCleanup },
217#endif
218#ifdef AFS
219 { "kerberostgtpassing", sKerberosTgtPassing },
220 { "afstokenpassing", sAFSTokenPassing },
221#endif
222 { "passwordauthentication", sPasswordAuthentication },
223#ifdef SKEY
224 { "skeyauthentication", sSkeyAuthentication },
225#endif
226 { "checkmail", sCheckMail },
227 { "listenaddress", sListenAddress },
228 { "printmotd", sPrintMotd },
229 { "ignorerhosts", sIgnoreRhosts },
230 { "ignoreuserknownhosts", sIgnoreUserKnownHosts },
231 { "x11forwarding", sX11Forwarding },
232 { "x11displayoffset", sX11DisplayOffset },
233 { "xauthlocation", sXAuthLocation },
234 { "strictmodes", sStrictModes },
235 { "permitemptypasswords", sEmptyPasswd },
236 { "uselogin", sUseLogin },
237 { "randomseed", sRandomSeedFile },
238 { "keepalive", sKeepAlives },
239 { "allowusers", sAllowUsers },
240 { "denyusers", sDenyUsers },
241 { "allowgroups", sAllowGroups },
242 { "denygroups", sDenyGroups },
243 { "ciphers", sCiphers },
244 { "protocol", sProtocol },
245 { "gatewayports", sGatewayPorts },
246 { "subsystem", sSubsystem },
247 { "maxstartups", sMaxStartups },
248 { NULL, 0 }
249};
250
251/*
252 * Returns the number of the token pointed to by cp of length len. Never
253 * returns if the token is not known.
254 */
255
256static ServerOpCodes
257parse_token(const char *cp, const char *filename,
258 int linenum)
259{
260 unsigned int i;
261
262 for (i = 0; keywords[i].name; i++)
263 if (strcasecmp(cp, keywords[i].name) == 0)
264 return keywords[i].opcode;
265
266 fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
267 filename, linenum, cp);
268 return sBadOption;
269}
270
271/*
272 * add listen address
273 */
274void
275add_listen_addr(ServerOptions *options, char *addr)
276{
277 extern int IPv4or6;
278 struct addrinfo hints, *ai, *aitop;
279 char strport[NI_MAXSERV];
280 int gaierr;
281 int i;
282
283 if (options->num_ports == 0)
284 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
285 for (i = 0; i < options->num_ports; i++) {
286 memset(&hints, 0, sizeof(hints));
287 hints.ai_family = IPv4or6;
288 hints.ai_socktype = SOCK_STREAM;
289 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
290 snprintf(strport, sizeof strport, "%d", options->ports[i]);
291 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
292 fatal("bad addr or host: %s (%s)\n",
293 addr ? addr : "<NULL>",
294 gai_strerror(gaierr));
295 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
296 ;
297 ai->ai_next = options->listen_addrs;
298 options->listen_addrs = aitop;
299 }
300}
301
302/* Reads the server configuration file. */
303
304void
305read_server_config(ServerOptions *options, const char *filename)
306{
307 FILE *f;
308 char line[1024];
309 char *cp, **charptr, *arg;
310 int linenum, *intptr, value;
311 int bad_options = 0;
312 ServerOpCodes opcode;
313 int i;
314
315 f = fopen(filename, "r");
316 if (!f) {
317 perror(filename);
318 exit(1);
319 }
320 linenum = 0;
321 while (fgets(line, sizeof(line), f)) {
322 linenum++;
323 cp = line;
324 arg = strdelim(&cp);
325 /* Ignore leading whitespace */
326 if (*arg == '\0')
327 arg = strdelim(&cp);
328 if (!*arg || *arg == '#')
329 continue;
330 opcode = parse_token(arg, filename, linenum);
331 switch (opcode) {
332 case sBadOption:
333 bad_options++;
334 continue;
335 case sPort:
336 /* ignore ports from configfile if cmdline specifies ports */
337 if (options->ports_from_cmdline)
338 continue;
339 if (options->listen_addrs != NULL)
340 fatal("%s line %d: ports must be specified before "
341 "ListenAdress.\n", filename, linenum);
342 if (options->num_ports >= MAX_PORTS)
343 fatal("%s line %d: too many ports.\n",
344 filename, linenum);
345 arg = strdelim(&cp);
346 if (!arg || *arg == '\0')
347 fatal("%s line %d: missing port number.\n",
348 filename, linenum);
349 options->ports[options->num_ports++] = atoi(arg);
350 break;
351
352 case sServerKeyBits:
353 intptr = &options->server_key_bits;
354parse_int:
355 arg = strdelim(&cp);
356 if (!arg || *arg == '\0') {
357 fprintf(stderr, "%s line %d: missing integer value.\n",
358 filename, linenum);
359 exit(1);
360 }
361 value = atoi(arg);
362 if (*intptr == -1)
363 *intptr = value;
364 break;
365
366 case sLoginGraceTime:
367 intptr = &options->login_grace_time;
368 goto parse_int;
369
370 case sKeyRegenerationTime:
371 intptr = &options->key_regeneration_time;
372 goto parse_int;
373
374 case sListenAddress:
375 arg = strdelim(&cp);
376 if (!arg || *arg == '\0')
377 fatal("%s line %d: missing inet addr.\n",
378 filename, linenum);
379 add_listen_addr(options, arg);
380 break;
381
382 case sHostKeyFile:
383 case sHostDSAKeyFile:
384 charptr = (opcode == sHostKeyFile ) ?
385 &options->host_key_file : &options->host_dsa_key_file;
386parse_filename:
387 arg = strdelim(&cp);
388 if (!arg || *arg == '\0') {
389 fprintf(stderr, "%s line %d: missing file name.\n",
390 filename, linenum);
391 exit(1);
392 }
393 if (*charptr == NULL)
394 *charptr = tilde_expand_filename(arg, getuid());
395 break;
396
397 case sPidFile:
398 charptr = &options->pid_file;
399 goto parse_filename;
400
401 case sRandomSeedFile:
402 fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
403 filename, linenum);
404 arg = strdelim(&cp);
405 break;
406
407 case sPermitRootLogin:
408 intptr = &options->permit_root_login;
409 arg = strdelim(&cp);
410 if (!arg || *arg == '\0') {
411 fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n",
412 filename, linenum);
413 exit(1);
414 }
415 if (strcmp(arg, "without-password") == 0)
416 value = 2;
417 else if (strcmp(arg, "yes") == 0)
418 value = 1;
419 else if (strcmp(arg, "no") == 0)
420 value = 0;
421 else {
422 fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
423 filename, linenum, arg);
424 exit(1);
425 }
426 if (*intptr == -1)
427 *intptr = value;
428 break;
429
430 case sIgnoreRhosts:
431 intptr = &options->ignore_rhosts;
432parse_flag:
433 arg = strdelim(&cp);
434 if (!arg || *arg == '\0') {
435 fprintf(stderr, "%s line %d: missing yes/no argument.\n",
436 filename, linenum);
437 exit(1);
438 }
439 if (strcmp(arg, "yes") == 0)
440 value = 1;
441 else if (strcmp(arg, "no") == 0)
442 value = 0;
443 else {
444 fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
445 filename, linenum, arg);
446 exit(1);
447 }
448 if (*intptr == -1)
449 *intptr = value;
450 break;
451
452 case sIgnoreUserKnownHosts:
453 intptr = &options->ignore_user_known_hosts;
454 goto parse_flag;
455
456 case sRhostsAuthentication:
457 intptr = &options->rhosts_authentication;
458 goto parse_flag;
459
460 case sRhostsRSAAuthentication:
461 intptr = &options->rhosts_rsa_authentication;
462 goto parse_flag;
463
464 case sRSAAuthentication:
465 intptr = &options->rsa_authentication;
466 goto parse_flag;
467
468 case sDSAAuthentication:
469 intptr = &options->dsa_authentication;
470 goto parse_flag;
471
472#ifdef KRB4
473 case sKerberosAuthentication:
474 intptr = &options->kerberos_authentication;
475 goto parse_flag;
476
477 case sKerberosOrLocalPasswd:
478 intptr = &options->kerberos_or_local_passwd;
479 goto parse_flag;
480
481 case sKerberosTicketCleanup:
482 intptr = &options->kerberos_ticket_cleanup;
483 goto parse_flag;
484#endif
485
486#ifdef AFS
487 case sKerberosTgtPassing:
488 intptr = &options->kerberos_tgt_passing;
489 goto parse_flag;
490
491 case sAFSTokenPassing:
492 intptr = &options->afs_token_passing;
493 goto parse_flag;
494#endif
495
496 case sPasswordAuthentication:
497 intptr = &options->password_authentication;
498 goto parse_flag;
499
500 case sCheckMail:
501 intptr = &options->check_mail;
502 goto parse_flag;
503
504#ifdef SKEY
505 case sSkeyAuthentication:
506 intptr = &options->skey_authentication;
507 goto parse_flag;
508#endif
509
510 case sPrintMotd:
511 intptr = &options->print_motd;
512 goto parse_flag;
513
514 case sX11Forwarding:
515 intptr = &options->x11_forwarding;
516 goto parse_flag;
517
518 case sX11DisplayOffset:
519 intptr = &options->x11_display_offset;
520 goto parse_int;
521
522 case sXAuthLocation:
523 charptr = &options->xauth_location;
524 goto parse_filename;
525
526 case sStrictModes:
527 intptr = &options->strict_modes;
528 goto parse_flag;
529
530 case sKeepAlives:
531 intptr = &options->keepalives;
532 goto parse_flag;
533
534 case sEmptyPasswd:
535 intptr = &options->permit_empty_passwd;
536 goto parse_flag;
537
538 case sUseLogin:
539 intptr = &options->use_login;
540 goto parse_flag;
541
542 case sGatewayPorts:
543 intptr = &options->gateway_ports;
544 goto parse_flag;
545
546 case sLogFacility:
547 intptr = (int *) &options->log_facility;
548 arg = strdelim(&cp);
549 value = log_facility_number(arg);
550 if (value == (SyslogFacility) - 1)
551 fatal("%.200s line %d: unsupported log facility '%s'\n",
552 filename, linenum, arg ? arg : "<NONE>");
553 if (*intptr == -1)
554 *intptr = (SyslogFacility) value;
555 break;
556
557 case sLogLevel:
558 intptr = (int *) &options->log_level;
559 arg = strdelim(&cp);
560 value = log_level_number(arg);
561 if (value == (LogLevel) - 1)
562 fatal("%.200s line %d: unsupported log level '%s'\n",
563 filename, linenum, arg ? arg : "<NONE>");
564 if (*intptr == -1)
565 *intptr = (LogLevel) value;
566 break;
567
568 case sAllowUsers:
569 while ((arg = strdelim(&cp)) && *arg != '\0') {
570 if (options->num_allow_users >= MAX_ALLOW_USERS)
571 fatal("%s line %d: too many allow users.\n",
572 filename, linenum);
573 options->allow_users[options->num_allow_users++] = xstrdup(arg);
574 }
575 break;
576
577 case sDenyUsers:
578 while ((arg = strdelim(&cp)) && *arg != '\0') {
579 if (options->num_deny_users >= MAX_DENY_USERS)
580 fatal( "%s line %d: too many deny users.\n",
581 filename, linenum);
582 options->deny_users[options->num_deny_users++] = xstrdup(arg);
583 }
584 break;
585
586 case sAllowGroups:
587 while ((arg = strdelim(&cp)) && *arg != '\0') {
588 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
589 fatal("%s line %d: too many allow groups.\n",
590 filename, linenum);
591 options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
592 }
593 break;
594
595 case sDenyGroups:
596 while ((arg = strdelim(&cp)) && *arg != '\0') {
597 if (options->num_deny_groups >= MAX_DENY_GROUPS)
598 fatal("%s line %d: too many deny groups.\n",
599 filename, linenum);
600 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
601 }
602 break;
603
604 case sCiphers:
605 arg = strdelim(&cp);
606 if (!arg || *arg == '\0')
607 fatal("%s line %d: Missing argument.", filename, linenum);
608 if (!ciphers_valid(arg))
609 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
610 filename, linenum, arg ? arg : "<NONE>");
611 if (options->ciphers == NULL)
612 options->ciphers = xstrdup(arg);
613 break;
614
615 case sProtocol:
616 intptr = &options->protocol;
617 arg = strdelim(&cp);
618 if (!arg || *arg == '\0')
619 fatal("%s line %d: Missing argument.", filename, linenum);
620 value = proto_spec(arg);
621 if (value == SSH_PROTO_UNKNOWN)
622 fatal("%s line %d: Bad protocol spec '%s'.",
623 filename, linenum, arg ? arg : "<NONE>");
624 if (*intptr == SSH_PROTO_UNKNOWN)
625 *intptr = value;
626 break;
627
628 case sSubsystem:
629 if(options->num_subsystems >= MAX_SUBSYSTEMS) {
630 fatal("%s line %d: too many subsystems defined.",
631 filename, linenum);
632 }
633 arg = strdelim(&cp);
634 if (!arg || *arg == '\0')
635 fatal("%s line %d: Missing subsystem name.",
636 filename, linenum);
637 for (i = 0; i < options->num_subsystems; i++)
638 if(strcmp(arg, options->subsystem_name[i]) == 0)
639 fatal("%s line %d: Subsystem '%s' already defined.",
640 filename, linenum, arg);
641 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
642 arg = strdelim(&cp);
643 if (!arg || *arg == '\0')
644 fatal("%s line %d: Missing subsystem command.",
645 filename, linenum);
646 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
647 options->num_subsystems++;
648 break;
649
650 case sMaxStartups:
651 arg = strdelim(&cp);
652 if (!arg || *arg == '\0')
653 fatal("%s line %d: Missing MaxStartups spec.",
654 filename, linenum);
655 if (sscanf(arg, "%d:%d:%d",
656 &options->max_startups_begin,
657 &options->max_startups_rate,
658 &options->max_startups) == 3) {
659 if (options->max_startups_begin >
660 options->max_startups ||
661 options->max_startups_rate > 100 ||
662 options->max_startups_rate < 1)
663 fatal("%s line %d: Illegal MaxStartups spec.",
664 filename, linenum);
665 break;
666 }
667 intptr = &options->max_startups;
668 goto parse_int;
669
670 default:
671 fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n",
672 filename, linenum, arg, opcode);
673 exit(1);
674 }
675 if ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
676 fprintf(stderr,
677 "%s line %d: garbage at end of line; \"%.200s\".\n",
678 filename, linenum, arg);
679 exit(1);
680 }
681 }
682 fclose(f);
683 if (bad_options > 0) {
684 fprintf(stderr, "%s: terminating, %d bad configuration options\n",
685 filename, bad_options);
686 exit(1);
687 }
688}
This page took 0.047116 seconds and 5 git commands to generate.