]> andersk Git - openssh.git/blame - readconf.c
- Merged more OpenBSD CVS changes:
[openssh.git] / readconf.c
CommitLineData
8efc0c15 1/*
2
3readconf.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sat Apr 22 00:03:10 1995 ylo
11
12Functions for reading the configuration files.
13
14*/
15
16#include "includes.h"
17RCSID("$Id$");
18
19#include "ssh.h"
20#include "cipher.h"
21#include "readconf.h"
22#include "xmalloc.h"
23
24/* Format of the configuration file:
25
26 # Configuration data is parsed as follows:
27 # 1. command line options
28 # 2. user-specific file
29 # 3. system-wide file
30 # Any configuration value is only changed the first time it is set.
31 # Thus, host-specific definitions should be at the beginning of the
32 # configuration file, and defaults at the end.
33
34 # Host-specific declarations. These may override anything above. A single
35 # host may match multiple declarations; these are processed in the order
36 # that they are given in.
37
38 Host *.ngs.fi ngs.fi
39 FallBackToRsh no
40
41 Host fake.com
42 HostName another.host.name.real.org
43 User blaah
44 Port 34289
45 ForwardX11 no
46 ForwardAgent no
47
48 Host books.com
49 RemoteForward 9999 shadows.cs.hut.fi:9999
50 Cipher 3des
51
52 Host fascist.blob.com
53 Port 23123
54 User tylonen
55 RhostsAuthentication no
56 PasswordAuthentication no
57
58 Host puukko.hut.fi
59 User t35124p
60 ProxyCommand ssh-proxy %h %p
61
62 Host *.fr
63 UseRsh yes
64
65 Host *.su
66 Cipher none
67 PasswordAuthentication no
68
69 # Defaults for various options
70 Host *
71 ForwardAgent no
72 ForwardX11 yes
73 RhostsAuthentication yes
74 PasswordAuthentication yes
75 RSAAuthentication yes
76 RhostsRSAAuthentication yes
77 FallBackToRsh no
78 UseRsh no
79 StrictHostKeyChecking yes
80 KeepAlives no
81 IdentityFile ~/.ssh/identity
82 Port 22
83 EscapeChar ~
84
85*/
86
87/* Keyword tokens. */
88
89typedef enum
90{
91 oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
92 oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
93#ifdef KRB4
94 oKerberosAuthentication,
95#endif /* KRB4 */
96#ifdef AFS
97 oKerberosTgtPassing, oAFSTokenPassing,
98#endif
99 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
100 oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
101 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
102 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
103 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
6a17f9c2 104 oUsePrivilegedPort, oLogLevel
8efc0c15 105} OpCodes;
106
107/* Textual representations of the tokens. */
108
109static struct
110{
111 const char *name;
112 OpCodes opcode;
113} keywords[] =
114{
115 { "forwardagent", oForwardAgent },
116 { "forwardx11", oForwardX11 },
117 { "gatewayports", oGatewayPorts },
118 { "useprivilegedport", oUsePrivilegedPort },
119 { "rhostsauthentication", oRhostsAuthentication },
120 { "passwordauthentication", oPasswordAuthentication },
121 { "rsaauthentication", oRSAAuthentication },
122#ifdef KRB4
123 { "kerberosauthentication", oKerberosAuthentication },
124#endif /* KRB4 */
125#ifdef AFS
126 { "kerberostgtpassing", oKerberosTgtPassing },
127 { "afstokenpassing", oAFSTokenPassing },
128#endif
129 { "fallbacktorsh", oFallBackToRsh },
130 { "usersh", oUseRsh },
131 { "identityfile", oIdentityFile },
132 { "hostname", oHostName },
133 { "proxycommand", oProxyCommand },
134 { "port", oPort },
135 { "cipher", oCipher },
136 { "remoteforward", oRemoteForward },
137 { "localforward", oLocalForward },
138 { "user", oUser },
139 { "host", oHost },
140 { "escapechar", oEscapeChar },
141 { "rhostsrsaauthentication", oRhostsRSAAuthentication },
142 { "globalknownhostsfile", oGlobalKnownHostsFile },
143 { "userknownhostsfile", oUserKnownHostsFile },
144 { "connectionattempts", oConnectionAttempts },
145 { "batchmode", oBatchMode },
146 { "checkhostip", oCheckHostIP },
147 { "stricthostkeychecking", oStrictHostKeyChecking },
148 { "compression", oCompression },
149 { "compressionlevel", oCompressionLevel },
150 { "keepalive", oKeepAlives },
151 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
152 { "tisauthentication", oTISAuthentication },
6a17f9c2 153 { "loglevel", oLogLevel },
154 { NULL, 0 }
155};
156
157/* textual representation of log-levels */
158
159static struct
160{
161 const char *name;
162 LogLevel level;
163} log_levels[] =
164{
165 { "QUIET", SYSLOG_LEVEL_QUIET },
166 { "FATAL", SYSLOG_LEVEL_FATAL },
167 { "ERROR", SYSLOG_LEVEL_ERROR },
168 { "INFO", SYSLOG_LEVEL_INFO },
169 { "CHAT", SYSLOG_LEVEL_CHAT },
170 { "DEBUG", SYSLOG_LEVEL_DEBUG },
8efc0c15 171 { NULL, 0 }
172};
173
174/* Characters considered whitespace in strtok calls. */
175#define WHITESPACE " \t\r\n"
176
177
178/* Adds a local TCP/IP port forward to options. Never returns if there
179 is an error. */
180
181void add_local_forward(Options *options, int port, const char *host,
182 int host_port)
183{
184 Forward *fwd;
185 extern uid_t original_real_uid;
186 if ((port & 0xffff) != port)
187 fatal("Requested forwarding of nonexistent port %d.", port);
188 if (port < IPPORT_RESERVED && original_real_uid != 0)
189 fatal("Privileged ports can only be forwarded by root.\n");
190 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
191 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
192 fwd = &options->local_forwards[options->num_local_forwards++];
193 fwd->port = port;
194 fwd->host = xstrdup(host);
195 fwd->host_port = host_port;
196}
197
198/* Adds a remote TCP/IP port forward to options. Never returns if there
199 is an error. */
200
201void add_remote_forward(Options *options, int port, const char *host,
202 int host_port)
203{
204 Forward *fwd;
205 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
206 fatal("Too many remote forwards (max %d).",
207 SSH_MAX_FORWARDS_PER_DIRECTION);
208 fwd = &options->remote_forwards[options->num_remote_forwards++];
209 fwd->port = port;
210 fwd->host = xstrdup(host);
211 fwd->host_port = host_port;
212}
213
214/* Returns the number of the token pointed to by cp of length len.
215 Never returns if the token is not known. */
216
217static OpCodes parse_token(const char *cp, const char *filename, int linenum)
218{
219 unsigned int i;
220
221 for (i = 0; keywords[i].name; i++)
222 if (strcmp(cp, keywords[i].name) == 0)
223 return keywords[i].opcode;
224
225 fatal("%.200s line %d: Bad configuration option.",
226 filename, linenum);
227 /*NOTREACHED*/
228 return 0;
229}
230
231/* Processes a single option line as used in the configuration files.
232 This only sets those values that have not already been set. */
233
234void process_config_line(Options *options, const char *host,
235 char *line, const char *filename, int linenum,
236 int *activep)
237{
238 char buf[256], *cp, *string, **charptr;
6a17f9c2 239 int opcode, *intptr, value, fwd_port, fwd_host_port, i;
8efc0c15 240
241 /* Skip leading whitespace. */
242 cp = line + strspn(line, WHITESPACE);
243 if (!*cp || *cp == '\n' || *cp == '#')
244 return;
245
246 /* Get the keyword. (Each line is supposed to begin with a keyword). */
247 cp = strtok(cp, WHITESPACE);
248 {
249 char *t = cp;
250 for (; *t != 0; t++)
251 if ('A' <= *t && *t <= 'Z')
252 *t = *t - 'A' + 'a'; /* tolower */
253
254 }
255 opcode = parse_token(cp, filename, linenum);
256
257 switch (opcode)
258 {
259
260 case oForwardAgent:
261 intptr = &options->forward_agent;
262 parse_flag:
263 cp = strtok(NULL, WHITESPACE);
264 if (!cp)
265 fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
266 value = 0; /* To avoid compiler warning... */
267 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
268 value = 1;
269 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
270 value = 0;
271 else
272 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
273 if (*activep && *intptr == -1)
274 *intptr = value;
275 break;
276
277 case oForwardX11:
278 intptr = &options->forward_x11;
279 goto parse_flag;
280
281 case oGatewayPorts:
282 intptr = &options->gateway_ports;
283 goto parse_flag;
284
285 case oUsePrivilegedPort:
286 intptr = &options->use_privileged_port;
287 goto parse_flag;
288
289 case oRhostsAuthentication:
290 intptr = &options->rhosts_authentication;
291 goto parse_flag;
292
293 case oPasswordAuthentication:
294 intptr = &options->password_authentication;
295 goto parse_flag;
296
297 case oRSAAuthentication:
298 intptr = &options->rsa_authentication;
299 goto parse_flag;
300
301 case oRhostsRSAAuthentication:
302 intptr = &options->rhosts_rsa_authentication;
303 goto parse_flag;
304
305#ifdef KRB4
306 case oKerberosAuthentication:
307 intptr = &options->kerberos_authentication;
308 goto parse_flag;
309#endif /* KRB4 */
310
311#ifdef AFS
312 case oKerberosTgtPassing:
313 intptr = &options->kerberos_tgt_passing;
314 goto parse_flag;
315
316 case oAFSTokenPassing:
317 intptr = &options->afs_token_passing;
318 goto parse_flag;
319#endif
320
321 case oFallBackToRsh:
322 intptr = &options->fallback_to_rsh;
323 goto parse_flag;
324
325 case oUseRsh:
326 intptr = &options->use_rsh;
327 goto parse_flag;
328
329 case oBatchMode:
330 intptr = &options->batch_mode;
331 goto parse_flag;
332
333 case oCheckHostIP:
334 intptr = &options->check_host_ip;
335 goto parse_flag;
336
337 case oStrictHostKeyChecking:
338 intptr = &options->strict_host_key_checking;
339 cp = strtok(NULL, WHITESPACE);
340 if (!cp)
341 fatal("%.200s line %d: Missing yes/no argument.",
342 filename, linenum);
343 value = 0; /* To avoid compiler warning... */
344 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
345 value = 1;
346 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
347 value = 0;
348 else if (strcmp(cp, "ask") == 0)
349 value = 2;
350 else
351 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
352 if (*activep && *intptr == -1)
353 *intptr = value;
354 break;
355
356 case oCompression:
357 intptr = &options->compression;
358 goto parse_flag;
359
360 case oKeepAlives:
361 intptr = &options->keepalives;
362 goto parse_flag;
363
364 case oNumberOfPasswordPrompts:
365 intptr = &options->number_of_password_prompts;
366 goto parse_int;
367
368 case oTISAuthentication:
369 cp = strtok(NULL, WHITESPACE);
370 if (cp != 0 && (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0))
371 fprintf(stderr,
372 "%.99s line %d: Warning, TIS is not supported.\n",
373 filename,
374 linenum);
375 break;
376
377 case oCompressionLevel:
378 intptr = &options->compression_level;
379 goto parse_int;
380
381 case oIdentityFile:
382 cp = strtok(NULL, WHITESPACE);
383 if (!cp)
384 fatal("%.200s line %d: Missing argument.", filename, linenum);
385 if (*activep)
386 {
387 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
388 fatal("%.200s line %d: Too many identity files specified (max %d).",
389 filename, linenum, SSH_MAX_IDENTITY_FILES);
390 options->identity_files[options->num_identity_files++] = xstrdup(cp);
391 }
392 break;
393
394 case oUser:
395 charptr = &options->user;
396 parse_string:
397 cp = strtok(NULL, WHITESPACE);
398 if (!cp)
399 fatal("%.200s line %d: Missing argument.", filename, linenum);
400 if (*activep && *charptr == NULL)
401 *charptr = xstrdup(cp);
402 break;
403
404 case oGlobalKnownHostsFile:
405 charptr = &options->system_hostfile;
406 goto parse_string;
407
408 case oUserKnownHostsFile:
409 charptr = &options->user_hostfile;
410 goto parse_string;
411
412 case oHostName:
413 charptr = &options->hostname;
414 goto parse_string;
415
416 case oProxyCommand:
417 charptr = &options->proxy_command;
418 string = xstrdup("");
419 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
420 {
421 string = xrealloc(string, strlen(string) + strlen(cp) + 2);
422 strcat(string, " ");
423 strcat(string, cp);
424 }
425 if (*activep && *charptr == NULL)
426 *charptr = string;
427 else
428 xfree(string);
429 return;
430
431 case oPort:
432 intptr = &options->port;
433 parse_int:
434 cp = strtok(NULL, WHITESPACE);
435 if (!cp)
436 fatal("%.200s line %d: Missing argument.", filename, linenum);
437 if (cp[0] < '0' || cp[0] > '9')
438 fatal("%.200s line %d: Bad number.", filename, linenum);
439#if 0
440 value = atoi(cp);
441#else
442 {
443 char *ptr;
444 value = strtol(cp, &ptr, 0); /* Octal, decimal, or hex format? */
445 if (cp == ptr)
446 fatal("%.200s line %d: Bad number.", filename, linenum);
447 }
448#endif
449 if (*activep && *intptr == -1)
450 *intptr = value;
451 break;
452
453 case oConnectionAttempts:
454 intptr = &options->connection_attempts;
455 goto parse_int;
456
457 case oCipher:
458 intptr = &options->cipher;
459 cp = strtok(NULL, WHITESPACE);
460 value = cipher_number(cp);
461 if (value == -1)
462 fatal("%.200s line %d: Bad cipher.", filename, linenum);
463 if (*activep && *intptr == -1)
464 *intptr = value;
465 break;
6a17f9c2 466
467 case oLogLevel:
468 cp = strtok(NULL, WHITESPACE);
469 if (!cp)
470 {
471 fprintf(stderr, "%s line %d: missing level name.\n",
472 filename, linenum);
473 exit(1);
474 }
475 for (i = 0; log_levels[i].name; i++)
476 if (strcasecmp(log_levels[i].name, cp) == 0)
477 break;
478 if (!log_levels[i].name)
479 {
480 fprintf(stderr, "%s line %d: unsupported log level %s\n",
481 filename, linenum, cp);
482 exit(1);
483 }
484 if (options->log_level == (LogLevel)(-1))
485 options->log_level = log_levels[i].level;
486 break;
8efc0c15 487
488 case oRemoteForward:
489 cp = strtok(NULL, WHITESPACE);
490 if (!cp)
491 fatal("%.200s line %d: Missing argument.", filename, linenum);
492 if (cp[0] < '0' || cp[0] > '9')
493 fatal("%.200s line %d: Badly formatted port number.",
494 filename, linenum);
495 fwd_port = atoi(cp);
496 cp = strtok(NULL, WHITESPACE);
497 if (!cp)
498 fatal("%.200s line %d: Missing second argument.",
499 filename, linenum);
500 if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
501 fatal("%.200s line %d: Badly formatted host:port.",
502 filename, linenum);
503 if (*activep)
504 add_remote_forward(options, fwd_port, buf, fwd_host_port);
505 break;
506
507 case oLocalForward:
508 cp = strtok(NULL, WHITESPACE);
509 if (!cp)
510 fatal("%.200s line %d: Missing argument.", filename, linenum);
511 if (cp[0] < '0' || cp[0] > '9')
512 fatal("%.200s line %d: Badly formatted port number.",
513 filename, linenum);
514 fwd_port = atoi(cp);
515 cp = strtok(NULL, WHITESPACE);
516 if (!cp)
517 fatal("%.200s line %d: Missing second argument.",
518 filename, linenum);
519 if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
520 fatal("%.200s line %d: Badly formatted host:port.",
521 filename, linenum);
522 if (*activep)
523 add_local_forward(options, fwd_port, buf, fwd_host_port);
524 break;
525
526 case oHost:
527 *activep = 0;
528 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
529 if (match_pattern(host, cp))
530 {
531 debug("Applying options for %.100s", cp);
532 *activep = 1;
533 break;
534 }
535 /* Avoid garbage check below, as strtok already returned NULL. */
536 return;
537
538 case oEscapeChar:
539 intptr = &options->escape_char;
540 cp = strtok(NULL, WHITESPACE);
541 if (!cp)
542 fatal("%.200s line %d: Missing argument.", filename, linenum);
543 if (cp[0] == '^' && cp[2] == 0 &&
544 (unsigned char)cp[1] >= 64 && (unsigned char)cp[1] < 128)
545 value = (unsigned char)cp[1] & 31;
546 else
547 if (strlen(cp) == 1)
548 value = (unsigned char)cp[0];
549 else
550 if (strcmp(cp, "none") == 0)
551 value = -2;
552 else
553 {
554 fatal("%.200s line %d: Bad escape character.",
555 filename, linenum);
556 /*NOTREACHED*/
557 value = 0; /* Avoid compiler warning. */
558 }
559 if (*activep && *intptr == -1)
560 *intptr = value;
561 break;
562
563 default:
564 fatal("parse_config_file: Unimplemented opcode %d", opcode);
565 }
566
567 /* Check that there is no garbage at end of line. */
568 if (strtok(NULL, WHITESPACE) != NULL)
569 fatal("%.200s line %d: garbage at end of line.",
570 filename, linenum);
571}
572
573
574/* Reads the config file and modifies the options accordingly. Options should
575 already be initialized before this call. This never returns if there
576 is an error. If the file does not exist, this returns immediately. */
577
578void read_config_file(const char *filename, const char *host, Options *options)
579{
580 FILE *f;
581 char line[1024];
582 int active, linenum;
583
584 /* Open the file. */
585 f = fopen(filename, "r");
586 if (!f)
587 return;
588
589 debug("Reading configuration data %.200s", filename);
590
591 /* Mark that we are now processing the options. This flag is turned on/off
592 by Host specifications. */
593 active = 1;
594 linenum = 0;
595 while (fgets(line, sizeof(line), f))
596 {
597 /* Update line number counter. */
598 linenum++;
599
600 process_config_line(options, host, line, filename, linenum, &active);
601 }
602 fclose(f);
603}
604
605/* Initializes options to special values that indicate that they have not
606 yet been set. Read_config_file will only set options with this value.
607 Options are processed in the following order: command line, user config
608 file, system config file. Last, fill_default_options is called. */
609
610void initialize_options(Options *options)
611{
612 memset(options, 'X', sizeof(*options));
613 options->forward_agent = -1;
614 options->forward_x11 = -1;
615 options->gateway_ports = -1;
616 options->use_privileged_port = -1;
617 options->rhosts_authentication = -1;
618 options->rsa_authentication = -1;
619#ifdef KRB4
620 options->kerberos_authentication = -1;
621#endif
622#ifdef AFS
623 options->kerberos_tgt_passing = -1;
624 options->afs_token_passing = -1;
625#endif
626 options->password_authentication = -1;
627 options->rhosts_rsa_authentication = -1;
628 options->fallback_to_rsh = -1;
629 options->use_rsh = -1;
630 options->batch_mode = -1;
631 options->check_host_ip = -1;
632 options->strict_host_key_checking = -1;
633 options->compression = -1;
634 options->keepalives = -1;
635 options->compression_level = -1;
636 options->port = -1;
637 options->connection_attempts = -1;
638 options->number_of_password_prompts = -1;
639 options->cipher = -1;
640 options->num_identity_files = 0;
641 options->hostname = NULL;
642 options->proxy_command = NULL;
643 options->user = NULL;
644 options->escape_char = -1;
645 options->system_hostfile = NULL;
646 options->user_hostfile = NULL;
647 options->num_local_forwards = 0;
648 options->num_remote_forwards = 0;
6a17f9c2 649 options->log_level = (LogLevel)-1;
8efc0c15 650}
651
652/* Called after processing other sources of option data, this fills those
653 options for which no value has been specified with their default values. */
654
655void fill_default_options(Options *options)
656{
657 if (options->forward_agent == -1)
658 options->forward_agent = 1;
659 if (options->forward_x11 == -1)
660 options->forward_x11 = 1;
661 if (options->gateway_ports == -1)
662 options->gateway_ports = 0;
663 if (options->use_privileged_port == -1)
664 options->use_privileged_port = 1;
665 if (options->rhosts_authentication == -1)
666 options->rhosts_authentication = 1;
667 if (options->rsa_authentication == -1)
668 options->rsa_authentication = 1;
669#ifdef KRB4
670 if (options->kerberos_authentication == -1)
671 options->kerberos_authentication = 1;
672#endif /* KRB4 */
673#ifdef AFS
674 if (options->kerberos_tgt_passing == -1)
675 options->kerberos_tgt_passing = 1;
676 if (options->afs_token_passing == -1)
677 options->afs_token_passing = 1;
678#endif /* AFS */
679 if (options->password_authentication == -1)
680 options->password_authentication = 1;
681 if (options->rhosts_rsa_authentication == -1)
682 options->rhosts_rsa_authentication = 1;
683 if (options->fallback_to_rsh == -1)
684 options->fallback_to_rsh = 1;
685 if (options->use_rsh == -1)
686 options->use_rsh = 0;
687 if (options->batch_mode == -1)
688 options->batch_mode = 0;
689 if (options->check_host_ip == -1)
690 options->check_host_ip = 1;
691 if (options->strict_host_key_checking == -1)
692 options->strict_host_key_checking = 2; /* 2 is default */
693 if (options->compression == -1)
694 options->compression = 0;
695 if (options->keepalives == -1)
696 options->keepalives = 1;
697 if (options->compression_level == -1)
698 options->compression_level = 6;
699 if (options->port == -1)
700 options->port = 0; /* Filled in ssh_connect. */
701 if (options->connection_attempts == -1)
702 options->connection_attempts = 4;
703 if (options->number_of_password_prompts == -1)
704 options->number_of_password_prompts = 3;
705 if (options->cipher == -1)
706 options->cipher = SSH_CIPHER_NOT_SET; /* Selected in ssh_login(). */
707 if (options->num_identity_files == 0)
708 {
709 options->identity_files[0] =
710 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
711 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
712 options->num_identity_files = 1;
713 }
714 if (options->escape_char == -1)
715 options->escape_char = '~';
716 if (options->system_hostfile == NULL)
717 options->system_hostfile = SSH_SYSTEM_HOSTFILE;
718 if (options->user_hostfile == NULL)
719 options->user_hostfile = SSH_USER_HOSTFILE;
6a17f9c2 720 if (options->log_level == (LogLevel)-1)
721 options->log_level = SYSLOG_LEVEL_INFO;
8efc0c15 722 /* options->proxy_command should not be set by default */
723 /* options->user will be set in the main program if appropriate */
724 /* options->hostname will be set in the main program if appropriate */
725}
726
This page took 0.158765 seconds and 5 git commands to generate.