Subject: PR 11733: rcmd(1) always asks for stderr channel
To: None <tech-userlevel@netbsd.org>
From: Simon J. Gerraty <sjg@quick.com.au>
List: tech-userlevel
Date: 12/26/2000 01:07:46
The essential problem with the way rcmd(1) and rcmd(3) interract is
that there is no way to communicate to rcmd(1) that no stderr channel
should be established - eg for rcp(1).
The following patch provides a fix for PR 11733 but
a/ only solves it for rcmd(1), not replacement commands.
b/ might be better if resrcmd(3) used putenv("RCMD_NO_FD2=1") rather
than pass a new option (-2) to rcmd_cmd. In fact that was my first
inclination.
Input welcome.
--sjg
Index: lib/libc/net/rcmd.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/net/rcmd.c,v
retrieving revision 1.44
diff -u -p -r1.44 rcmd.c
--- lib/libc/net/rcmd.c 2000/07/07 08:03:39 1.44
+++ lib/libc/net/rcmd.c 2000/12/26 09:00:28
@@ -487,8 +487,9 @@ rshrcmd(ahost, rport, locuser, remuser,
execlp(rshcmd, p ? p + 1 : rshcmd, "-c", cmd, NULL);
} else {
p = strrchr(rshcmd, '/');
- execlp(rshcmd, p ? p + 1 : rshcmd, *ahost, "-l",
- remuser, cmd, NULL);
+ execlp(rshcmd, p ? p + 1 : rshcmd, *ahost,
+ (fd2p) ? "-l" : "-2l",
+ remuser, cmd, NULL);
}
warn("rshrcmd: exec %s", rshcmd);
_exit(1);
Index: usr.bin/rsh/rsh.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/rsh/rsh.c,v
retrieving revision 1.13
diff -u -p -r1.13 rsh.c
--- usr.bin/rsh/rsh.c 2000/01/31 14:19:34 1.13
+++ usr.bin/rsh/rsh.c 2000/12/26 09:00:29
@@ -88,7 +88,7 @@ void warning __P((const char *, ...));
* rsh - remote shell
*/
extern char *__progname; /* XXX */
-int remerr;
+int *remerrp;
static int sigs[] = { SIGINT, SIGTERM, SIGQUIT };
@@ -113,6 +113,7 @@ main(argc, argv)
struct passwd *pw;
struct servent *sp;
sigset_t oset, nset;
+ int fd2;
#ifdef IN_RCMD
char *locuser = 0, *loop;
@@ -125,7 +126,8 @@ main(argc, argv)
argoff = asrsh = dflag = nflag = 0;
one = 1;
host = user = NULL;
-
+ remerrp = &fd2;
+
#ifndef IN_RCMD
/*
* If called as something other than "rsh" use it as the host name,
@@ -145,6 +147,9 @@ main(argc, argv)
}
#ifdef IN_RCMD
+ if (getenv("RCMD_NO_FD2") != NULL)
+ remerrp = NULL;
+
if ((loop = getenv("RCMD_LOOP")) && strcmp(loop, "YES") == 0)
warnx("rcmd appears to be looping!");
@@ -152,24 +157,24 @@ main(argc, argv)
# ifdef KERBEROS
# ifdef CRYPT
-# define OPTIONS "8KLdek:l:nu:wx"
+# define OPTIONS "28KLdek:l:nu:wx"
# else
-# define OPTIONS "8KLdek:l:nu:w"
+# define OPTIONS "28KLdek:l:nu:w"
# endif
# else
-# define OPTIONS "8KLdel:nu:w"
+# define OPTIONS "28KLdel:nu:w"
# endif
#else /* IN_RCMD */
# ifdef KERBEROS
# ifdef CRYPT
-# define OPTIONS "8KLdek:l:nwx"
+# define OPTIONS "28KLdek:l:nwx"
# else
-# define OPTIONS "8KLdek:l:nw"
+# define OPTIONS "28KLdek:l:nw"
# endif
# else
-# define OPTIONS "8KLdel:nw"
+# define OPTIONS "28KLdel:nw"
# endif
#endif /* IN_RCMD */
@@ -181,6 +186,9 @@ main(argc, argv)
err(1, "malloc");
while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != -1)
switch(ch) {
+ case '2':
+ remerrp = NULL;
+ break;
case 'K':
#ifdef KERBEROS
use_kerberos = 0;
@@ -306,10 +314,10 @@ try_connect:
#ifdef CRYPT
if (doencrypt)
rem = krcmd_mutual(&host, sp->s_port, user, args,
- &remerr, dest_realm, &cred, schedule);
+ remerrp, dest_realm, &cred, schedule);
else
#endif
- rem = krcmd(&host, sp->s_port, user, args, &remerr,
+ rem = krcmd(&host, sp->s_port, user, args, remerrp,
dest_realm);
if (rem < 0) {
use_kerberos = 0;
@@ -331,7 +339,7 @@ try_connect:
rem = rcmd_af(&host, sp->s_port,
#endif
name,
- user, args, &remerr, PF_UNSPEC);
+ user, args, remerrp, PF_UNSPEC);
}
#else /* KERBEROS */
@@ -340,20 +348,21 @@ try_connect:
#else
rem = rcmd_af(&host, sp->s_port,
#endif
- name, user, args, &remerr, PF_UNSPEC);
+ name, user, args, remerrp, PF_UNSPEC);
#endif /* KERBEROS */
(void)free(name);
if (rem < 0)
exit(1);
- if (remerr < 0)
+ if (remerrp != NULL && *remerrp < 0)
errx(1, "can't establish stderr");
if (dflag) {
if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one,
sizeof(one)) < 0)
warn("setsockopt remote");
- if (setsockopt(remerr, SOL_SOCKET, SO_DEBUG, &one,
+ if (remerrp != NULL &&
+ setsockopt(*remerrp, SOL_SOCKET, SO_DEBUG, &one,
sizeof(one)) < 0)
warn("setsockopt stderr");
}
@@ -387,7 +396,8 @@ try_connect:
if (!doencrypt)
#endif
{
- (void)ioctl(remerr, FIONBIO, &one);
+ if (remerrp)
+ (void)ioctl(*remerrp, FIONBIO, &one);
(void)ioctl(rem, FIONBIO, &one);
}
@@ -451,7 +461,8 @@ talk(nflag, oset, pid, rem)
if (!nflag && pid == 0) {
- (void)close(remerr);
+ if (remerrp)
+ (void)close(*remerrp);
fdp->events = POLLOUT|POLLNVAL|POLLERR|POLLHUP;
fdp->fd = rem;
@@ -507,11 +518,15 @@ done:
}
(void) sigprocmask(SIG_SETMASK, oset, NULL);
+ nfds = 0;
fds[0].events = fds[1].events = POLLIN|POLLNVAL|POLLERR|POLLHUP;
- fds[0].fd = remerr;
- fds[1].fd = rem;
+ if (remerrp)
+ fds[nfds++].fd = *remerrp;
+ else
+ fds[1].events = 0;
+ fds[nfds++].fd = rem;
fdp = &fds[0];
- nfds = 2;
+
do {
if (poll(fdp, nfds, INFTIM) == -1) {
if (errno != EINTR)
@@ -537,15 +552,18 @@ sendsig(sig)
{
char signo;
+ if (!remerrp)
+ return;
+
signo = sig;
#ifdef KERBEROS
#ifdef CRYPT
if (doencrypt)
- (void)des_write(remerr, &signo, 1);
+ (void)des_write(*remerrp, &signo, 1);
else
#endif
#endif
- (void)write(remerr, &signo, 1);
+ (void)write(*remerrp, &signo, 1);
}
#ifdef KERBEROS