summaryrefslogtreecommitdiff
path: root/src/rsh-client.c
blob: 512bdad1ee7d9dc03d3902df3aef87060d828c19 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/* CVS rsh client stuff.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.  */

#include <config.h>

#include "cvs.h"
#include "buffer.h"

#ifdef CLIENT_SUPPORT

#include "rsh-client.h"

#ifndef NO_EXT_METHOD

/* Contact the server by starting it with rsh.  */

/* Right now, we have two different definitions for this function,
   depending on whether we start the rsh server using popenRW or not.
   This isn't ideal, and the best thing would probably be to change
   the OS/2 port to be more like the regular Unix client (i.e., by
   implementing piped_child)... but I'm doing something else at the
   moment, and wish to make only one change at a time.  -Karl */

# ifdef START_RSH_WITH_POPEN_RW



/* This is actually a crock -- it's OS/2-specific, for no one else
   uses it.  If I get time, I want to make piped_child and all the
   other stuff in os2/run.c work right.  In the meantime, this gets us
   up and running, and that's most important. */
void
start_rsh_server (cvsroot_t *root, struct buffer **to_server_p,
                  struct buffer **from_server_p)
{
    int pipes[2];
    int child_pid;

    /* If you're working through firewalls, you can set the
       CVS_RSH environment variable to a script which uses rsh to
       invoke another rsh on a proxy machine.  */
    char *cvs_rsh = (root->cvs_rsh != NULL
		     ? root->cvs_rsh : getenv ("CVS_RSH"));
    char *cvs_server = (root->cvs_server != NULL
			? root->cvs_server : getenv ("CVS_SERVER"));
    int i = 0;
    /* This needs to fit "rsh", "-b", "-l", "USER", "host",
       "cmd (w/ args)", and NULL.  We leave some room to grow. */
    char *rsh_argv[10];

    if (!cvs_rsh)
	/* People sometimes suggest or assume that this should default
	   to "remsh" on systems like HPUX in which that is the
	   system-supplied name for the rsh program.  However, that
	   causes various problems (keep in mind that systems such as
	   HPUX might have non-system-supplied versions of "rsh", like
	   a Kerberized one, which one might want to use).  If we
	   based the name on what is found in the PATH of the person
	   who runs configure, that would make it harder to
	   consistently produce the same result in the face of
	   different people producing binary distributions.  If we
	   based it on "remsh" always being the default for HPUX
	   (e.g. based on uname), that might be slightly better but
	   would require us to keep track of what the defaults are for
	   each system type, and probably would cope poorly if the
	   existence of remsh or rsh varies from OS version to OS
	   version.  Therefore, it seems best to have the default
	   remain "rsh", and tell HPUX users to specify remsh, for
	   example in CVS_RSH or other such mechanisms to be devised,
	   if that is what they want (the manual already tells them
	   that).  */
	cvs_rsh = RSH_DFLT;
    if (!cvs_server)
	cvs_server = "cvs";

    /* The command line starts out with rsh. */
    rsh_argv[i++] = cvs_rsh;

#   ifdef RSH_NEEDS_BINARY_FLAG
    /* "-b" for binary, under OS/2. */
    rsh_argv[i++] = "-b";
#   endif /* RSH_NEEDS_BINARY_FLAG */

    /* Then we strcat more things on the end one by one. */
    if (root->username != NULL)
    {
	rsh_argv[i++] = "-l";
	rsh_argv[i++] = root->username;
    }

    rsh_argv[i++] = root->hostname;
    rsh_argv[i++] = cvs_server;
    rsh_argv[i++] = "server";

    /* Mark the end of the arg list. */
    rsh_argv[i]   = NULL;

    if (trace)
    {
	fprintf (stderr, " -> Starting server: ");
	for (i = 0; rsh_argv[i]; i++)
	    fprintf (stderr, "%s ", rsh_argv[i]);
	putc ('\n', stderr);
    }

    /* Do the deed. */
    child_pid = popenRW (rsh_argv, pipes);
    if (child_pid < 0)
	error (1, errno, "cannot start server via rsh");

    /* Give caller the file descriptors in a form it can deal with. */
    make_bufs_from_fds (pipes[0], pipes[1], child_pid, to_server_p,
                        from_server_p, 0);
}

# else /* ! START_RSH_WITH_POPEN_RW */

void
start_rsh_server (cvsroot_t *root, struct buffer **to_server_p,
                  struct buffer **from_server_p)
{
    /* If you're working through firewalls, you can set the
       CVS_RSH environment variable to a script which uses rsh to
       invoke another rsh on a proxy machine.  */
    char *cvs_rsh = (root->cvs_rsh != NULL
		     ? root->cvs_rsh : getenv ("CVS_RSH"));
    char *cvs_server = (root->cvs_server != NULL
			? root->cvs_server : getenv ("CVS_SERVER"));
    char *command;
    int tofd, fromfd;
    int child_pid;

    if (!cvs_rsh)
	cvs_rsh = RSH_DFLT;
    if (!cvs_server)
	cvs_server = "cvs";

    /* Pass the command to rsh as a single string.  This shouldn't
     * affect most rsh servers at all, and will pacify some buggy
     * versions of rsh that grab switches out of the middle of the
     * command (they're calling the GNU getopt routines incorrectly).
     *
     * If you are running a very old (Nov 3, 1994, before 1.5)
     * version of the server, you need to make sure that your .bashrc
     * on the server machine does not set CVSROOT to something
     * containing a colon (or better yet, upgrade the server).
     */
    command = Xasprintf ("%s server", cvs_server);

    {
        char *argv[10];
	char **p = argv;

	*p++ = cvs_rsh;

	/* If the login names differ between client and server
	 * pass it on to rsh.
	 */
	if (root->username != NULL)
	{
	    *p++ = "-l";
	    *p++ = root->username;
	}

	*p++ = root->hostname;
	*p++ = command;
	*p++ = NULL;

	if (trace)
        {
	    int i;

            fprintf (stderr, " -> Starting server: ");
	    for (i = 0; argv[i]; i++)
	        fprintf (stderr, "%s ", argv[i]);
	    putc ('\n', stderr);
	}
	child_pid = piped_child (argv, &tofd, &fromfd, true);

	if (child_pid < 0)
	    error (1, errno, "cannot start server via rsh");
    }
    free (command);

    make_bufs_from_fds (tofd, fromfd, child_pid, root, to_server_p,
                        from_server_p, 0);
}

# endif /* START_RSH_WITH_POPEN_RW */

#endif /* NO_EXT_METHOD */

#endif /* CLIENT_SUPPORT */