remove nologin, it's paths.h now
[unix-history] / usr / src / libexec / rshd / rshd.c
CommitLineData
8c5eec2f 1/*
56940953 2 * Copyright (c) 1983, 1988, 1989 The Regents of the University of California.
780d12ad
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
8c5eec2f
DF
16 */
17
18#ifndef lint
19char copyright[] =
56940953 20"@(#) Copyright (c) 1983, 1988, 1089 The Regents of the University of California.\n\
8c5eec2f 21 All rights reserved.\n";
780d12ad 22#endif /* not lint */
8c5eec2f 23
1d68cba5 24#ifndef lint
5416610d 25static char sccsid[] = "@(#)rshd.c 5.27 (Berkeley) %G%";
780d12ad 26#endif /* not lint */
1d68cba5 27
56940953
MK
28/* From:
29 * $Source: /mit/kerberos/ucb/mit/rshd/RCS/rshd.c,v $
30 * $Header: /mit/kerberos/ucb/mit/rshd/RCS/rshd.c,v 5.2 89/07/31 19:30:04 kfall Exp $
31 */
32
33
bb933cc2
MK
34/*
35 * remote shell server:
046a4121 36 * [port]\0
bb933cc2
MK
37 * remuser\0
38 * locuser\0
39 * command\0
40 * data
41 */
1d68cba5 42#include <sys/param.h>
046a4121 43#include <sys/ioctl.h>
1d68cba5 44#include <sys/socket.h>
c9db37f1 45#include <sys/file.h>
17ccb086 46#include <sys/signal.h>
beaa2897 47#include <sys/signal.h>
d4413a13 48#include <sys/time.h>
e7d6d17a
SL
49
50#include <netinet/in.h>
51
4c99408e
JB
52#include <arpa/inet.h>
53
e7d6d17a 54#include <stdio.h>
1d68cba5
BJ
55#include <errno.h>
56#include <pwd.h>
3f5b52bc 57#include <netdb.h>
3f99c0f7 58#include <syslog.h>
17ccb086 59#include "pathnames.h"
beaa2897 60#include "pathnames.h"
1d68cba5
BJ
61
62int errno;
e0ffdf97 63int keepalive = 1;
56940953 64int check_all = 0;
beaa2897 65int check_all = 0;
d4413a13
JL
66char *index(), *rindex(), *strncat();
67/*VARARGS1*/
1d68cba5 68int error();
56940953 69int sent_null;
beaa2897 70int sent_null;
bb933cc2 71
d4413a13 72/*ARGSUSED*/
1d68cba5
BJ
73main(argc, argv)
74 int argc;
75 char **argv;
76{
d6dd6df6
KF
77
78 extern int opterr, optind;
d6dd6df6 79 extern int _check_rhosts_file;
bcb894cb 80 struct linger linger;
10869b2d 81 int ch, on = 1, fromlen;
1d68cba5 82 struct sockaddr_in from;
3f5b52bc 83
0d097e0d 84 openlog("rshd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
10869b2d
KB
85
86 opterr = 0;
56940953
MK
87 switch (ch) {
88 case 'a':
89 check_all = 1;
90 break;
10869b2d
KB
91 case 'l':
92 _check_rhosts_file = 0;
93 break;
e0ffdf97
KB
94 case 'n':
95 keepalive = 0;
96 break;
10869b2d
KB
97 case '?':
98 default:
0d097e0d 99 usage();
10869b2d
KB
100 break;
101 }
26c5bd5e 102
10869b2d
KB
103 argc -= optind;
104 argv += optind;
105
bb933cc2
MK
106 fromlen = sizeof (from);
107 if (getpeername(0, &from, &fromlen) < 0) {
56940953 108 syslog(LOG_ERR, "getpeername: %m");
bb933cc2 109 _exit(1);
3f5b52bc 110 }
e0ffdf97
KB
111 if (keepalive &&
112 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
113 sizeof(on)) < 0)
3f99c0f7 114 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
bcb894cb
SL
115 linger.l_onoff = 1;
116 linger.l_linger = 60; /* XXX */
d4413a13
JL
117 if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger,
118 sizeof (linger)) < 0)
3f99c0f7 119 syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m");
4c1b6a2b 120 doit(&from);
a8e3386b
SL
121}
122
1d68cba5
BJ
123char username[20] = "USER=";
124char homedir[64] = "HOME=";
125char shell[64] = "SHELL=";
126char *envinit[] =
17ccb086 127 {homedir, shell, _PATH_DEFPATH, username, 0};
1d68cba5
BJ
128char **environ;
129
4c1b6a2b 130doit(fromp)
1d68cba5
BJ
131 struct sockaddr_in *fromp;
132{
133 char cmdbuf[NCARGS+1], *cp;
134 char locuser[16], remuser[16];
135 struct passwd *pwd;
d4413a13 136 int s;
3f5b52bc 137 struct hostent *hp;
7ad57ed0 138 char *hostname;
1d68cba5 139 short port;
780d12ad 140 int pv[2], pid, cc;
046a4121
MK
141 int nfd;
142 fd_set ready, readfrom;
1d68cba5
BJ
143 char buf[BUFSIZ], sig;
144 int one = 1;
046a4121 145 char remotehost[2 * MAXHOSTNAMELEN + 1];
26c5bd5e 146
1d68cba5
BJ
147 (void) signal(SIGINT, SIG_DFL);
148 (void) signal(SIGQUIT, SIG_DFL);
149 (void) signal(SIGTERM, SIG_DFL);
27890867 150#ifdef DEBUG
b52175dc 151 { int t = open(_PATH_TTY, 2);
1d68cba5
BJ
152 if (t >= 0) {
153 ioctl(t, TIOCNOTTY, (char *)0);
154 (void) close(t);
155 }
156 }
157#endif
1d68cba5 158 fromp->sin_port = ntohs((u_short)fromp->sin_port);
c7299f34 159 if (fromp->sin_family != AF_INET) {
3f99c0f7 160 syslog(LOG_ERR, "malformed from address\n");
1d68cba5 161 exit(1);
d173f55d 162 }
4c1b6a2b
MK
163#ifdef IP_OPTIONS
164 {
165 u_char optbuf[BUFSIZ/3], *cp;
166 char lbuf[BUFSIZ], *lp;
167 int optsize = sizeof(optbuf), ipproto;
168 struct protoent *ip;
cf9611a9
MK
169#ifdef IP_OPTIONS
170 {
171 u_char optbuf[BUFSIZ/3], *cp;
172 char lbuf[BUFSIZ], *lp;
173 int optsize = sizeof(optbuf), ipproto;
174 struct protoent *ip;
175
176 if ((ip = getprotobyname("ip")) != NULL)
177 ipproto = ip->p_proto;
178 else
179 ipproto = IPPROTO_IP;
180 if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) == 0 &&
181 optsize != 0) {
182 lp = lbuf;
183 for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
184 sprintf(lp, " %2.2x", *cp);
185 syslog(LOG_NOTICE,
186 "Connection received using IP options (ignored):%s", lbuf);
187 if (setsockopt(0, ipproto, IP_OPTIONS,
188 (char *)NULL, &optsize) != 0) {
189 syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m");
190 exit(1);
191 }
192 }
193 }
194#endif
4c1b6a2b
MK
195
196 if ((ip = getprotobyname("ip")) != NULL)
197 ipproto = ip->p_proto;
198 else
199 ipproto = IPPROTO_IP;
5416610d 200 if (!getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) &&
4c1b6a2b
MK
201 optsize != 0) {
202 lp = lbuf;
203 for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
204 sprintf(lp, " %2.2x", *cp);
205 syslog(LOG_NOTICE,
206 "Connection received using IP options (ignored):%s", lbuf);
207 if (setsockopt(0, ipproto, IP_OPTIONS,
208 (char *)NULL, &optsize) != 0) {
209 syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m");
210 exit(1);
211 }
212 }
213 }
214#endif
26c5bd5e 215
cee3e39b
KF
216#ifdef KERBEROS
217 if (!use_kerberos)
26c5bd5e 218
1d68cba5
BJ
219 (void) alarm(60);
220 port = 0;
221 for (;;) {
222 char c;
4c1b6a2b 223 if ((cc = read(0, &c, 1)) != 1) {
c7299f34
MK
224 if (cc < 0)
225 syslog(LOG_NOTICE, "read: %m");
4c1b6a2b 226 shutdown(0, 1+1);
1d68cba5 227 exit(1);
d173f55d 228 }
1d68cba5
BJ
229 port = port * 10 + c - '0';
230 }
26c5bd5e 231
1d68cba5
BJ
232 (void) alarm(0);
233 if (port != 0) {
d4413a13 234 int lport = IPPORT_RESERVED - 1;
3b0e7dec 235 s = rresvport(&lport);
d173f55d 236 if (s < 0) {
3f99c0f7 237 syslog(LOG_ERR, "can't get stderr port: %m");
d173f55d
SL
238 exit(1);
239 }
cee3e39b
KF
240#ifdef KERBEROS
241 if (!use_kerberos)
e23c0837 242 fromp->sin_port = htons((u_short)port);
d4413a13 243 if (connect(s, fromp, sizeof (*fromp)) < 0) {
7ad57ed0 244 syslog(LOG_INFO, "connect second port: %m");
1d68cba5 245 exit(1);
d173f55d 246 }
1d68cba5 247 }
26c5bd5e 248
046a4121 249#ifdef notdef
4c1b6a2b 250 /* from inetd, socket is already on 0, 1, 2 */
d173f55d
SL
251 dup2(f, 0);
252 dup2(f, 1);
253 dup2(f, 2);
046a4121 254#endif
d4413a13 255 hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr),
3f5b52bc 256 fromp->sin_family);
26c5bd5e 257 if (hp) {
046a4121
MK
258 /*
259 * If name returned by gethostbyaddr is in our domain,
260 * attempt to verify that we haven't been fooled by someone
261 * in a remote net; look up the name and check that this
262 * address corresponds to the name.
263 */
56940953 264 if (check_all || (!use_kerberos && local_domain(hp->h_name))) {
046a4121
MK
265 strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1);
266 remotehost[sizeof(remotehost) - 1] = 0;
26c5bd5e 267 hp = gethostbyname(remotehost);
046a4121
MK
268 if (hp == NULL) {
269 syslog(LOG_INFO,
270 "Couldn't look up address for %s",
271 remotehost);
56940953 272 error("Couldn't look up address for your host\n");
26c5bd5e 273 exit(1);
beaa2897
MK
274 }
275#ifdef h_addr /* 4.2 hack */
276 for (; ; hp->h_addr_list++) {
046a4121
MK
277 if (hp->h_addr_list[0] == NULL) {
278 syslog(LOG_NOTICE,
279 "Host addr %s not listed for host %s",
280 inet_ntoa(fromp->sin_addr),
281 hp->h_name);
56940953 282 error("Host address mismatch\n");
26c5bd5e
KF
283 exit(1);
284 }
5416610d
KB
285 if (!bcmp(hp->h_addr_list[0],
286 (caddr_t)&fromp->sin_addr,
287 sizeof(fromp->sin_addr)))
288 break;
26c5bd5e 289 }
beaa2897
MK
290#else
291 if (bcmp(hp->h_addr, (caddr_t)&fromp->sin_addr,
292 sizeof(fromp->sin_addr))) {
293 syslog(LOG_NOTICE,
294 "Host addr %s not listed for host %s",
295 inet_ntoa(fromp->sin_addr),
296 hp->h_name);
297 error("Host address mismatch\n");
298 exit(1);
299 }
300#endif
26c5bd5e 301 }
7ad57ed0 302 hostname = hp->h_name;
046a4121 303 } else
7ad57ed0 304 hostname = inet_ntoa(fromp->sin_addr);
26c5bd5e 305
0d23e75d 306 getstr(remuser, sizeof(remuser), "remuser");
1d68cba5
BJ
307 getstr(locuser, sizeof(locuser), "locuser");
308 getstr(cmdbuf, sizeof(cmdbuf), "command");
309 setpwent();
310 pwd = getpwnam(locuser);
311 if (pwd == NULL) {
312 error("Login incorrect.\n");
313 exit(1);
314 }
1d68cba5 315 if (chdir(pwd->pw_dir) < 0) {
d4413a13 316 (void) chdir("/");
bb933cc2 317#ifdef notdef
1d68cba5
BJ
318 error("No remote directory.\n");
319 exit(1);
bb933cc2 320#endif
1d68cba5 321 }
26c5bd5e 322
0d23e75d
MK
323 if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
324 ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) {
325 error("Permission denied.\n");
326 exit(1);
327 }
26c5bd5e 328
17ccb086 329 if (pwd->pw_uid && !access(_PATH_NOLOGIN, F_OK)) {
c9db37f1
KB
330 error("Logins currently disabled.\n");
331 exit(1);
332 }
beaa2897 333
1d68cba5 334 (void) write(2, "\0", 1);
56940953 335 sent_null = 1;
beaa2897 336 sent_null = 1;
26c5bd5e 337
1d68cba5
BJ
338 if (port) {
339 if (pipe(pv) < 0) {
340 error("Can't make pipe.\n");
341 exit(1);
342 }
d6dd6df6
KF
343#ifdef KERBEROS
344 if (encrypt) {
345 if (pipe(pv1) < 0) {
346 error("Can't make 2nd pipe.\n");
347 exit(1);
348 }
349 if (pipe(pv2) < 0) {
350 error("Can't make 3rd pipe.\n");
351 exit(1);
352 }
353 }
354#endif
1d68cba5
BJ
355 pid = fork();
356 if (pid == -1) {
56940953 357 error("Can't fork; try again.\n");
1d68cba5
BJ
358 exit(1);
359 }
360 if (pid) {
d6dd6df6
KF
361#ifdef KERBEROS
362 if (encrypt) {
363 static char msg[] = SECURE_MESSAGE;
56940953
MK
364 (void) close(pv1[1]);
365 (void) close(pv2[1]);
d6dd6df6
KF
366 des_write(s, msg, sizeof(msg));
367
368 } else
369#endif
370 {
371 (void) close(0); (void) close(1);
d6dd6df6 372 }
56940953 373 (void) close(2); (void) close(pv[1]);
d6dd6df6 374
046a4121
MK
375 FD_ZERO(&readfrom);
376 FD_SET(s, &readfrom);
377 FD_SET(pv[0], &readfrom);
56940953
MK
378 if (pv[0] > s)
379 nfd = pv[0];
380 else
381 nfd = s;
d6dd6df6
KF
382#ifdef KERBEROS
383 if (encrypt) {
384 FD_ZERO(&writeto);
385 FD_SET(pv2[0], &writeto);
386 FD_SET(pv1[0], &readfrom);
387
388 nfd = MAX(nfd, pv2[0]);
389 nfd = MAX(nfd, pv1[0]);
390 } else
391#endif
392 ioctl(pv[0], FIONBIO, (char *)&one);
393
1d68cba5 394 /* should set s nbio! */
56940953 395 nfd++;
1d68cba5
BJ
396 do {
397 ready = readfrom;
d6dd6df6
KF
398#ifdef KERBEROS
399 if (encrypt) {
400 wready = writeto;
401 if (select(nfd, &ready,
402 &wready, (fd_set *) 0,
403 (struct timeval *) 0) < 0)
404 break;
405 } else
406#endif
407 if (select(nfd, &ready, (fd_set *)0,
408 (fd_set *)0, (struct timeval *)0) < 0)
409 break;
046a4121 410 if (FD_ISSET(s, &ready)) {
d6dd6df6
KF
411 int ret;
412#ifdef KERBEROS
413 if (encrypt)
414 ret = des_read(s, &sig, 1);
415 else
416#endif
417 ret = read(s, &sig, 1);
418 if (ret <= 0)
046a4121 419 FD_CLR(s, &readfrom);
1d68cba5
BJ
420 else
421 killpg(pid, sig);
422 }
046a4121 423 if (FD_ISSET(pv[0], &ready)) {
fadc6b8f 424 errno = 0;
d6dd6df6 425 cc = read(pv[0], buf, sizeof(buf));
1d68cba5 426 if (cc <= 0) {
ff24c640 427 shutdown(s, 1+1);
046a4121 428 FD_CLR(pv[0], &readfrom);
d6dd6df6
KF
429 } else {
430#ifdef KERBEROS
431 if (encrypt)
432 (void)
433 des_write(s, buf, cc);
434 else
435#endif
436 (void)
437 write(s, buf, cc);
438 }
439 }
440#ifdef KERBEROS
441
442 if (encrypt && FD_ISSET(pv1[0], &ready)) {
443 errno = 0;
444 cc = read(pv1[0], buf, sizeof(buf));
445 if (cc <= 0) {
446 shutdown(pv1[0], 1+1);
447 FD_CLR(pv1[0], &readfrom);
448 } else
449 (void) des_write(1, buf, cc);
450 }
451
452 if (encrypt && FD_ISSET(pv2[0], &wready)) {
453 errno = 0;
454 cc = des_read(0, buf, sizeof(buf));
455 if (cc <= 0) {
456 shutdown(pv2[0], 1+1);
457 FD_CLR(pv2[0], &writeto);
1d68cba5 458 } else
d6dd6df6 459 (void) write(pv2[0], buf, cc);
1d68cba5 460 }
d6dd6df6
KF
461#endif
462
046a4121 463 } while (FD_ISSET(s, &readfrom) ||
d6dd6df6
KF
464#ifdef KERBEROS
465 (encrypt && FD_ISSET(pv1[0], &readfrom)) ||
466#endif
046a4121 467 FD_ISSET(pv[0], &readfrom));
1d68cba5
BJ
468 exit(0);
469 }
470 setpgrp(0, getpid());
471 (void) close(s); (void) close(pv[0]);
d6dd6df6
KF
472#ifdef KERBEROS
473 if (encrypt) {
474 close(pv1[0]); close(pv2[0]);
475 dup2(pv1[1], 1);
476 dup2(pv2[1], 0);
477 close(pv1[1]);
478 close(pv2[1]);
479 }
480#endif
1d68cba5 481 dup2(pv[1], 2);
389cc7a4 482 close(pv[1]);
beaa2897 483 close(pv[1]);
1d68cba5
BJ
484 }
485 if (*pwd->pw_shell == '\0')
17ccb086 486 pwd->pw_shell = _PATH_BSHELL;
d6dd6df6 487#if BSD > 43
56940953
MK
488 if (setlogin(pwd->pw_name) < 0)
489 syslog(LOG_ERR, "setlogin() failed: %m");
d6dd6df6 490#endif
56940953
MK
491 (void) setgid((gid_t)pwd->pw_gid);
492 initgroups(pwd->pw_name, pwd->pw_gid);
d4413a13 493 (void) setuid((uid_t)pwd->pw_uid);
1d68cba5
BJ
494 environ = envinit;
495 strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
496 strncat(shell, pwd->pw_shell, sizeof(shell)-7);
497 strncat(username, pwd->pw_name, sizeof(username)-6);
498 cp = rindex(pwd->pw_shell, '/');
499 if (cp)
500 cp++;
501 else
502 cp = pwd->pw_shell;
cee3e39b 503 endpwent();
beaa2897
MK
504 if (pwd->pw_uid == 0)
505 syslog(LOG_INFO|LOG_AUTH, "ROOT shell from %s@%s, comm: %s\n",
506 remuser, hostname, cmdbuf);
507 endpwent();
56940953 508 if (pwd->pw_uid == 0) {
49114004
KF
509#ifdef KERBEROS
510 if (use_kerberos)
56940953 511 syslog(LOG_INFO|LOG_AUTH,
49114004
KF
512 "ROOT Kerberos shell from %s.%s@%s on %s, comm: %s\n",
513 kdata->pname, kdata->pinst, kdata->prealm,
514 hostname, cmdbuf);
515 else
516#endif
56940953 517 syslog(LOG_INFO|LOG_AUTH,
49114004
KF
518 "ROOT shell from %s@%s, comm: %s\n",
519 remuser, hostname, cmdbuf);
520 }
1d68cba5
BJ
521 execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
522 perror(pwd->pw_shell);
523 exit(1);
1d68cba5
BJ
524}
525
beaa2897
MK
526/*
527 * Report error to client.
528 * Note: can't be used until second socket has connected
529 * to client, or older clients will hang waiting
530 * for that connection first.
531 */
56940953
MK
532/*
533 * Report error to client.
534 * Note: can't be used until second socket has connected
535 * to client, or older clients will hang waiting
536 * for that connection first.
537 */
d4413a13 538/*VARARGS1*/
35db6ea0 539error(fmt, a1, a2, a3)
1d68cba5 540 char *fmt;
35db6ea0 541 int a1, a2, a3;
1d68cba5 542{
56940953 543 char buf[BUFSIZ], *bp = buf;
1d68cba5 544
56940953
MK
545 if (sent_null == 0)
546 *bp++ = 1;
547 (void) sprintf(bp, fmt, a1, a2, a3);
1d68cba5
BJ
548 (void) write(2, buf, strlen(buf));
549}
550
551getstr(buf, cnt, err)
552 char *buf;
553 int cnt;
554 char *err;
555{
556 char c;
557
558 do {
559 if (read(0, &c, 1) != 1)
560 exit(1);
561 *buf++ = c;
562 if (--cnt == 0) {
563 error("%s too long\n", err);
564 exit(1);
565 }
566 } while (c != 0);
567}
26c5bd5e 568
046a4121
MK
569/*
570 * Check whether host h is in our local domain,
56940953
MK
571 * defined as sharing the last two components of the domain part,
572 * or the entire domain part if the local domain has only one component.
046a4121
MK
573 * If either name is unqualified (contains no '.'),
574 * assume that the host is local, as it will be
575 * interpreted as such.
576 */
577local_domain(h)
578 char *h;
26c5bd5e 579{
046a4121 580 char localhost[MAXHOSTNAMELEN];
56940953 581 char *p1, *p2, *topdomain();
046a4121 582
beaa2897 583 localhost[0] = 0;
56940953 584 localhost[0] = 0;
046a4121 585 (void) gethostname(localhost, sizeof(localhost));
56940953
MK
586 p1 = topdomain(localhost);
587 p2 = topdomain(h);
046a4121 588 if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2))
26c5bd5e
KF
589 return(1);
590 return(0);
591}
0d097e0d 592
56940953
MK
593char *
594topdomain(h)
595 char *h;
596{
597 register char *p;
598 char *maybe = NULL;
599 int dots = 0;
600
601 for (p = h + strlen(h); p >= h; p--) {
602 if (*p == '.') {
603 if (++dots == 2)
604 return (p);
605 maybe = p;
606 }
607 }
608 return (maybe);
609}
610
beaa2897
MK
611char *
612topdomain(h)
613 char *h;
614{
615 register char *p;
616 char *maybe = NULL;
617 int dots = 0;
618
619 for (p = h + strlen(h); p >= h; p--) {
620 if (*p == '.') {
621 if (++dots == 2)
622 return (p);
623 maybe = p;
624 }
625 }
626 return (maybe);
627}
628
0d097e0d
KF
629usage()
630{
631#ifdef KERBEROS
56940953 632 syslog(LOG_ERR, "usage: rshd [-aln]");
d6dd6df6 633#else
56940953 634 syslog(LOG_ERR, "usage: rshd [-alknvx]");
0d097e0d
KF
635#endif
636}