아래의 패치는 RHEL 4.0 기준으로 작성되었고 테스트시 이상없었습니다.
패치 적용 후 rsh 실행시 -t 옵션을 주어 사용하면 됩니다.
diff -uNr netkit-rsh-0.17.org/rsh/rsh.c netkit-rsh-0.17/rsh/rsh.c
--- netkit-rsh-0.17.org/rsh/rsh.c 2006-09-20 10:40:30.732583250 +0900
+++ netkit-rsh-0.17/rsh/rsh.c 2006-09-20 09:55:11.000000000 +0900
@@ -65,8 +65,9 @@
static int rfd2;
static char *copyargs(char **);
static void sendsig(int);
-static void talk(int nflag, long omask, int pid, int rem);
+static void talk(int nflag, long omask, int pid, int rem, int timeout);
static void usage(void);
+void connect_timeout( int );
int
main(int argc, char *argv[])
@@ -75,6 +76,7 @@
struct servent *sp;
long omask;
int argoff, asrsh, ch, dflag, nflag, one, pid=0, rem, uid;
+ int timeout=0;
char *p;
char *args, *host, *user;
char *null = NULL;
@@ -101,7 +103,7 @@
argoff = 1;
}
-#define OPTIONS "+8KLdel:nw"
+#define OPTIONS "+8KLdelt:nw"
while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
switch(ch) {
case 'K':
@@ -120,6 +122,9 @@
case 'n':
nflag = 1;
break;
+ case 't':
+ timeout = atoi(optarg);
+ break;
case '?':
default:
usage();
@@ -162,9 +167,20 @@
fprintf(stderr, "rsh: shell/tcp: unknown service.\n");
exit(1);
}
+ if( timeout ) {
+ signal( SIGALRM, connect_timeout);
+ alarm( timeout );
+ }
+
rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
+ if( timeout ) {
+ signal(SIGALRM, SIG_DFL);
+ alarm(0);
+ }
+
+
if (rem < 0)
exit(1);
@@ -211,7 +227,7 @@
ioctl(rem, FIONBIO, &one);
}
- talk(nflag, omask, pid, rem);
+ talk(nflag, omask, pid, rem, timeout);
if (!nflag)
kill(pid, SIGKILL);
@@ -219,13 +235,15 @@
}
static void
-talk(int nflag, long omask, int pid, int rem)
+talk(int nflag, long omask, int pid, int rem, int timeout)
{
register int cc, wc;
register char *bp;
fd_set readfrom, rembits;
int rfd2_ok, rem_ok;
char buf[BUFSIZ];
+ struct timeval tvtimeout;
+ int srval ;
FD_ZERO(&rembits);
@@ -265,6 +283,9 @@
exit(0);
}
+ tvtimeout.tv_sec = timeout;
+ tvtimeout.tv_usec = 0;
+
rfd2_ok = rem_ok = 1;
sigsetmask(omask);
while (rfd2_ok || rem_ok) {
@@ -273,8 +294,13 @@
FD_SET(rfd2, &readfrom);
if (rem_ok)
FD_SET(rem, &readfrom);
- if (select(rfd2 > rem ? rfd2+1 : rem+1,
- &readfrom, 0, 0, 0) < 0) {
+ if( timeout ) {
+ srval = select(rfd2 > rem ? rfd2+1 : rem+1, &readfrom, 0, 0, &tvtimeout );
+ } else {
+ srval = select(rfd2 > rem ? rfd2+1 : rem+1, &readfrom, 0, 0, 0);
+ }
+
+ if ( srval < 0) {
if (errno != EINTR) {
fprintf(stderr,
"rsh: select: %s.\n", strerror(errno));
@@ -282,6 +308,11 @@
}
continue;
}
+
+ if( srval == 0 ) {
+ fprintf(stderr, "timeout reached (%d seconds)", timeout);
+ }
+
if (FD_ISSET(rfd2, &readfrom)) {
errno = 0;
cc = read(rfd2, buf, sizeof buf);
@@ -301,6 +332,14 @@
}
}
+
+/*
+void
+sendsig2(int signo)
+{
+ abort();
+}
+*/
void
sendsig(int signo)
{
@@ -332,11 +371,21 @@
return(args);
}
+void
+connect_timeout( int sig)
+{
+ char message[] = "timeout reached before connection completed.\n";
+ write(STDERR_FILENO, message, sizeof(message) - 1);
+ abort();
+ //_exit(1);
+}
+
+
void
usage(void)
{
fprintf(stderr,
- "usage: rsh [-nd%s]%s[-l login] host [command]\n",
+ "usage: rsh [-nd%s]%s -t timeout [-l login] host [command]\n",
"", " ");
exit(1);
}