15e9cd1aeSAssar Westerlund /*
25e9cd1aeSAssar Westerlund * Copyright (c) 1983, 1990, 1992, 1993
35e9cd1aeSAssar Westerlund * The Regents of the University of California. All rights reserved.
45e9cd1aeSAssar Westerlund *
55e9cd1aeSAssar Westerlund * Redistribution and use in source and binary forms, with or without
65e9cd1aeSAssar Westerlund * modification, are permitted provided that the following conditions
75e9cd1aeSAssar Westerlund * are met:
85e9cd1aeSAssar Westerlund * 1. Redistributions of source code must retain the above copyright
95e9cd1aeSAssar Westerlund * notice, this list of conditions and the following disclaimer.
105e9cd1aeSAssar Westerlund * 2. Redistributions in binary form must reproduce the above copyright
115e9cd1aeSAssar Westerlund * notice, this list of conditions and the following disclaimer in the
125e9cd1aeSAssar Westerlund * documentation and/or other materials provided with the distribution.
13*ae771770SStanislav Sedov * 3. Neither the name of the University nor the names of its contributors
145e9cd1aeSAssar Westerlund * may be used to endorse or promote products derived from this software
155e9cd1aeSAssar Westerlund * without specific prior written permission.
165e9cd1aeSAssar Westerlund *
175e9cd1aeSAssar Westerlund * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
185e9cd1aeSAssar Westerlund * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
195e9cd1aeSAssar Westerlund * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
205e9cd1aeSAssar Westerlund * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
215e9cd1aeSAssar Westerlund * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
225e9cd1aeSAssar Westerlund * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
235e9cd1aeSAssar Westerlund * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
245e9cd1aeSAssar Westerlund * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
255e9cd1aeSAssar Westerlund * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
265e9cd1aeSAssar Westerlund * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
275e9cd1aeSAssar Westerlund * SUCH DAMAGE.
285e9cd1aeSAssar Westerlund */
295e9cd1aeSAssar Westerlund
305e9cd1aeSAssar Westerlund #include "rcp_locl.h"
31adb0ddaeSAssar Westerlund #include <getarg.h>
325e9cd1aeSAssar Westerlund
335e9cd1aeSAssar Westerlund #define RSH_PROGRAM "rsh"
345e9cd1aeSAssar Westerlund
355e9cd1aeSAssar Westerlund struct passwd *pwd;
365e9cd1aeSAssar Westerlund uid_t userid;
375e9cd1aeSAssar Westerlund int errs, remin, remout;
385e9cd1aeSAssar Westerlund int pflag, iamremote, iamrecursive, targetshouldbedirectory;
395e9cd1aeSAssar Westerlund int doencrypt, noencrypt;
40bbd80c28SJacques Vidrine int usebroken, usekrb4, usekrb5, forwardtkt;
415e9cd1aeSAssar Westerlund char *port;
42c19800e8SDoug Rabson int eflag = 0;
435e9cd1aeSAssar Westerlund
445e9cd1aeSAssar Westerlund #define CMDNEEDS 64
455e9cd1aeSAssar Westerlund char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
465e9cd1aeSAssar Westerlund
475e9cd1aeSAssar Westerlund int response (void);
485e9cd1aeSAssar Westerlund void rsource (char *, struct stat *);
495e9cd1aeSAssar Westerlund void sink (int, char *[]);
505e9cd1aeSAssar Westerlund void source (int, char *[]);
515e9cd1aeSAssar Westerlund void tolocal (int, char *[]);
525e9cd1aeSAssar Westerlund void toremote (char *, int, char *[]);
535e9cd1aeSAssar Westerlund
545e9cd1aeSAssar Westerlund int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout);
555e9cd1aeSAssar Westerlund
56adb0ddaeSAssar Westerlund static int fflag, tflag;
575e9cd1aeSAssar Westerlund
58adb0ddaeSAssar Westerlund static int version_flag, help_flag;
59adb0ddaeSAssar Westerlund
60adb0ddaeSAssar Westerlund struct getargs args[] = {
61bbd80c28SJacques Vidrine { NULL, '4', arg_flag, &usekrb4, "use Kerberos 4 authentication" },
62adb0ddaeSAssar Westerlund { NULL, '5', arg_flag, &usekrb5, "use Kerberos 5 authentication" },
63adb0ddaeSAssar Westerlund { NULL, 'F', arg_flag, &forwardtkt, "forward credentials" },
64adb0ddaeSAssar Westerlund { NULL, 'K', arg_flag, &usebroken, "use BSD authentication" },
65adb0ddaeSAssar Westerlund { NULL, 'P', arg_string, &port, "non-default port", "port" },
66adb0ddaeSAssar Westerlund { NULL, 'p', arg_flag, &pflag, "preserve file permissions" },
67adb0ddaeSAssar Westerlund { NULL, 'r', arg_flag, &iamrecursive, "recursive mode" },
68adb0ddaeSAssar Westerlund { NULL, 'x', arg_flag, &doencrypt, "use encryption" },
69adb0ddaeSAssar Westerlund { NULL, 'z', arg_flag, &noencrypt, "don't encrypt" },
70adb0ddaeSAssar Westerlund { NULL, 'd', arg_flag, &targetshouldbedirectory },
71c19800e8SDoug Rabson { NULL, 'e', arg_flag, &eflag, "passed to rsh" },
72adb0ddaeSAssar Westerlund { NULL, 'f', arg_flag, &fflag },
73adb0ddaeSAssar Westerlund { NULL, 't', arg_flag, &tflag },
74adb0ddaeSAssar Westerlund { "version", 0, arg_flag, &version_flag },
75adb0ddaeSAssar Westerlund { "help", 0, arg_flag, &help_flag }
76adb0ddaeSAssar Westerlund };
77adb0ddaeSAssar Westerlund
78adb0ddaeSAssar Westerlund static void
usage(int ret)79adb0ddaeSAssar Westerlund usage (int ret)
80adb0ddaeSAssar Westerlund {
81adb0ddaeSAssar Westerlund arg_printusage (args,
82adb0ddaeSAssar Westerlund sizeof(args) / sizeof(args[0]),
83adb0ddaeSAssar Westerlund NULL,
84adb0ddaeSAssar Westerlund "file1 file2|file... directory");
85adb0ddaeSAssar Westerlund exit (ret);
865e9cd1aeSAssar Westerlund }
87adb0ddaeSAssar Westerlund
88adb0ddaeSAssar Westerlund int
main(int argc,char ** argv)89adb0ddaeSAssar Westerlund main(int argc, char **argv)
90adb0ddaeSAssar Westerlund {
91adb0ddaeSAssar Westerlund char *targ;
92adb0ddaeSAssar Westerlund int optind = 0;
93adb0ddaeSAssar Westerlund
944137ff4cSJacques Vidrine setprogname(argv[0]);
95adb0ddaeSAssar Westerlund if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
96adb0ddaeSAssar Westerlund &optind))
97adb0ddaeSAssar Westerlund usage (1);
98adb0ddaeSAssar Westerlund if(help_flag)
99adb0ddaeSAssar Westerlund usage(0);
100adb0ddaeSAssar Westerlund if (version_flag) {
101adb0ddaeSAssar Westerlund print_version (NULL);
102adb0ddaeSAssar Westerlund return 0;
103adb0ddaeSAssar Westerlund }
104adb0ddaeSAssar Westerlund
105adb0ddaeSAssar Westerlund iamremote = (fflag || tflag);
106adb0ddaeSAssar Westerlund
1075e9cd1aeSAssar Westerlund argc -= optind;
1085e9cd1aeSAssar Westerlund argv += optind;
1095e9cd1aeSAssar Westerlund
1105e9cd1aeSAssar Westerlund if ((pwd = getpwuid(userid = getuid())) == NULL)
1115e9cd1aeSAssar Westerlund errx(1, "unknown user %d", (int)userid);
1125e9cd1aeSAssar Westerlund
1135e9cd1aeSAssar Westerlund remin = STDIN_FILENO; /* XXX */
1145e9cd1aeSAssar Westerlund remout = STDOUT_FILENO;
1155e9cd1aeSAssar Westerlund
1165e9cd1aeSAssar Westerlund if (fflag) { /* Follow "protocol", send data. */
117*ae771770SStanislav Sedov (void)response();
1185e9cd1aeSAssar Westerlund source(argc, argv);
1195e9cd1aeSAssar Westerlund exit(errs);
1205e9cd1aeSAssar Westerlund }
1215e9cd1aeSAssar Westerlund
1225e9cd1aeSAssar Westerlund if (tflag) { /* Receive data. */
1235e9cd1aeSAssar Westerlund sink(argc, argv);
1245e9cd1aeSAssar Westerlund exit(errs);
1255e9cd1aeSAssar Westerlund }
1265e9cd1aeSAssar Westerlund
1275e9cd1aeSAssar Westerlund if (argc < 2)
128adb0ddaeSAssar Westerlund usage(1);
1295e9cd1aeSAssar Westerlund if (argc > 2)
1305e9cd1aeSAssar Westerlund targetshouldbedirectory = 1;
1315e9cd1aeSAssar Westerlund
1325e9cd1aeSAssar Westerlund remin = remout = -1;
1335e9cd1aeSAssar Westerlund /* Command to be executed on remote system using "rsh". */
1344137ff4cSJacques Vidrine snprintf(cmd, sizeof(cmd),
1354137ff4cSJacques Vidrine "rcp%s%s%s", iamrecursive ? " -r" : "",
1365e9cd1aeSAssar Westerlund pflag ? " -p" : "", targetshouldbedirectory ? " -d" : "");
1375e9cd1aeSAssar Westerlund
138adb0ddaeSAssar Westerlund signal(SIGPIPE, lostconn);
1395e9cd1aeSAssar Westerlund
1405e9cd1aeSAssar Westerlund if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */
1415e9cd1aeSAssar Westerlund toremote(targ, argc, argv);
1425e9cd1aeSAssar Westerlund else {
1435e9cd1aeSAssar Westerlund tolocal(argc, argv); /* Dest is local host. */
1445e9cd1aeSAssar Westerlund if (targetshouldbedirectory)
1455e9cd1aeSAssar Westerlund verifydir(argv[argc - 1]);
1465e9cd1aeSAssar Westerlund }
1475e9cd1aeSAssar Westerlund exit(errs);
1485e9cd1aeSAssar Westerlund }
1495e9cd1aeSAssar Westerlund
1505e9cd1aeSAssar Westerlund void
toremote(char * targ,int argc,char ** argv)151adb0ddaeSAssar Westerlund toremote(char *targ, int argc, char **argv)
1525e9cd1aeSAssar Westerlund {
1534137ff4cSJacques Vidrine int i;
1545e9cd1aeSAssar Westerlund char *bp, *host, *src, *suser, *thost, *tuser;
1555e9cd1aeSAssar Westerlund
1565e9cd1aeSAssar Westerlund *targ++ = 0;
1575e9cd1aeSAssar Westerlund if (*targ == 0)
1585e9cd1aeSAssar Westerlund targ = ".";
1595e9cd1aeSAssar Westerlund
160*ae771770SStanislav Sedov if ((thost = strchr(argv[argc - 1], '@')) != NULL) {
1615e9cd1aeSAssar Westerlund /* user@host */
1625e9cd1aeSAssar Westerlund *thost++ = 0;
1635e9cd1aeSAssar Westerlund tuser = argv[argc - 1];
1645e9cd1aeSAssar Westerlund if (*tuser == '\0')
1655e9cd1aeSAssar Westerlund tuser = NULL;
1665e9cd1aeSAssar Westerlund else if (!okname(tuser))
1675e9cd1aeSAssar Westerlund exit(1);
1685e9cd1aeSAssar Westerlund } else {
1695e9cd1aeSAssar Westerlund thost = argv[argc - 1];
1705e9cd1aeSAssar Westerlund tuser = NULL;
1715e9cd1aeSAssar Westerlund }
172*ae771770SStanislav Sedov thost = unbracket(thost);
1735e9cd1aeSAssar Westerlund
1745e9cd1aeSAssar Westerlund for (i = 0; i < argc - 1; i++) {
1755e9cd1aeSAssar Westerlund src = colon(argv[i]);
1765e9cd1aeSAssar Westerlund if (src) { /* remote to remote */
177c19800e8SDoug Rabson int ret;
1785e9cd1aeSAssar Westerlund *src++ = 0;
1795e9cd1aeSAssar Westerlund if (*src == 0)
1805e9cd1aeSAssar Westerlund src = ".";
1815e9cd1aeSAssar Westerlund host = strchr(argv[i], '@');
1825e9cd1aeSAssar Westerlund if (host) {
1834137ff4cSJacques Vidrine *host++ = '\0';
184*ae771770SStanislav Sedov host = unbracket(host);
1855e9cd1aeSAssar Westerlund suser = argv[i];
1865e9cd1aeSAssar Westerlund if (*suser == '\0')
1875e9cd1aeSAssar Westerlund suser = pwd->pw_name;
1885e9cd1aeSAssar Westerlund else if (!okname(suser))
1895e9cd1aeSAssar Westerlund continue;
190c19800e8SDoug Rabson ret = asprintf(&bp,
191c19800e8SDoug Rabson "%s%s %s -l %s -n %s %s '%s%s%s:%s'",
192c19800e8SDoug Rabson _PATH_RSH, eflag ? " -e" : "",
193c19800e8SDoug Rabson host, suser, cmd, src,
1945e9cd1aeSAssar Westerlund tuser ? tuser : "", tuser ? "@" : "",
1955e9cd1aeSAssar Westerlund thost, targ);
1964137ff4cSJacques Vidrine } else {
197*ae771770SStanislav Sedov host = unbracket(argv[i]);
198c19800e8SDoug Rabson ret = asprintf(&bp,
199c19800e8SDoug Rabson "exec %s%s %s -n %s %s '%s%s%s:%s'",
200c19800e8SDoug Rabson _PATH_RSH, eflag ? " -e" : "",
201*ae771770SStanislav Sedov host, cmd, src,
2025e9cd1aeSAssar Westerlund tuser ? tuser : "", tuser ? "@" : "",
2035e9cd1aeSAssar Westerlund thost, targ);
2044137ff4cSJacques Vidrine }
205c19800e8SDoug Rabson if (ret == -1)
2064137ff4cSJacques Vidrine err (1, "malloc");
207*ae771770SStanislav Sedov susystem(bp);
208adb0ddaeSAssar Westerlund free(bp);
2095e9cd1aeSAssar Westerlund } else { /* local to remote */
2105e9cd1aeSAssar Westerlund if (remin == -1) {
211c19800e8SDoug Rabson if (asprintf(&bp, "%s -t %s", cmd, targ) == -1)
2125e9cd1aeSAssar Westerlund err (1, "malloc");
2135e9cd1aeSAssar Westerlund host = thost;
2145e9cd1aeSAssar Westerlund
2155e9cd1aeSAssar Westerlund if (do_cmd(host, tuser, bp, &remin, &remout) < 0)
2165e9cd1aeSAssar Westerlund exit(1);
2175e9cd1aeSAssar Westerlund
2185e9cd1aeSAssar Westerlund if (response() < 0)
2195e9cd1aeSAssar Westerlund exit(1);
220adb0ddaeSAssar Westerlund free(bp);
2215e9cd1aeSAssar Westerlund }
2225e9cd1aeSAssar Westerlund source(1, argv+i);
2235e9cd1aeSAssar Westerlund }
2245e9cd1aeSAssar Westerlund }
2255e9cd1aeSAssar Westerlund }
2265e9cd1aeSAssar Westerlund
2275e9cd1aeSAssar Westerlund void
tolocal(int argc,char ** argv)228adb0ddaeSAssar Westerlund tolocal(int argc, char **argv)
2295e9cd1aeSAssar Westerlund {
2304137ff4cSJacques Vidrine int i;
2315e9cd1aeSAssar Westerlund char *bp, *host, *src, *suser;
2325e9cd1aeSAssar Westerlund
2335e9cd1aeSAssar Westerlund for (i = 0; i < argc - 1; i++) {
234c19800e8SDoug Rabson int ret;
235c19800e8SDoug Rabson
2365e9cd1aeSAssar Westerlund if (!(src = colon(argv[i]))) { /* Local to local. */
237c19800e8SDoug Rabson ret = asprintf(&bp, "exec %s%s%s %s %s", _PATH_CP,
2385e9cd1aeSAssar Westerlund iamrecursive ? " -PR" : "", pflag ? " -p" : "",
2395e9cd1aeSAssar Westerlund argv[i], argv[argc - 1]);
240c19800e8SDoug Rabson if (ret == -1)
2414137ff4cSJacques Vidrine err (1, "malloc");
242*ae771770SStanislav Sedov if (susystem(bp))
2435e9cd1aeSAssar Westerlund ++errs;
244adb0ddaeSAssar Westerlund free(bp);
2455e9cd1aeSAssar Westerlund continue;
2465e9cd1aeSAssar Westerlund }
2475e9cd1aeSAssar Westerlund *src++ = 0;
2485e9cd1aeSAssar Westerlund if (*src == 0)
2495e9cd1aeSAssar Westerlund src = ".";
2505e9cd1aeSAssar Westerlund if ((host = strchr(argv[i], '@')) == NULL) {
2515e9cd1aeSAssar Westerlund host = argv[i];
2525e9cd1aeSAssar Westerlund suser = pwd->pw_name;
2535e9cd1aeSAssar Westerlund } else {
2545e9cd1aeSAssar Westerlund *host++ = 0;
2555e9cd1aeSAssar Westerlund suser = argv[i];
2565e9cd1aeSAssar Westerlund if (*suser == '\0')
2575e9cd1aeSAssar Westerlund suser = pwd->pw_name;
2585e9cd1aeSAssar Westerlund else if (!okname(suser))
2595e9cd1aeSAssar Westerlund continue;
2605e9cd1aeSAssar Westerlund }
261c19800e8SDoug Rabson ret = asprintf(&bp, "%s -f %s", cmd, src);
262c19800e8SDoug Rabson if (ret == -1)
2635e9cd1aeSAssar Westerlund err (1, "malloc");
2645e9cd1aeSAssar Westerlund if (do_cmd(host, suser, bp, &remin, &remout) < 0) {
265adb0ddaeSAssar Westerlund free(bp);
2665e9cd1aeSAssar Westerlund ++errs;
2675e9cd1aeSAssar Westerlund continue;
2685e9cd1aeSAssar Westerlund }
269adb0ddaeSAssar Westerlund free(bp);
2705e9cd1aeSAssar Westerlund sink(1, argv + argc - 1);
271adb0ddaeSAssar Westerlund close(remin);
2725e9cd1aeSAssar Westerlund remin = remout = -1;
2735e9cd1aeSAssar Westerlund }
2745e9cd1aeSAssar Westerlund }
2755e9cd1aeSAssar Westerlund
2765e9cd1aeSAssar Westerlund void
source(int argc,char ** argv)277adb0ddaeSAssar Westerlund source(int argc, char **argv)
2785e9cd1aeSAssar Westerlund {
2795e9cd1aeSAssar Westerlund struct stat stb;
2805e9cd1aeSAssar Westerlund static BUF buffer;
2815e9cd1aeSAssar Westerlund BUF *bp;
2825e9cd1aeSAssar Westerlund off_t i;
283*ae771770SStanislav Sedov off_t amt;
284*ae771770SStanislav Sedov int fd, haderr, indx, result;
2855e9cd1aeSAssar Westerlund char *last, *name, buf[BUFSIZ];
2865e9cd1aeSAssar Westerlund
2875e9cd1aeSAssar Westerlund for (indx = 0; indx < argc; ++indx) {
2885e9cd1aeSAssar Westerlund name = argv[indx];
2895e9cd1aeSAssar Westerlund if ((fd = open(name, O_RDONLY, 0)) < 0)
2905e9cd1aeSAssar Westerlund goto syserr;
2915e9cd1aeSAssar Westerlund if (fstat(fd, &stb)) {
2925e9cd1aeSAssar Westerlund syserr: run_err("%s: %s", name, strerror(errno));
2935e9cd1aeSAssar Westerlund goto next;
2945e9cd1aeSAssar Westerlund }
295*ae771770SStanislav Sedov if (S_ISDIR(stb.st_mode) && iamrecursive) {
2965e9cd1aeSAssar Westerlund rsource(name, &stb);
2975e9cd1aeSAssar Westerlund goto next;
298*ae771770SStanislav Sedov } else if (!S_ISREG(stb.st_mode)) {
2995e9cd1aeSAssar Westerlund run_err("%s: not a regular file", name);
3005e9cd1aeSAssar Westerlund goto next;
3015e9cd1aeSAssar Westerlund }
3025e9cd1aeSAssar Westerlund if ((last = strrchr(name, '/')) == NULL)
3035e9cd1aeSAssar Westerlund last = name;
3045e9cd1aeSAssar Westerlund else
3055e9cd1aeSAssar Westerlund ++last;
3065e9cd1aeSAssar Westerlund if (pflag) {
3075e9cd1aeSAssar Westerlund /*
3085e9cd1aeSAssar Westerlund * Make it compatible with possible future
3095e9cd1aeSAssar Westerlund * versions expecting microseconds.
3105e9cd1aeSAssar Westerlund */
311adb0ddaeSAssar Westerlund snprintf(buf, sizeof(buf), "T%ld 0 %ld 0\n",
3125e9cd1aeSAssar Westerlund (long)stb.st_mtime,
3135e9cd1aeSAssar Westerlund (long)stb.st_atime);
314adb0ddaeSAssar Westerlund write(remout, buf, strlen(buf));
3155e9cd1aeSAssar Westerlund if (response() < 0)
3165e9cd1aeSAssar Westerlund goto next;
3175e9cd1aeSAssar Westerlund }
318c19800e8SDoug Rabson #undef MODEMASK
3195e9cd1aeSAssar Westerlund #define MODEMASK (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
3204137ff4cSJacques Vidrine snprintf(buf, sizeof(buf), "C%04o %lu %s\n",
321*ae771770SStanislav Sedov (unsigned int)(stb.st_mode & MODEMASK),
3224137ff4cSJacques Vidrine (unsigned long)stb.st_size,
3234137ff4cSJacques Vidrine last);
324adb0ddaeSAssar Westerlund write(remout, buf, strlen(buf));
3255e9cd1aeSAssar Westerlund if (response() < 0)
3265e9cd1aeSAssar Westerlund goto next;
3275e9cd1aeSAssar Westerlund if ((bp = allocbuf(&buffer, fd, BUFSIZ)) == NULL) {
328adb0ddaeSAssar Westerlund next: close(fd);
3295e9cd1aeSAssar Westerlund continue;
3305e9cd1aeSAssar Westerlund }
3315e9cd1aeSAssar Westerlund
3325e9cd1aeSAssar Westerlund /* Keep writing after an error so that we stay sync'd up. */
3335e9cd1aeSAssar Westerlund for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
3345e9cd1aeSAssar Westerlund amt = bp->cnt;
3355e9cd1aeSAssar Westerlund if (i + amt > stb.st_size)
3365e9cd1aeSAssar Westerlund amt = stb.st_size - i;
3375e9cd1aeSAssar Westerlund if (!haderr) {
338*ae771770SStanislav Sedov result = read(fd, bp->buf, (size_t)amt);
3395e9cd1aeSAssar Westerlund if (result != amt)
3405e9cd1aeSAssar Westerlund haderr = result >= 0 ? EIO : errno;
3415e9cd1aeSAssar Westerlund }
3425e9cd1aeSAssar Westerlund if (haderr)
343adb0ddaeSAssar Westerlund write(remout, bp->buf, amt);
3445e9cd1aeSAssar Westerlund else {
345*ae771770SStanislav Sedov result = write(remout, bp->buf, (size_t)amt);
3465e9cd1aeSAssar Westerlund if (result != amt)
3475e9cd1aeSAssar Westerlund haderr = result >= 0 ? EIO : errno;
3485e9cd1aeSAssar Westerlund }
3495e9cd1aeSAssar Westerlund }
3505e9cd1aeSAssar Westerlund if (close(fd) && !haderr)
3515e9cd1aeSAssar Westerlund haderr = errno;
3525e9cd1aeSAssar Westerlund if (!haderr)
353adb0ddaeSAssar Westerlund write(remout, "", 1);
3545e9cd1aeSAssar Westerlund else
3555e9cd1aeSAssar Westerlund run_err("%s: %s", name, strerror(haderr));
356adb0ddaeSAssar Westerlund response();
3575e9cd1aeSAssar Westerlund }
3585e9cd1aeSAssar Westerlund }
3595e9cd1aeSAssar Westerlund
3605e9cd1aeSAssar Westerlund void
rsource(char * name,struct stat * statp)361adb0ddaeSAssar Westerlund rsource(char *name, struct stat *statp)
3625e9cd1aeSAssar Westerlund {
3635e9cd1aeSAssar Westerlund DIR *dirp;
3645e9cd1aeSAssar Westerlund struct dirent *dp;
3655e9cd1aeSAssar Westerlund char *last, *vect[1], path[MAXPATHLEN];
3665e9cd1aeSAssar Westerlund
3675e9cd1aeSAssar Westerlund if (!(dirp = opendir(name))) {
3685e9cd1aeSAssar Westerlund run_err("%s: %s", name, strerror(errno));
3695e9cd1aeSAssar Westerlund return;
3705e9cd1aeSAssar Westerlund }
3715e9cd1aeSAssar Westerlund last = strrchr(name, '/');
3725e9cd1aeSAssar Westerlund if (last == 0)
3735e9cd1aeSAssar Westerlund last = name;
3745e9cd1aeSAssar Westerlund else
3755e9cd1aeSAssar Westerlund last++;
3765e9cd1aeSAssar Westerlund if (pflag) {
377adb0ddaeSAssar Westerlund snprintf(path, sizeof(path), "T%ld 0 %ld 0\n",
3785e9cd1aeSAssar Westerlund (long)statp->st_mtime,
3795e9cd1aeSAssar Westerlund (long)statp->st_atime);
380adb0ddaeSAssar Westerlund write(remout, path, strlen(path));
3815e9cd1aeSAssar Westerlund if (response() < 0) {
3825e9cd1aeSAssar Westerlund closedir(dirp);
3835e9cd1aeSAssar Westerlund return;
3845e9cd1aeSAssar Westerlund }
3855e9cd1aeSAssar Westerlund }
386adb0ddaeSAssar Westerlund snprintf(path, sizeof(path),
387*ae771770SStanislav Sedov "D%04o %d %s\n",
388*ae771770SStanislav Sedov (unsigned int)(statp->st_mode & MODEMASK), 0, last);
389adb0ddaeSAssar Westerlund write(remout, path, strlen(path));
3905e9cd1aeSAssar Westerlund if (response() < 0) {
3915e9cd1aeSAssar Westerlund closedir(dirp);
3925e9cd1aeSAssar Westerlund return;
3935e9cd1aeSAssar Westerlund }
394*ae771770SStanislav Sedov while ((dp = readdir(dirp)) != NULL) {
3955e9cd1aeSAssar Westerlund if (dp->d_ino == 0)
3965e9cd1aeSAssar Westerlund continue;
3975e9cd1aeSAssar Westerlund if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
3985e9cd1aeSAssar Westerlund continue;
3995e9cd1aeSAssar Westerlund if (strlen(name) + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) {
4005e9cd1aeSAssar Westerlund run_err("%s/%s: name too long", name, dp->d_name);
4015e9cd1aeSAssar Westerlund continue;
4025e9cd1aeSAssar Westerlund }
403adb0ddaeSAssar Westerlund snprintf(path, sizeof(path), "%s/%s", name, dp->d_name);
4045e9cd1aeSAssar Westerlund vect[0] = path;
4055e9cd1aeSAssar Westerlund source(1, vect);
4065e9cd1aeSAssar Westerlund }
407adb0ddaeSAssar Westerlund closedir(dirp);
408adb0ddaeSAssar Westerlund write(remout, "E\n", 2);
409adb0ddaeSAssar Westerlund response();
4105e9cd1aeSAssar Westerlund }
4115e9cd1aeSAssar Westerlund
4125e9cd1aeSAssar Westerlund void
sink(int argc,char ** argv)413adb0ddaeSAssar Westerlund sink(int argc, char **argv)
4145e9cd1aeSAssar Westerlund {
4155e9cd1aeSAssar Westerlund static BUF buffer;
4165e9cd1aeSAssar Westerlund struct stat stb;
4175e9cd1aeSAssar Westerlund struct timeval tv[2];
4185e9cd1aeSAssar Westerlund enum { YES, NO, DISPLAYED } wrerr;
4195e9cd1aeSAssar Westerlund BUF *bp;
4205e9cd1aeSAssar Westerlund off_t i, j, size;
4215e9cd1aeSAssar Westerlund int amt, count, exists, first, mask, mode, ofd, omode;
4225e9cd1aeSAssar Westerlund int setimes, targisdir, wrerrno = 0;
4235e9cd1aeSAssar Westerlund char ch, *cp, *np, *targ, *why, *vect[1], buf[BUFSIZ];
4245e9cd1aeSAssar Westerlund
4255e9cd1aeSAssar Westerlund #define atime tv[0]
4265e9cd1aeSAssar Westerlund #define mtime tv[1]
4275e9cd1aeSAssar Westerlund #define SCREWUP(str) { why = str; goto screwup; }
4285e9cd1aeSAssar Westerlund
4295e9cd1aeSAssar Westerlund setimes = targisdir = 0;
4305e9cd1aeSAssar Westerlund mask = umask(0);
4315e9cd1aeSAssar Westerlund if (!pflag)
432adb0ddaeSAssar Westerlund umask(mask);
4335e9cd1aeSAssar Westerlund if (argc != 1) {
4345e9cd1aeSAssar Westerlund run_err("ambiguous target");
4355e9cd1aeSAssar Westerlund exit(1);
4365e9cd1aeSAssar Westerlund }
4375e9cd1aeSAssar Westerlund targ = *argv;
4385e9cd1aeSAssar Westerlund if (targetshouldbedirectory)
4395e9cd1aeSAssar Westerlund verifydir(targ);
440adb0ddaeSAssar Westerlund write(remout, "", 1);
4415e9cd1aeSAssar Westerlund if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
4425e9cd1aeSAssar Westerlund targisdir = 1;
4435e9cd1aeSAssar Westerlund for (first = 1;; first = 0) {
4445e9cd1aeSAssar Westerlund cp = buf;
4455e9cd1aeSAssar Westerlund if (read(remin, cp, 1) <= 0)
4465e9cd1aeSAssar Westerlund return;
4475e9cd1aeSAssar Westerlund if (*cp++ == '\n')
4485e9cd1aeSAssar Westerlund SCREWUP("unexpected <newline>");
4495e9cd1aeSAssar Westerlund do {
4505e9cd1aeSAssar Westerlund if (read(remin, &ch, sizeof(ch)) != sizeof(ch))
4515e9cd1aeSAssar Westerlund SCREWUP("lost connection");
4525e9cd1aeSAssar Westerlund *cp++ = ch;
4535e9cd1aeSAssar Westerlund } while (cp < &buf[BUFSIZ - 1] && ch != '\n');
4545e9cd1aeSAssar Westerlund *cp = 0;
4555e9cd1aeSAssar Westerlund
4565e9cd1aeSAssar Westerlund if (buf[0] == '\01' || buf[0] == '\02') {
4575e9cd1aeSAssar Westerlund if (iamremote == 0)
458adb0ddaeSAssar Westerlund write(STDERR_FILENO,
4595e9cd1aeSAssar Westerlund buf + 1, strlen(buf + 1));
4605e9cd1aeSAssar Westerlund if (buf[0] == '\02')
4615e9cd1aeSAssar Westerlund exit(1);
4625e9cd1aeSAssar Westerlund ++errs;
4635e9cd1aeSAssar Westerlund continue;
4645e9cd1aeSAssar Westerlund }
4655e9cd1aeSAssar Westerlund if (buf[0] == 'E') {
466adb0ddaeSAssar Westerlund write(remout, "", 1);
4675e9cd1aeSAssar Westerlund return;
4685e9cd1aeSAssar Westerlund }
4695e9cd1aeSAssar Westerlund
4705e9cd1aeSAssar Westerlund if (ch == '\n')
4715e9cd1aeSAssar Westerlund *--cp = 0;
4725e9cd1aeSAssar Westerlund
4735e9cd1aeSAssar Westerlund cp = buf;
4745e9cd1aeSAssar Westerlund if (*cp == 'T') {
4755e9cd1aeSAssar Westerlund setimes++;
4765e9cd1aeSAssar Westerlund cp++;
4775e9cd1aeSAssar Westerlund mtime.tv_sec = strtol(cp, &cp, 10);
4785e9cd1aeSAssar Westerlund if (!cp || *cp++ != ' ')
4795e9cd1aeSAssar Westerlund SCREWUP("mtime.sec not delimited");
4805e9cd1aeSAssar Westerlund mtime.tv_usec = strtol(cp, &cp, 10);
4815e9cd1aeSAssar Westerlund if (!cp || *cp++ != ' ')
4825e9cd1aeSAssar Westerlund SCREWUP("mtime.usec not delimited");
4835e9cd1aeSAssar Westerlund atime.tv_sec = strtol(cp, &cp, 10);
4845e9cd1aeSAssar Westerlund if (!cp || *cp++ != ' ')
4855e9cd1aeSAssar Westerlund SCREWUP("atime.sec not delimited");
4865e9cd1aeSAssar Westerlund atime.tv_usec = strtol(cp, &cp, 10);
4875e9cd1aeSAssar Westerlund if (!cp || *cp++ != '\0')
4885e9cd1aeSAssar Westerlund SCREWUP("atime.usec not delimited");
489adb0ddaeSAssar Westerlund write(remout, "", 1);
4905e9cd1aeSAssar Westerlund continue;
4915e9cd1aeSAssar Westerlund }
4925e9cd1aeSAssar Westerlund if (*cp != 'C' && *cp != 'D') {
4935e9cd1aeSAssar Westerlund /*
4945e9cd1aeSAssar Westerlund * Check for the case "rcp remote:foo\* local:bar".
4955e9cd1aeSAssar Westerlund * In this case, the line "No match." can be returned
4965e9cd1aeSAssar Westerlund * by the shell before the rcp command on the remote is
4975e9cd1aeSAssar Westerlund * executed so the ^Aerror_message convention isn't
4985e9cd1aeSAssar Westerlund * followed.
4995e9cd1aeSAssar Westerlund */
5005e9cd1aeSAssar Westerlund if (first) {
5015e9cd1aeSAssar Westerlund run_err("%s", cp);
5025e9cd1aeSAssar Westerlund exit(1);
5035e9cd1aeSAssar Westerlund }
5045e9cd1aeSAssar Westerlund SCREWUP("expected control record");
5055e9cd1aeSAssar Westerlund }
5065e9cd1aeSAssar Westerlund mode = 0;
5075e9cd1aeSAssar Westerlund for (++cp; cp < buf + 5; cp++) {
5085e9cd1aeSAssar Westerlund if (*cp < '0' || *cp > '7')
5095e9cd1aeSAssar Westerlund SCREWUP("bad mode");
5105e9cd1aeSAssar Westerlund mode = (mode << 3) | (*cp - '0');
5115e9cd1aeSAssar Westerlund }
5125e9cd1aeSAssar Westerlund if (*cp++ != ' ')
5135e9cd1aeSAssar Westerlund SCREWUP("mode not delimited");
5145e9cd1aeSAssar Westerlund
5154137ff4cSJacques Vidrine for (size = 0; isdigit((unsigned char)*cp);)
5165e9cd1aeSAssar Westerlund size = size * 10 + (*cp++ - '0');
5175e9cd1aeSAssar Westerlund if (*cp++ != ' ')
5185e9cd1aeSAssar Westerlund SCREWUP("size not delimited");
5195e9cd1aeSAssar Westerlund if (targisdir) {
5205e9cd1aeSAssar Westerlund static char *namebuf;
5215e9cd1aeSAssar Westerlund static int cursize;
5225e9cd1aeSAssar Westerlund size_t need;
5235e9cd1aeSAssar Westerlund
5245e9cd1aeSAssar Westerlund need = strlen(targ) + strlen(cp) + 250;
5255e9cd1aeSAssar Westerlund if (need > cursize) {
5265e9cd1aeSAssar Westerlund if (!(namebuf = malloc(need)))
5275e9cd1aeSAssar Westerlund run_err("%s", strerror(errno));
5285e9cd1aeSAssar Westerlund }
529adb0ddaeSAssar Westerlund snprintf(namebuf, need, "%s%s%s", targ,
5305e9cd1aeSAssar Westerlund *targ ? "/" : "", cp);
5315e9cd1aeSAssar Westerlund np = namebuf;
5325e9cd1aeSAssar Westerlund } else
5335e9cd1aeSAssar Westerlund np = targ;
5345e9cd1aeSAssar Westerlund exists = stat(np, &stb) == 0;
5355e9cd1aeSAssar Westerlund if (buf[0] == 'D') {
5365e9cd1aeSAssar Westerlund int mod_flag = pflag;
5375e9cd1aeSAssar Westerlund if (exists) {
5385e9cd1aeSAssar Westerlund if (!S_ISDIR(stb.st_mode)) {
5395e9cd1aeSAssar Westerlund errno = ENOTDIR;
5405e9cd1aeSAssar Westerlund goto bad;
5415e9cd1aeSAssar Westerlund }
5425e9cd1aeSAssar Westerlund if (pflag)
543adb0ddaeSAssar Westerlund chmod(np, mode);
5445e9cd1aeSAssar Westerlund } else {
5455e9cd1aeSAssar Westerlund /* Handle copying from a read-only directory */
5465e9cd1aeSAssar Westerlund mod_flag = 1;
5475e9cd1aeSAssar Westerlund if (mkdir(np, mode | S_IRWXU) < 0)
5485e9cd1aeSAssar Westerlund goto bad;
5495e9cd1aeSAssar Westerlund }
5505e9cd1aeSAssar Westerlund vect[0] = np;
5515e9cd1aeSAssar Westerlund sink(1, vect);
5525e9cd1aeSAssar Westerlund if (setimes) {
5535e9cd1aeSAssar Westerlund setimes = 0;
5545e9cd1aeSAssar Westerlund if (utimes(np, tv) < 0)
5555e9cd1aeSAssar Westerlund run_err("%s: set times: %s",
5565e9cd1aeSAssar Westerlund np, strerror(errno));
5575e9cd1aeSAssar Westerlund }
5585e9cd1aeSAssar Westerlund if (mod_flag)
559adb0ddaeSAssar Westerlund chmod(np, mode);
5605e9cd1aeSAssar Westerlund continue;
5615e9cd1aeSAssar Westerlund }
5625e9cd1aeSAssar Westerlund omode = mode;
5635e9cd1aeSAssar Westerlund mode |= S_IWRITE;
5645e9cd1aeSAssar Westerlund if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
5655e9cd1aeSAssar Westerlund bad: run_err("%s: %s", np, strerror(errno));
5665e9cd1aeSAssar Westerlund continue;
5675e9cd1aeSAssar Westerlund }
568adb0ddaeSAssar Westerlund write(remout, "", 1);
5695e9cd1aeSAssar Westerlund if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == NULL) {
570adb0ddaeSAssar Westerlund close(ofd);
5715e9cd1aeSAssar Westerlund continue;
5725e9cd1aeSAssar Westerlund }
5735e9cd1aeSAssar Westerlund cp = bp->buf;
5745e9cd1aeSAssar Westerlund wrerr = NO;
5755e9cd1aeSAssar Westerlund for (count = i = 0; i < size; i += BUFSIZ) {
5765e9cd1aeSAssar Westerlund amt = BUFSIZ;
5775e9cd1aeSAssar Westerlund if (i + amt > size)
5785e9cd1aeSAssar Westerlund amt = size - i;
5795e9cd1aeSAssar Westerlund count += amt;
580adb0ddaeSAssar Westerlund if((j = net_read(remin, cp, amt)) != amt) {
5815e9cd1aeSAssar Westerlund run_err("%s", j ? strerror(errno) :
5825e9cd1aeSAssar Westerlund "dropped connection");
5835e9cd1aeSAssar Westerlund exit(1);
5845e9cd1aeSAssar Westerlund }
5855e9cd1aeSAssar Westerlund amt -= j;
5865e9cd1aeSAssar Westerlund cp += j;
5875e9cd1aeSAssar Westerlund if (count == bp->cnt) {
5885e9cd1aeSAssar Westerlund /* Keep reading so we stay sync'd up. */
5895e9cd1aeSAssar Westerlund if (wrerr == NO) {
590*ae771770SStanislav Sedov j = write(ofd, bp->buf, (size_t)count);
5915e9cd1aeSAssar Westerlund if (j != count) {
5925e9cd1aeSAssar Westerlund wrerr = YES;
5935e9cd1aeSAssar Westerlund wrerrno = j >= 0 ? EIO : errno;
5945e9cd1aeSAssar Westerlund }
5955e9cd1aeSAssar Westerlund }
5965e9cd1aeSAssar Westerlund count = 0;
5975e9cd1aeSAssar Westerlund cp = bp->buf;
5985e9cd1aeSAssar Westerlund }
5995e9cd1aeSAssar Westerlund }
6005e9cd1aeSAssar Westerlund if (count != 0 && wrerr == NO &&
601*ae771770SStanislav Sedov (j = write(ofd, bp->buf, (size_t)count)) != count) {
6025e9cd1aeSAssar Westerlund wrerr = YES;
6035e9cd1aeSAssar Westerlund wrerrno = j >= 0 ? EIO : errno;
6045e9cd1aeSAssar Westerlund }
6055e9cd1aeSAssar Westerlund if (ftruncate(ofd, size)) {
6065e9cd1aeSAssar Westerlund run_err("%s: truncate: %s", np, strerror(errno));
6075e9cd1aeSAssar Westerlund wrerr = DISPLAYED;
6085e9cd1aeSAssar Westerlund }
6095e9cd1aeSAssar Westerlund if (pflag) {
6105e9cd1aeSAssar Westerlund if (exists || omode != mode)
6115e9cd1aeSAssar Westerlund if (fchmod(ofd, omode))
6125e9cd1aeSAssar Westerlund run_err("%s: set mode: %s",
6135e9cd1aeSAssar Westerlund np, strerror(errno));
6145e9cd1aeSAssar Westerlund } else {
6155e9cd1aeSAssar Westerlund if (!exists && omode != mode)
6165e9cd1aeSAssar Westerlund if (fchmod(ofd, omode & ~mask))
6175e9cd1aeSAssar Westerlund run_err("%s: set mode: %s",
6185e9cd1aeSAssar Westerlund np, strerror(errno));
6195e9cd1aeSAssar Westerlund }
620adb0ddaeSAssar Westerlund close(ofd);
621adb0ddaeSAssar Westerlund response();
6225e9cd1aeSAssar Westerlund if (setimes && wrerr == NO) {
6235e9cd1aeSAssar Westerlund setimes = 0;
6245e9cd1aeSAssar Westerlund if (utimes(np, tv) < 0) {
6255e9cd1aeSAssar Westerlund run_err("%s: set times: %s",
6265e9cd1aeSAssar Westerlund np, strerror(errno));
6275e9cd1aeSAssar Westerlund wrerr = DISPLAYED;
6285e9cd1aeSAssar Westerlund }
6295e9cd1aeSAssar Westerlund }
6305e9cd1aeSAssar Westerlund switch(wrerr) {
6315e9cd1aeSAssar Westerlund case YES:
6325e9cd1aeSAssar Westerlund run_err("%s: %s", np, strerror(wrerrno));
6335e9cd1aeSAssar Westerlund break;
6345e9cd1aeSAssar Westerlund case NO:
635adb0ddaeSAssar Westerlund write(remout, "", 1);
6365e9cd1aeSAssar Westerlund break;
6375e9cd1aeSAssar Westerlund case DISPLAYED:
6385e9cd1aeSAssar Westerlund break;
6395e9cd1aeSAssar Westerlund }
6405e9cd1aeSAssar Westerlund }
6415e9cd1aeSAssar Westerlund screwup:
6425e9cd1aeSAssar Westerlund run_err("protocol error: %s", why);
6435e9cd1aeSAssar Westerlund exit(1);
6445e9cd1aeSAssar Westerlund }
6455e9cd1aeSAssar Westerlund
6465e9cd1aeSAssar Westerlund int
response(void)647adb0ddaeSAssar Westerlund response(void)
6485e9cd1aeSAssar Westerlund {
6495e9cd1aeSAssar Westerlund char ch, *cp, resp, rbuf[BUFSIZ];
6505e9cd1aeSAssar Westerlund
6515e9cd1aeSAssar Westerlund if (read(remin, &resp, sizeof(resp)) != sizeof(resp))
6525e9cd1aeSAssar Westerlund lostconn(0);
6535e9cd1aeSAssar Westerlund
6545e9cd1aeSAssar Westerlund cp = rbuf;
6555e9cd1aeSAssar Westerlund switch(resp) {
6565e9cd1aeSAssar Westerlund case 0: /* ok */
6575e9cd1aeSAssar Westerlund return (0);
6585e9cd1aeSAssar Westerlund default:
6595e9cd1aeSAssar Westerlund *cp++ = resp;
6605e9cd1aeSAssar Westerlund /* FALLTHROUGH */
6615e9cd1aeSAssar Westerlund case 1: /* error, followed by error msg */
6625e9cd1aeSAssar Westerlund case 2: /* fatal error, "" */
6635e9cd1aeSAssar Westerlund do {
6645e9cd1aeSAssar Westerlund if (read(remin, &ch, sizeof(ch)) != sizeof(ch))
6655e9cd1aeSAssar Westerlund lostconn(0);
6665e9cd1aeSAssar Westerlund *cp++ = ch;
6675e9cd1aeSAssar Westerlund } while (cp < &rbuf[BUFSIZ] && ch != '\n');
6685e9cd1aeSAssar Westerlund
6695e9cd1aeSAssar Westerlund if (!iamremote)
670adb0ddaeSAssar Westerlund write(STDERR_FILENO, rbuf, cp - rbuf);
6715e9cd1aeSAssar Westerlund ++errs;
6725e9cd1aeSAssar Westerlund if (resp == 1)
6735e9cd1aeSAssar Westerlund return (-1);
6745e9cd1aeSAssar Westerlund exit(1);
6755e9cd1aeSAssar Westerlund }
6765e9cd1aeSAssar Westerlund /* NOTREACHED */
6775e9cd1aeSAssar Westerlund }
6785e9cd1aeSAssar Westerlund
6795e9cd1aeSAssar Westerlund #include <stdarg.h>
6805e9cd1aeSAssar Westerlund
6815e9cd1aeSAssar Westerlund void
run_err(const char * fmt,...)6825e9cd1aeSAssar Westerlund run_err(const char *fmt, ...)
6835e9cd1aeSAssar Westerlund {
6845e9cd1aeSAssar Westerlund static FILE *fp;
6855e9cd1aeSAssar Westerlund va_list ap;
6865e9cd1aeSAssar Westerlund
6875e9cd1aeSAssar Westerlund ++errs;
6885e9cd1aeSAssar Westerlund if (fp == NULL && !(fp = fdopen(remout, "w")))
6895e9cd1aeSAssar Westerlund return;
6904137ff4cSJacques Vidrine va_start(ap, fmt);
691adb0ddaeSAssar Westerlund fprintf(fp, "%c", 0x01);
692adb0ddaeSAssar Westerlund fprintf(fp, "rcp: ");
693adb0ddaeSAssar Westerlund vfprintf(fp, fmt, ap);
694adb0ddaeSAssar Westerlund fprintf(fp, "\n");
695adb0ddaeSAssar Westerlund fflush(fp);
6965e9cd1aeSAssar Westerlund va_end(ap);
6974137ff4cSJacques Vidrine
6984137ff4cSJacques Vidrine if (!iamremote) {
6994137ff4cSJacques Vidrine va_start(ap, fmt);
7004137ff4cSJacques Vidrine vwarnx(fmt, ap);
7014137ff4cSJacques Vidrine va_end(ap);
7024137ff4cSJacques Vidrine }
7035e9cd1aeSAssar Westerlund }
7045e9cd1aeSAssar Westerlund
7055e9cd1aeSAssar Westerlund /*
7065e9cd1aeSAssar Westerlund * This function executes the given command as the specified user on the
7075e9cd1aeSAssar Westerlund * given host. This returns < 0 if execution fails, and >= 0 otherwise. This
7085e9cd1aeSAssar Westerlund * assigns the input and output file descriptors on success.
7095e9cd1aeSAssar Westerlund *
7105e9cd1aeSAssar Westerlund * If it cannot create necessary pipes it exits with error message.
7115e9cd1aeSAssar Westerlund */
7125e9cd1aeSAssar Westerlund
7135e9cd1aeSAssar Westerlund int
do_cmd(char * host,char * remuser,char * cmd,int * fdin,int * fdout)7145e9cd1aeSAssar Westerlund do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
7155e9cd1aeSAssar Westerlund {
7165e9cd1aeSAssar Westerlund int pin[2], pout[2], reserved[2];
7175e9cd1aeSAssar Westerlund
7185e9cd1aeSAssar Westerlund /*
7195e9cd1aeSAssar Westerlund * Reserve two descriptors so that the real pipes won't get
7205e9cd1aeSAssar Westerlund * descriptors 0 and 1 because that will screw up dup2 below.
7215e9cd1aeSAssar Westerlund */
7225e9cd1aeSAssar Westerlund pipe(reserved);
7235e9cd1aeSAssar Westerlund
7245e9cd1aeSAssar Westerlund /* Create a socket pair for communicating with rsh. */
7255e9cd1aeSAssar Westerlund if (pipe(pin) < 0) {
7265e9cd1aeSAssar Westerlund perror("pipe");
7275e9cd1aeSAssar Westerlund exit(255);
7285e9cd1aeSAssar Westerlund }
7295e9cd1aeSAssar Westerlund if (pipe(pout) < 0) {
7305e9cd1aeSAssar Westerlund perror("pipe");
7315e9cd1aeSAssar Westerlund exit(255);
7325e9cd1aeSAssar Westerlund }
7335e9cd1aeSAssar Westerlund
7345e9cd1aeSAssar Westerlund /* Free the reserved descriptors. */
7355e9cd1aeSAssar Westerlund close(reserved[0]);
7365e9cd1aeSAssar Westerlund close(reserved[1]);
7375e9cd1aeSAssar Westerlund
7385e9cd1aeSAssar Westerlund /* For a child to execute the command on the remote host using rsh. */
7395e9cd1aeSAssar Westerlund if (fork() == 0) {
7405e9cd1aeSAssar Westerlund char *args[100];
7415e9cd1aeSAssar Westerlund unsigned int i;
7425e9cd1aeSAssar Westerlund
7435e9cd1aeSAssar Westerlund /* Child. */
7445e9cd1aeSAssar Westerlund close(pin[1]);
7455e9cd1aeSAssar Westerlund close(pout[0]);
7465e9cd1aeSAssar Westerlund dup2(pin[0], 0);
7475e9cd1aeSAssar Westerlund dup2(pout[1], 1);
7485e9cd1aeSAssar Westerlund close(pin[0]);
7495e9cd1aeSAssar Westerlund close(pout[1]);
7505e9cd1aeSAssar Westerlund
7515e9cd1aeSAssar Westerlund i = 0;
7525e9cd1aeSAssar Westerlund args[i++] = RSH_PROGRAM;
753bbd80c28SJacques Vidrine if (usekrb4)
754bbd80c28SJacques Vidrine args[i++] = "-4";
7555e9cd1aeSAssar Westerlund if (usekrb5)
7565e9cd1aeSAssar Westerlund args[i++] = "-5";
7575e9cd1aeSAssar Westerlund if (usebroken)
7585e9cd1aeSAssar Westerlund args[i++] = "-K";
7595e9cd1aeSAssar Westerlund if (doencrypt)
7605e9cd1aeSAssar Westerlund args[i++] = "-x";
761adb0ddaeSAssar Westerlund if (forwardtkt)
762adb0ddaeSAssar Westerlund args[i++] = "-F";
7635e9cd1aeSAssar Westerlund if (noencrypt)
7645e9cd1aeSAssar Westerlund args[i++] = "-z";
7655e9cd1aeSAssar Westerlund if (port != NULL) {
7665e9cd1aeSAssar Westerlund args[i++] = "-p";
7675e9cd1aeSAssar Westerlund args[i++] = port;
7685e9cd1aeSAssar Westerlund }
769c19800e8SDoug Rabson if (eflag)
770c19800e8SDoug Rabson args[i++] = "-e";
7715e9cd1aeSAssar Westerlund if (remuser != NULL) {
7725e9cd1aeSAssar Westerlund args[i++] = "-l";
7735e9cd1aeSAssar Westerlund args[i++] = remuser;
7745e9cd1aeSAssar Westerlund }
7755e9cd1aeSAssar Westerlund args[i++] = host;
7765e9cd1aeSAssar Westerlund args[i++] = cmd;
7775e9cd1aeSAssar Westerlund args[i++] = NULL;
7785e9cd1aeSAssar Westerlund
7795e9cd1aeSAssar Westerlund execvp(RSH_PROGRAM, args);
7805e9cd1aeSAssar Westerlund perror(RSH_PROGRAM);
7815e9cd1aeSAssar Westerlund exit(1);
7825e9cd1aeSAssar Westerlund }
7835e9cd1aeSAssar Westerlund /* Parent. Close the other side, and return the local side. */
7845e9cd1aeSAssar Westerlund close(pin[0]);
7855e9cd1aeSAssar Westerlund *fdout = pin[1];
7865e9cd1aeSAssar Westerlund close(pout[1]);
7875e9cd1aeSAssar Westerlund *fdin = pout[0];
7885e9cd1aeSAssar Westerlund return 0;
7895e9cd1aeSAssar Westerlund }
790