1
0
Files
irix-657m-src/eoe/cmd/bsd/rsh.c
2022-09-29 17:59:04 +03:00

485 lines
9.3 KiB
C

/*
* Copyright (c) 1983 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)rsh.c 5.7 (Berkeley) 9/20/88";
#endif /* not lint */
#ifdef sgi
#define _BSD_SIGNALS
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <pwd.h>
#include <netdb.h>
#ifdef sgi
#include <getopt.h>
#endif
#ifdef sgi
#include <strings.h>
#include <malloc.h>
#define _PATH_RLOGIN "/usr/bsd/rlogin" /* look for rlogin(1) here */
#endif /* sgi */
/*
* rsh - remote shell
*/
/* VARARGS */
int error();
#ifndef sgi
char *index(), *rindex(), *malloc(), *getpass(), *strcpy();
struct passwd *getpwuid();
#endif
#ifdef sgi
extern int errno;
#else
int errno;
#endif
int options;
int rfd2;
int nflag;
#ifdef sgi
void sendsig();
#else
int sendsig();
#endif
#ifdef sgi
extern int rcmd();
int (*rcmdp)() = rcmd;
#endif
#ifdef AFS
extern int (*__afs_getsym())();
#endif
#define mask(s) (1 << ((s) - 1))
main(argc, argv0)
int argc;
char **argv0;
{
int rem, pid;
#ifdef sgi
#define NBUFS 5
#define BUFSIZE (64 * 1024)
char *buf[NBUFS];
char *host, *cp, **ap, *args, **argv = argv0, *user = 0;
int argoff = 0, ch = 0;
register char *p;
int i, b = 0;
#else
char *host, *cp, **ap, buf[BUFSIZ], *args, **argv = argv0, *user = 0;
#endif
register int cc;
int asrsh = 0;
struct passwd *pwd;
int readfrom, ready;
int one = 1;
struct servent *sp;
int port;
int omask;
int had_error = 0;
#ifdef sgi
/*
* use memalign to set up page-aligned buffer
*/
for (i = 0; i < NBUFS; i++) {
buf[i] = memalign(16*1024, BUFSIZE);
if (!buf[i]) {
perror("rsh");
exit(1);
}
}
/* work around sh bug which leaves lots of open files */
{ int maxfd = getdtablehi();
for (cc = 3; cc < maxfd; cc++)
(void)close(cc);
}
nflag = options = 0;
/* if called as something other than "rsh", use it as the host name */
if (p = rindex(argv[0], '/'))
++p;
else
p = argv[0];
if (strcmp(p, "rsh"))
host = p;
else {
asrsh = 1;
host = NULL;
}
/* handle "rsh host flags" */
if (!host && argc > 2 && argv[1][0] != '-') {
host = argv[1];
argoff = 1;
}
#else
host = rindex(argv[0], '/');
if (host)
host++;
else
host = argv[0];
argv++, --argc;
if (!strcmp(host, "rsh")) {
host = *argv++, --argc;
asrsh = 1;
}
#endif
#ifdef sgi
#define OPTIONS "8Ldel:nw"
while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
switch(ch) {
case 'L': /* -8Lew are ignored to allow rlogin aliases */
case 'e':
case '8':
break;
case 'd':
options |= SO_DEBUG;
break;
case 'l':
user = optarg;
break;
case 'n':
nflag = 1;
break;
case '?':
default:
goto usage;
}
optind += argoff;
#else /* !sgi */
another:
if (argc > 0 && !strcmp(*argv, "-l")) {
argv++, argc--;
if (argc > 0)
user = *argv++, argc--;
goto another;
}
if (argc > 0 && !strcmp(*argv, "-n")) {
argv++, argc--;
nflag++;
goto another;
}
if (argc > 0 && !strcmp(*argv, "-d")) {
argv++, argc--;
options |= SO_DEBUG;
goto another;
}
/*
* Ignore the -L, -w, -e and -8 flags to allow aliases with rlogin
* to work
*
* There must be a better way to do this! -jmb
*/
if (argc > 0 && !strncmp(*argv, "-L", 2)) {
argv++, argc--;
goto another;
}
if (argc > 0 && !strncmp(*argv, "-w", 2)) {
argv++, argc--;
goto another;
}
if (argc > 0 && !strncmp(*argv, "-e", 2)) {
argv++, argc--;
goto another;
}
if (argc > 0 && !strncmp(*argv, "-8", 2)) {
argv++, argc--;
goto another;
}
#endif /* sgi */
#ifdef sgi
/* if haven't gotten a host yet, do so */
if (!host && !(host = argv[optind++]))
goto usage;
#else
if (host == 0)
goto usage;
#endif
#ifdef sgi
/* if no further arguments, must have been called as rlogin. */
if (!argv[optind]) {
if (asrsh)
*argv0 = "rlogin";
execv(_PATH_RLOGIN, argv0);
perror(_PATH_RLOGIN);
exit(1);
}
argc -= optind;
argv += optind;
#else /* !sgi */
if (argv[0] == 0) {
if (asrsh)
*argv0 = "rlogin";
execv("/usr/ucb/rlogin", argv0);
perror("/usr/ucb/rlogin");
exit(1);
}
#endif
#ifdef sgi
/* Accept user1@host format, though "-l user2" overrides user1 */
cp = strchr(host, '@');
if (cp) {
*cp = '\0';
if (user == NULL && cp > host)
user = host;
host = cp + 1;
if (*host == '\0')
goto usage;
}
#endif
pwd = getpwuid(getuid());
if (pwd == 0) {
fprintf(stderr, "who are you?\n");
exit(1);
}
#ifdef AFS
if ((rcmdp = __afs_getsym("rcmd")) == NULL)
rcmdp = rcmd;
#endif
cc = 0;
for (ap = argv; *ap; ap++)
cc += strlen(*ap) + 1;
cp = args = malloc(cc);
for (ap = argv; *ap; ap++) {
(void) strcpy(cp, *ap);
while (*cp)
cp++;
if (ap[1])
*cp++ = ' ';
}
#ifdef sgi
port = 514;
#else
sp = getservbyname("shell", "tcp");
if (sp == 0) {
fprintf(stderr, "rsh: shell/tcp: unknown service\n");
exit(1);
}
port = sp->s_port;
#endif
rem = (*rcmdp)(&host, port, pwd->pw_name,
user ? user : pwd->pw_name, args, &rfd2);
if (rem < 0) {
fprintf(stderr, "rsh: connection failed\n");
exit(1);
}
if (rfd2 < 0) {
fprintf(stderr, "rsh: can't establish stderr\n");
exit(2);
}
if (options & SO_DEBUG) {
if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof (one)) < 0)
perror("setsockopt (stdin)");
if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one, sizeof (one)) < 0)
perror("setsockopt (stderr)");
}
(void) setuid(getuid());
omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, sendsig);
if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
signal(SIGQUIT, sendsig);
if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
signal(SIGTERM, sendsig);
if (nflag == 0) {
pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
}
}
ioctl(rfd2, FIONBIO, &one);
ioctl(rem, FIONBIO, &one);
if (nflag == 0 && pid == 0) {
char *bp; int rembits, wc;
(void) close(rfd2);
reread:
errno = 0;
cc = read(0, buf[b], BUFSIZE);
#ifdef sgi
if (cc <= 0) {
if (cc == 0)
goto done;
if (errno == EINTR || errno == EAGAIN)
goto reread;
perror("read");
exit(1);
}
bp = buf[b];
#else
if (cc <= 0)
goto done;
bp = buf;
#endif
rewrite:
rembits = 1<<rem;
if (select(16, 0, &rembits, 0, 0) < 0) {
if (errno != EINTR) {
perror("select");
exit(1);
}
goto rewrite;
}
if ((rembits & (1<<rem)) == 0)
goto rewrite;
wc = write(rem, bp, cc);
if (wc < 0) {
if (errno == EWOULDBLOCK)
goto rewrite;
#ifdef sgi
if (errno == EINTR || errno == EAGAIN)
goto rewrite;
#endif /* sgi */
perror("write");
exit(1);
}
cc -= wc; bp += wc;
if (cc == 0) {
b++;
if (b == NBUFS) {
b = 0;
}
goto reread;
}
goto rewrite;
done:
(void) shutdown(rem, 1);
exit(0);
}
sigsetmask(omask);
readfrom = (1<<rfd2) | (1<<rem);
b = 0;
do {
ready = readfrom;
if (select(16, &ready, 0, 0, 0) < 0) {
if (errno != EINTR) {
perror("select");
exit(1);
}
continue;
}
if (ready & (1<<rfd2)) {
errno = 0;
cc = read(rfd2, buf[b], BUFSIZE);
if (cc <= 0) {
#ifdef sgi
if (errno != EWOULDBLOCK && errno != EAGAIN
&& errno != EINTR) {
if (cc < 0) {
perror("read\n");
had_error = 1;
}
readfrom &= ~(1<<rfd2);
shutdown(rfd2,0);
}
#else
if (errno != EWOULDBLOCK)
readfrom &= ~(1<<rfd2);
#endif
} else {
(void) write(2, buf[b], cc);
b++;
if (b == NBUFS) {
b = 0;
}
}
}
if (ready & (1<<rem)) {
errno = 0;
cc = read(rem, buf[b], BUFSIZE);
if (cc <= 0) {
#ifdef sgi
if (errno != EWOULDBLOCK && errno != EAGAIN
&& errno != EINTR) {
if (cc < 0) {
perror("read\n");
had_error = 1;
}
readfrom &= ~(1<<rem);
shutdown(rem,0);
}
#else
if (errno != EWOULDBLOCK)
readfrom &= ~(1<<rem);
#endif
} else {
(void) write(1, buf[b], cc);
b++;
if (b == NBUFS) {
b = 0;
}
}
}
} while (readfrom);
if (nflag == 0)
(void) kill(pid, SIGKILL);
if (had_error)
exit(1);
exit(0);
usage:
#ifdef sgi
fprintf(stderr,
"usage: rsh [ -l username ] [ -n ] host command\n");
fprintf(stderr,
"usage: rsh host [ -l username ] [ -n ] command\n");
fprintf(stderr,
" rsh [ -n ] username@host command\n");
fprintf(stderr,
" rsh username@host [ -n ] command\n");
#else
fprintf(stderr,
"usage: rsh host [ -l login ] [ -n ] command\n");
#endif
exit(1);
}
#ifdef sgi
void
#endif
sendsig(signo)
char signo;
{
(void) write(rfd2, &signo, 1);
}