+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: Missing subsystem name.",
+ filename, linenum);
+ for (i = 0; i < options->num_subsystems; i++)
+ if (strcmp(arg, options->subsystem_name[i]) == 0)
+ fatal("%s line %d: Subsystem '%s' already defined.",
+ filename, linenum, arg);
+ options->subsystem_name[options->num_subsystems] = xstrdup(arg);
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: Missing subsystem command.",
+ filename, linenum);
+ options->subsystem_command[options->num_subsystems] = xstrdup(arg);
+ options->num_subsystems++;
+ break;
+
+ case sMaxStartups:
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: Missing MaxStartups spec.",
+ filename, linenum);
+ if ((n = sscanf(arg, "%d:%d:%d",
+ &options->max_startups_begin,
+ &options->max_startups_rate,
+ &options->max_startups)) == 3) {
+ if (options->max_startups_begin >
+ options->max_startups ||
+ options->max_startups_rate > 100 ||
+ options->max_startups_rate < 1)
+ fatal("%s line %d: Illegal MaxStartups spec.",
+ filename, linenum);
+ } else if (n != 1)
+ fatal("%s line %d: Illegal MaxStartups spec.",
+ filename, linenum);
+ else
+ options->max_startups = options->max_startups_begin;
+ break;
+
+ case sBanner:
+ charptr = &options->banner;
+ goto parse_filename;
+ /*
+ * These options can contain %X options expanded at
+ * connect time, so that you can specify paths like:
+ *
+ * AuthorizedKeysFile /etc/ssh_keys/%u
+ */
+ case sAuthorizedKeysFile:
+ case sAuthorizedKeysFile2:
+ charptr = (opcode == sAuthorizedKeysFile ) ?
+ &options->authorized_keys_file :
+ &options->authorized_keys_file2;
+ goto parse_filename;
+
+ case sClientAliveInterval:
+ intptr = &options->client_alive_interval;
+ goto parse_time;
+
+ case sClientAliveCountMax:
+ intptr = &options->client_alive_count_max;
+ goto parse_int;
+
+ case sDeprecated:
+ log("%s line %d: Deprecated option %s",
+ filename, linenum, arg);
+ while (arg)
+ arg = strdelim(&cp);
+ break;
+
+ default:
+ fatal("%s line %d: Missing handler for opcode %s (%d)",
+ filename, linenum, arg, opcode);
+ }
+ if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
+ fatal("%s line %d: garbage at end of line; \"%.200s\".",
+ filename, linenum, arg);
+ return 0;
+}
+
+/* Reads the server configuration file. */
+
+void
+read_server_config(ServerOptions *options, const char *filename)
+{
+ int linenum, bad_options = 0;
+ char line[1024];
+ FILE *f;
+
+ f = fopen(filename, "r");
+ if (!f) {
+ perror(filename);
+ exit(1);
+ }
+ linenum = 0;
+ while (fgets(line, sizeof(line), f)) {
+ /* Update line number counter. */
+ linenum++;
+ if (process_server_config_line(options, line, filename, linenum) != 0)
+ bad_options++;