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