1 /*
2  * Copyright (c) 1992-1998 Michael A. Cooper.
3  * This software may be freely used and distributed provided it is not
4  * sold for profit or used in part or in whole for commercial gain
5  * without prior written agreement, and the author is credited
6  * appropriately.
7  */
8 /*
9  * This is an rcmd() replacement originally by
10  * Chris Siebenmann <cks@utcc.utoronto.ca>.
11  */
12 
13 #ifndef lint
14 static char RCSid[] =
15 "$Id: rshrcmd.c,v 1.9 1998/11/10 04:15:07 mcooper Exp $";
16 
17 static char copyright[] = "Copyright (c) 1992-1998 Michael A. Cooper.\n";
18 #endif
19 
20 #include	"defs.h"
21 
22 #if	!defined(DIRECT_RCMD)
23 
24 #include      <sys/types.h>
25 #include      <sys/socket.h>
26 #include      <sys/wait.h>
27 #include      <signal.h>
28 #include      <errno.h>
29 #include      <netdb.h>
30 #include      <stdio.h>
31 
32 /*
33  * This is a replacement rcmd() function that uses the rsh(1c)
34  * program in place of a direct rcmd() function call so as to
35  * avoid having to be root.
36  */
rshrcmd(ahost,port,luser,ruser,cmd,fd2p)37 rshrcmd(ahost, port, luser, ruser, cmd, fd2p)
38 	char  	**ahost;
39 	u_short	port;
40 	char	*luser, *ruser, *cmd;
41 	int	*fd2p;
42 {
43 	int             cpid;
44 	int             sp[2];
45 
46 	/* insure that we are indeed being used as we thought. */
47 	if (fd2p != 0)
48 		return -1;
49 
50 	/* get a socketpair we'll use for stdin and stdout. */
51 	if (getsocketpair(AF_UNIX, SOCK_STREAM, 0, sp) < 0) {
52 		error("socketpair(AF_UNIX, SOCK_STREAM, 0) failed: %s.",
53 		      SYSERR);
54 		return -1;
55 	}
56 
57 	cpid = fork();
58 	if (cpid < 0) {
59 		error("fork failed: %s.", SYSERR);
60 		return -1;      /* error. */
61 	}
62 	if (cpid == 0) {
63 		/* child. we use sp[1] to be stdin/stdout, and close
64 		   sp[0]. */
65 		(void) close(sp[0]);
66 		if (dup2(sp[1], 0) < 0 || dup2(0,1) < 0) {
67 			error("dup2 failed: %s.", SYSERR);
68 			_exit(255);
69 		}
70 		/* fork again to lose parent. */
71 		cpid = fork();
72 		if (cpid < 0) {
73 			error("fork to lose parent failed: %s.", SYSERR);
74 			_exit(255);
75 		}
76 		if (cpid > 0)
77 			_exit(0);
78 		/* in grandchild here. */
79 
80 		/*
81 		 * If we are rdist'ing to "localhost" as the same user
82 		 * as we are, then avoid running remote shell for efficiency.
83 		 */
84 		if (strcmp(*ahost, "localhost") == 0 &&
85 		    strcmp(luser, ruser) == 0) {
86 			execlp(_PATH_BSHELL, xbasename(_PATH_BSHELL), "-c",
87 			       cmd, (char *) NULL);
88 			error("execlp %s failed: %s.", _PATH_BSHELL, SYSERR);
89 		} else {
90 			execlp(path_remsh, xbasename(path_remsh),
91 			       *ahost, "-l", ruser, cmd, (char *) NULL);
92 			error("execlp %s failed: %s.", path_remsh, SYSERR);
93 		}
94 		_exit(255);
95 	}
96 	if (cpid > 0) {
97 		/* parent. close sp[1], return sp[0]. */
98 		(void) close(sp[1]);
99 		/* reap child. */
100 		(void) wait(0);
101 		return sp[0];
102 	}
103 	/*NOTREACHED*/
104 }
105 
106 #endif	/* !DIRECT_RCMD */
107