diff options
Diffstat (limited to 'usr/src/cmd/rexd/on.c')
| -rw-r--r-- | usr/src/cmd/rexd/on.c | 762 |
1 files changed, 0 insertions, 762 deletions
diff --git a/usr/src/cmd/rexd/on.c b/usr/src/cmd/rexd/on.c deleted file mode 100644 index f436e71126..0000000000 --- a/usr/src/cmd/rexd/on.c +++ /dev/null @@ -1,762 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * on - user interface program for remote execution service - * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#define BSD_COMP - -#include <ctype.h> -#include <errno.h> -#include <netdb.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <netinet/in.h> -#include <rpc/rpc.h> -#include <rpc/clnt_soc.h> -#include <rpc/key_prot.h> -#include <sys/fcntl.h> -#include <sys/ioctl.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <sys/sockio.h> -#include <sys/stat.h> -#include <sys/time.h> - - -#include <sys/ttold.h> - - -#include "rex.h" - -#include <stropts.h> -#include <sys/stream.h> -#include <sys/ttcompat.h> - - -#define bcmp(b1, b2, len) memcmp(b1, b2, len) -#define bzero(b, len) memset(b, '\0', len) -#define bcopy(b1, b2, len) memcpy(b2, b1, len) - -#define CommandName "on" /* given as argv[0] */ -#define AltCommandName "dbon" - -extern int errno; - -/* - * Note - the following must be long enough for at least two portmap - * timeouts on the other side. - */ -struct timeval LongTimeout = { 123, 0 }; -struct timeval testtimeout = { 5, 0 }; - -int Debug = 0; /* print extra debugging information */ -int Only2 = 0; /* stdout and stderr are the same */ -int Interactive = 0; /* use a pty on server */ -int NoInput = 0; /* don't read standard input */ -int child = 0; /* pid of the executed process */ -int ChildDied = 0; /* true when above is valid */ -int HasHelper = 0; /* must kill helpers (interactive mode) */ - -int InOut; /* socket for stdin/stdout */ -int Err; /* socket for stderr */ - -struct sgttyb OldFlags; /* saved tty flags */ -struct sgttyb NewFlags; /* for stop/continue job control */ -CLIENT *Client; /* RPC client handle */ -struct rex_ttysize WindowSize; /* saved window size */ - -static int Argc; -static char **Argv; /* saved argument vector (for ps) */ -static char *LastArgv; /* saved end-of-argument vector */ - -void usage(void); -void Die(int stat); -void doaccept(int *fdp); -u_short makeport(int *fdp); - - -/* - * window change handler - propagate to remote server - */ -void -sigwinch(int junk) -{ - struct winsize newsize; /* the modern way to get row and col */ - struct rex_ttysize size; /* the old way no body */ - /* bothered to change */ - enum clnt_stat clstat; - - ioctl(0, TIOCGWINSZ, &newsize); - - /* - * compensate for the struct change - */ - size.ts_lines = (int)newsize.ws_row; /* typecast important! */ - size.ts_cols = (int)newsize.ws_col; - - if (bcmp(&size, &WindowSize, sizeof (size)) == 0) - return; - - WindowSize = size; - if (clstat = clnt_call(Client, REXPROC_WINCH, - xdr_rex_ttysize, (caddr_t)&size, xdr_void, - NULL, LongTimeout)) { - fprintf(stderr, "on (size): "); - clnt_perrno(clstat); - fprintf(stderr, "\r\n"); - } -} - -/* - * signal handler - propagate to remote server - */ -void -sendsig(int sig) -{ - enum clnt_stat clstat; - - if (clstat = clnt_call(Client, REXPROC_SIGNAL, - xdr_int, (caddr_t) &sig, xdr_void, - NULL, LongTimeout)) { - fprintf(stderr, "on (signal): "); - clnt_perrno(clstat); - fprintf(stderr, "\r\n"); - } -} - - -void -cont(int junk) -{ - /* - * Put tty modes back the way they were and tell the rexd server - * to send the command a SIGCONT signal. - */ - if (Interactive) { - ioctl(0, TIOCSETN, &NewFlags); - (void) send(InOut, "", 1, MSG_OOB); - } -} - -/* - * oob -- called when the command invoked by the rexd server is stopped - * with a SIGTSTP or SIGSTOP signal. - */ -void -oob(int junk) -{ - int atmark; - char waste[BUFSIZ], mark; - - for (;;) { - if (ioctl(InOut, SIOCATMARK, &atmark) < 0) { - perror("ioctl"); - break; - } - if (atmark) - break; - (void) read(InOut, waste, sizeof (waste)); - } - (void) recv(InOut, &mark, 1, MSG_OOB); - /* - * Reset tty modes to something sane and stop myself - */ - if (Interactive) { - ioctl(0, TIOCSETN, &OldFlags); - printf("\r\n"); - } - kill(getpid(), SIGSTOP); -} - - - -int -main(int argc, char **argv) -{ - struct winsize newsize; /* the modern way to get row and col */ - char *rhost, **cmdp; - char curdir[MAXPATHLEN]; - char wdhost[MAXHOSTNAMELEN]; - char fsname[MAXPATHLEN]; - char dirwithin[MAXPATHLEN]; - struct rex_start rst; - struct rex_result result; - extern char **environ; - enum clnt_stat clstat; - struct hostent *hp; - struct sockaddr_in server_addr; - int sock = RPC_ANYSOCK; - fd_set selmask, zmask, remmask; - int nfds, cc; - char *chi, *cho; - int trying_authdes; - char netname[MAXNETNAMELEN+1]; - char hostname[MAXHOSTNAMELEN+1]; - char publickey[HEXKEYBYTES+1]; - int i; - char *domain; - static char buf[4096]; - - /* - * we check the invoked command name to see if it should - * really be a host name. - */ - if ((rhost = strrchr(argv[0], '/')) == NULL) { - rhost = argv[0]; - } else { - rhost++; - } - - /* - * argv start and extent for setproctitle() - */ - Argc = argc; - Argv = argv; - if (argc > 0) - LastArgv = argv[argc-1] + strlen(argv[argc-1]); - else - LastArgv = NULL; - - while (argc > 1 && argv[1][0] == '-') { - switch (argv[1][1]) { - case 'd': Debug = 1; - break; - case 'i': Interactive = 1; - break; - case 'n': NoInput = 1; - break; - default: - printf("Unknown option %s\n", argv[1]); - } - argv++; - argc--; - } - - if (strcmp(rhost, CommandName) && strcmp(rhost, AltCommandName)) { - cmdp = &argv[1]; - Interactive = 1; - } else { - if (argc < 2) - usage(); - rhost = argv[1]; - cmdp = &argv[2]; - } - - /* - * Can only have one of these - */ - if (Interactive && NoInput) - usage(); - - if ((hp = gethostbyname(rhost)) == NULL) { - fprintf(stderr, "on: unknown host %s\n", rhost); - exit(1); - } - - bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr, hp->h_length); - server_addr.sin_family = AF_INET; - server_addr.sin_port = 0; /* use pmapper */ - - if (Debug) - printf("Got the host named %s (%s)\n", - rhost, inet_ntoa(server_addr.sin_addr)); - trying_authdes = 1; - -try_auth_unix: - sock = RPC_ANYSOCK; - - if (Debug) - printf("clnt_create: Server_Addr %u Prog %d Vers %d Sock %d\n", - &server_addr, REXPROG, REXVERS, sock); - - if ((Client = clnttcp_create(&server_addr, REXPROG, REXVERS, &sock, - 0, 0)) == NULL) { - fprintf(stderr, "on: cannot connect to server on %s\n", - rhost); - clnt_pcreateerror("on:"); - exit(1); - } - - if (Debug) - printf("TCP RPC connection created\n"); - - if (trying_authdes) { - yp_get_default_domain(&domain); - - cho = hostname; - *cho = 0; - chi = hp->h_name; - - for (i = 0; (*chi && (i < MAXHOSTNAMELEN)); i++) - { - if (isupper(*chi)) - *cho = tolower(*chi); - else - *cho = *chi; - cho++; - chi++; - } - *cho = 0; - - if (domain != NULL) { - if (host2netname(netname, hostname, domain) == 0) { - trying_authdes = 0; - if (Debug) - printf("host2netname failed %s\n", - hp->h_name); - } - /* #ifdef NOWAY */ - else { - - if (getpublickey(netname, publickey) == 0) { - trying_authdes = 0; - cho = strchr(hostname, '.'); - - if (cho) { - *cho = 0; - - if (!host2netname(netname, - hostname, - domain)) { - if (Debug) - printf("host2netname failed %s\n", hp->h_name); - } else { - if (getpublickey( - netname, - publickey) != 0) - trying_authdes = 1; - } - } - } - } - } else { - trying_authdes = 0; - if (Debug) - printf("yp_get_default_domain failed \n"); - } - } - - if (trying_authdes) { - Client->cl_auth = (AUTH *)authdes_create(netname, 60*60, - &server_addr, NULL); - - if (Client->cl_auth == NULL) { - - if (Debug) - printf("authdes_create failed %s\n", netname); - trying_authdes = 0; - } - } - - - if (trying_authdes == 0) - if ((Client->cl_auth = authsys_create_default()) == NULL) { - clnt_destroy(Client); - fprintf(stderr,"on: can't create authunix structure.\n"); - exit(1); - } - - - /* - * Now that we have created the TCP connection, we do some - * work while the server daemon is being swapped in. - */ - if (getcwd(curdir, MAXPATHLEN) == (char *)NULL) { - fprintf(stderr, "on: can't find . (%s)\n", curdir); - exit(1); - } - - if (findmount(curdir, wdhost, fsname, dirwithin) == 0) { - - if (Debug) { - fprintf(stderr, - "findmount failed: curdir %s\twdhost %s\t", - curdir, wdhost); - fprintf(stderr, "fsname %s\tdirwithin %s\n", - fsname, dirwithin); - } - - fprintf(stderr, "on: can't locate mount point for %s (%s)\n", - curdir, dirwithin); - exit(1); - } - - if (Debug) { - printf("findmount suceeds: cwd= %s, wd host %s, fs %s,", - curdir, wdhost, fsname); - printf("dir within %s\n", dirwithin); - } - - Only2 = samefd(1, 2); - - rst.rst_cmd = (void *)(cmdp); - rst.rst_host = (void *)wdhost; - rst.rst_fsname = (void *)fsname; - rst.rst_dirwithin = (void *)dirwithin; - rst.rst_env = (void *)environ; - rst.rst_port0 = makeport(&InOut); - rst.rst_port1 = rst.rst_port0; /* same port for stdin */ - rst.rst_flags = 0; - - if (Debug) - printf("before Interactive flags\n"); - - if (Interactive) { - rst.rst_flags |= REX_INTERACTIVE; - ioctl(0, TIOCGETP, &OldFlags); - NewFlags = OldFlags; - NewFlags.sg_flags |= (u_int)RAW; - NewFlags.sg_flags &= (u_int)~ECHO; - ioctl(0, TIOCSETN, &NewFlags); - } - - if (Only2) { - rst.rst_port2 = rst.rst_port1; - } else { - rst.rst_port2 = makeport(&Err); - } - - if (Debug) - printf("before client call REXPROC_START\n"); - - (void) memset(&result, '\0', sizeof(result)); - - if (clstat = clnt_call(Client, REXPROC_START, - xdr_rex_start, (caddr_t)&rst, - xdr_rex_result, (caddr_t)&result, LongTimeout)) { - - if (Debug) - printf("Client call failed for REXPROC_START\r\n"); - - if (trying_authdes) { - auth_destroy(Client->cl_auth); - clnt_destroy(Client); - trying_authdes = 0; - if (Interactive) - ioctl(0, TIOCSETN, &OldFlags); - goto try_auth_unix; - } else { - fprintf(stderr, "on %s: ", rhost); - clnt_perrno(clstat); - fprintf(stderr, "\n"); - Die(1); - } - } - - if (result.rlt_stat != 0) { - fprintf(stderr, "on %s: %s\n\r", rhost, result.rlt_message); - Die(1); - } - - clnt_freeres(Client, xdr_rex_result, (caddr_t)&result); - - if (Debug) - printf("Client call suceeded for REXPROC_START\r\n"); - - if (Interactive) { - /* - * Pass the tty modes along to the server - */ - struct rex_ttymode mode; - int err; - - mode.basic.sg_ispeed = OldFlags.sg_ispeed; - mode.basic.sg_ospeed = OldFlags.sg_ospeed; - mode.basic.sg_erase = OldFlags.sg_erase; - mode.basic.sg_kill = OldFlags.sg_kill; - mode.basic.sg_flags = (short) (OldFlags.sg_flags & 0xFFFF); - err = (ioctl(0, TIOCGETC, &mode.more) < 0 || - ioctl(0, TIOCGLTC, &mode.yetmore) < 0 || - ioctl(0, TIOCLGET, &mode.andmore) < 0); - if (Debug) - printf("Before clnt_call(REXPROC_MODES) err=%d\n", err); - - if (!err && (clstat = clnt_call(Client, REXPROC_MODES, - xdr_rex_ttymode, (caddr_t)&mode, - xdr_void, NULL, LongTimeout))) { - - fprintf(stderr, "on (modes) %s: ", rhost); - clnt_perrno(clstat); - fprintf(stderr, "\r\n"); - } - - err = ioctl(0, TIOCGWINSZ, &newsize) < 0; - /* typecast important in following lines */ - WindowSize.ts_lines = (int)newsize.ws_row; - WindowSize.ts_cols = (int)newsize.ws_col; - - if (Debug) - printf("Before client call REXPROC_WINCH\n"); - - if (!err && (clstat = clnt_call(Client, REXPROC_WINCH, - xdr_rex_ttysize, (caddr_t)&WindowSize, - xdr_void, NULL, LongTimeout))) { - - fprintf(stderr, "on (size) %s: ", rhost); - clnt_perrno(clstat); - fprintf(stderr, "\r\n"); - } - - sigset(SIGWINCH, sigwinch); - sigset(SIGINT, sendsig); - sigset(SIGQUIT, sendsig); - sigset(SIGTERM, sendsig); - } - sigset(SIGCONT, cont); - sigset(SIGURG, oob); - doaccept(&InOut); - (void) fcntl(InOut, F_SETOWN, getpid()); - FD_ZERO(&remmask); - FD_SET(InOut, &remmask); - if (Debug) - printf("accept on stdout\r\n"); - - if (!Only2) { - - doaccept(&Err); - shutdown(Err, 1); /* 1=> further sends disallowed */ - if (Debug) - printf("accept on stderr\r\n"); - FD_SET(Err, &remmask); - } - - FD_ZERO(&zmask); - if (NoInput) { - - /* - * no input - simulate end-of-file instead - */ - shutdown(InOut, 1); /* 1=> further sends disallowed */ - } else { - /* - * set up to read standard input, send to remote - */ - FD_SET(0, &zmask); - } - - FD_ZERO(&selmask); - while (FD_ISSET(InOut, &remmask) || FD_ISSET(Err, &remmask)) { - if (FD_ISSET(InOut, &remmask)) - FD_SET(InOut, &selmask); - else - FD_CLR(InOut, &selmask); - if (FD_ISSET(Err, &remmask)) - FD_SET(Err, &selmask); - else - FD_CLR(Err, &selmask); - if (FD_ISSET(0, &zmask)) - FD_SET(0, &selmask); - else - FD_CLR(0, &selmask); - nfds = select(FD_SETSIZE, &selmask, (fd_set *) 0, (fd_set *) 0, - (struct timeval *) 0); - - - if (nfds <= 0) { - if (errno == EINTR) continue; - perror("on: select"); - Die(1); - } - if (FD_ISSET(InOut, &selmask)) { - - cc = read(InOut, buf, sizeof buf); - if (cc > 0) - write(1, buf, cc); - else - FD_CLR(InOut, &remmask); - } - - if (!Only2 && FD_ISSET(Err, &selmask)) { - - cc = read(Err, buf, sizeof buf); - if (cc > 0) - write(2, buf, cc); - else - FD_CLR(Err, &remmask); - } - - if (!NoInput && FD_ISSET(0, &selmask)) { - - cc = read(0, buf, sizeof buf); - if (cc > 0) - write(InOut, buf, cc); - else { - /* - * End of standard input - shutdown outgoing - * direction of the TCP connection. - */ - if (Debug) - printf("Got EOF - shutting down connection\n"); - FD_CLR(0, &zmask); - shutdown(InOut, 1); /* further sends disallowed */ - } - } - } - - close(InOut); - if (!Only2) - close(Err); - - (void) memset(&result, '\0', sizeof(result)); - - if (clstat = clnt_call(Client, REXPROC_WAIT, - xdr_void, 0, xdr_rex_result, (caddr_t)&result, - LongTimeout)) { - - fprintf(stderr, "on: "); - clnt_perrno(clstat); - fprintf(stderr, "\r\n"); - Die(1); - } - Die(result.rlt_stat); - return (0); /* Should never get here. */ -} - -/* - * like exit, but resets the terminal state first - */ -void -Die(int stat) - -{ - if (Interactive) { - ioctl(0, TIOCSETN, &OldFlags); - printf("\r\n"); - } - exit(stat); -} - - -void -remstop() - -{ - Die(23); -} - -/* - * returns true if we can safely say that the two file descriptors - * are the "same" (both are same file). - */ -int -samefd(a, b) -{ - struct stat astat, bstat; - - if (fstat(a, &astat) || fstat(b, &bstat)) - return (0); - if (astat.st_ino == 0 || bstat.st_ino == 0) - return (0); - return (!bcmp(&astat, &bstat, sizeof (astat))); -} - - -/* - * accept the incoming connection on the given - * file descriptor, and return the new file descritpor - */ -void -doaccept(fdp) - int *fdp; -{ - int fd; - - fd = accept(*fdp, 0, 0); - - if (fd < 0) { - perror("accept"); - remstop(); - } - close(*fdp); - *fdp = fd; -} - -/* - * create a socket, and return its the port number. - */ -u_short -makeport(fdp) - int *fdp; -{ - struct sockaddr_in sin; - socklen_t len = (socklen_t)sizeof (sin); - int fd; - - fd = socket(AF_INET, SOCK_STREAM, 0); - - if (fd < 0) { - perror("socket"); - exit(1); - } - - bzero((char *)&sin, sizeof (sin)); - sin.sin_family = AF_INET; - bind(fd, (struct sockaddr *)&sin, sizeof (sin)); - getsockname(fd, (struct sockaddr *)&sin, &len); - listen(fd, 1); - *fdp = fd; - return (htons(sin.sin_port)); -} - -void -usage(void) -{ - fprintf(stderr, "Usage: on [-i|-n] [-d] machine cmd [args]...\n"); - exit(1); -} - -/* - * SETPROCTITLE -- set the title of this process for "ps" - * - * Does nothing if there were not enough arguments on the command - * line for the information. - * - * Side Effects: - * Clobbers argv[] of our main procedure. - */ -void -setproctitle(user, host) - char *user, *host; -{ - register char *tohere; - - tohere = Argv[0]; - if ((int)LastArgv == (int)((char *)NULL) || - (int)(strlen(user) + strlen(host)+3) > (int)(LastArgv - tohere)) - return; - *tohere++ = '-'; /* So ps prints (rpc.rexd) */ - sprintf(tohere, "%s@%s", user, host); - while (*tohere++) /* Skip to end of printf output */ - ; - while (tohere < LastArgv) /* Avoid confusing ps */ - *tohere++ = ' '; -} |
