update changelog
[alioth/cvs.git] / src / rsh-client.c
1 /* CVS rsh client stuff.
2
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2, or (at your option)
6    any later version.
7
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.  */
12
13 #include <config.h>
14
15 #include "cvs.h"
16 #include "buffer.h"
17
18 #ifdef CLIENT_SUPPORT
19
20 #include "rsh-client.h"
21
22 #ifndef NO_EXT_METHOD
23
24 /* Contact the server by starting it with rsh.  */
25
26 /* Right now, we have two different definitions for this function,
27    depending on whether we start the rsh server using popenRW or not.
28    This isn't ideal, and the best thing would probably be to change
29    the OS/2 port to be more like the regular Unix client (i.e., by
30    implementing piped_child)... but I'm doing something else at the
31    moment, and wish to make only one change at a time.  -Karl */
32
33 # ifdef START_RSH_WITH_POPEN_RW
34
35
36
37 /* This is actually a crock -- it's OS/2-specific, for no one else
38    uses it.  If I get time, I want to make piped_child and all the
39    other stuff in os2/run.c work right.  In the meantime, this gets us
40    up and running, and that's most important. */
41 void
42 start_rsh_server (cvsroot_t *root, struct buffer **to_server_p,
43                   struct buffer **from_server_p)
44 {
45     int pipes[2];
46     int child_pid;
47
48     /* If you're working through firewalls, you can set the
49        CVS_RSH environment variable to a script which uses rsh to
50        invoke another rsh on a proxy machine.  */
51     char *cvs_rsh = (root->cvs_rsh != NULL
52                      ? root->cvs_rsh : getenv ("CVS_RSH"));
53     char *cvs_server = (root->cvs_server != NULL
54                         ? root->cvs_server : getenv ("CVS_SERVER"));
55     int i = 0;
56     /* This needs to fit "rsh", "-b", "-l", "USER", "-p", port, "host",
57        "cmd (w/ args)", and NULL.  We leave some room to grow. */
58     char *rsh_argv[16];
59     char argvport[16];
60
61     if (!cvs_rsh)
62         /* People sometimes suggest or assume that this should default
63            to "remsh" on systems like HPUX in which that is the
64            system-supplied name for the rsh program.  However, that
65            causes various problems (keep in mind that systems such as
66            HPUX might have non-system-supplied versions of "rsh", like
67            a Kerberized one, which one might want to use).  If we
68            based the name on what is found in the PATH of the person
69            who runs configure, that would make it harder to
70            consistently produce the same result in the face of
71            different people producing binary distributions.  If we
72            based it on "remsh" always being the default for HPUX
73            (e.g. based on uname), that might be slightly better but
74            would require us to keep track of what the defaults are for
75            each system type, and probably would cope poorly if the
76            existence of remsh or rsh varies from OS version to OS
77            version.  Therefore, it seems best to have the default
78            remain "rsh", and tell HPUX users to specify remsh, for
79            example in CVS_RSH or other such mechanisms to be devised,
80            if that is what they want (the manual already tells them
81            that).  */
82         cvs_rsh = RSH_DFLT;
83     if (!cvs_server)
84         cvs_server = "cvs";
85
86     /* The command line starts out with rsh. */
87     rsh_argv[i++] = cvs_rsh;
88
89 #   ifdef RSH_NEEDS_BINARY_FLAG
90     /* "-b" for binary, under OS/2. */
91     rsh_argv[i++] = "-b";
92 #   endif /* RSH_NEEDS_BINARY_FLAG */
93
94     /* Then we strcat more things on the end one by one. */
95     if (root->username != NULL)
96     {
97         rsh_argv[i++] = "-l";
98         rsh_argv[i++] = root->username;
99     }
100
101     if (root->method == extssh_method && root->port)
102     {
103         snprintf(argvport, sizeof(argvport), "%d", root->port);
104         rsh_argv[i++] = "-p";
105         rsh_argv[i++] = argvport;
106     }
107
108     rsh_argv[i++] = root->hostname;
109     rsh_argv[i++] = cvs_server;
110     if (readonlyfs)
111         rsh_argv[i++] = "-R";
112     rsh_argv[i++] = "server";
113
114     /* Mark the end of the arg list. */
115     rsh_argv[i]   = NULL;
116
117     if (trace)
118     {
119         fprintf (stderr, " -> Starting server: ");
120         for (i = 0; rsh_argv[i]; i++)
121             fprintf (stderr, "%s ", rsh_argv[i]);
122         putc ('\n', stderr);
123     }
124
125     /* Do the deed. */
126     child_pid = popenRW (rsh_argv, pipes);
127     if (child_pid < 0)
128         error (1, errno, "cannot start server via rsh");
129
130     /* Give caller the file descriptors in a form it can deal with. */
131     make_bufs_from_fds (pipes[0], pipes[1], child_pid, to_server_p,
132                         from_server_p, 0);
133 }
134
135 # else /* ! START_RSH_WITH_POPEN_RW */
136
137 void
138 start_rsh_server (cvsroot_t *root, struct buffer **to_server_p,
139                   struct buffer **from_server_p)
140 {
141     /* If you're working through firewalls, you can set the
142        CVS_RSH environment variable to a script which uses rsh to
143        invoke another rsh on a proxy machine.  */
144     char *cvs_rsh = (root->cvs_rsh != NULL
145                      ? root->cvs_rsh : getenv ("CVS_RSH"));
146     char *cvs_server = (root->cvs_server != NULL
147                         ? root->cvs_server : getenv ("CVS_SERVER"));
148     char *command;
149     int tofd, fromfd;
150     int child_pid;
151
152     if (!cvs_rsh)
153         cvs_rsh = RSH_DFLT;
154     if (!cvs_server)
155         cvs_server = "cvs";
156
157     /* Pass the command to rsh as a single string.  This shouldn't
158      * affect most rsh servers at all, and will pacify some buggy
159      * versions of rsh that grab switches out of the middle of the
160      * command (they're calling the GNU getopt routines incorrectly).
161      *
162      * If you are running a very old (Nov 3, 1994, before 1.5)
163      * version of the server, you need to make sure that your .bashrc
164      * on the server machine does not set CVSROOT to something
165      * containing a colon (or better yet, upgrade the server).
166      */
167     command = Xasprintf ("%s%s server", cvs_server, readonlyfs ? " -R" : "");
168
169     {
170         char argvport[16];
171         char *argv[16];
172         char **p = argv;
173
174         *p++ = cvs_rsh;
175
176         /* If the login names differ between client and server
177          * pass it on to rsh.
178          */
179         if (root->username != NULL)
180         {
181             *p++ = "-l";
182             *p++ = root->username;
183         }
184
185         if (root->method == extssh_method && root->port)
186         {
187                 snprintf(argvport, sizeof(argvport), "%d", root->port);
188                 *p++ = "-p";
189                 *p++ = argvport;
190         }
191
192         *p++ = root->hostname;
193         *p++ = command;
194         *p++ = NULL;
195
196         if (trace)
197         {
198             int i;
199
200             fprintf (stderr, " -> Starting server: ");
201             for (i = 0; argv[i]; i++)
202                 fprintf (stderr, "%s ", argv[i]);
203             putc ('\n', stderr);
204         }
205         child_pid = piped_child (argv, &tofd, &fromfd, true);
206
207         if (child_pid < 0)
208             error (1, errno, "cannot start server via rsh");
209     }
210     free (command);
211
212     make_bufs_from_fds (tofd, fromfd, child_pid, root, to_server_p,
213                         from_server_p, 0);
214 }
215
216 # endif /* START_RSH_WITH_POPEN_RW */
217
218 #endif /* NO_EXT_METHOD */
219
220 #endif /* CLIENT_SUPPORT */