📄 rcp.c
字号:
/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */#ifndef lintchar copyright[] ="@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)rcp.c 1.1 87/12/21 SMI"; /* from UCB 5.3 6/8/85"*/#endif /* not lint *//* * rcp */#undef _MINIX#define NAMESERVER#include <ctype.h>#include <errno.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <utime.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include <dirent.h>#include <fcntl.h>#include <pwd.h>#include <signal.h>#include <unistd.h>#include <net/gen/netdb.h>#include <net/netlib.h>#if __STDC__#define PROTO(func, args) func args#else#define PROTO(func, args) func ()#endif /* __STDC__ */PROTO (int main, (int argc, char *argv[]));PROTO (void lostconn, (int sig));PROTO (void error, (char *fmt, ...) );PROTO (int response, (void) );PROTO (void source, (int argc, char *argv[]) );PROTO (void sink, (int argc, char *argv[]) );PROTO (void usage, (void) );PROTO (char *colon, (char *cp) );PROTO (int okname, (char *cp0) );PROTO (int susystem, (char *s) );PROTO (void verifydir, (char *cp) );PROTO (void rsource, (char *name, struct stat *statp) );PROTO (struct buffer *allocbuf, (struct buffer *bp, int fd, int blksize) );#define vfork forkint rem;int errs;int errno;int iamremote, targetshouldbedirectory;int iamrecursive;int myuid; /* uid of invoker */int pflag;struct passwd *pwd;int userid;int port;struct buffer { int cnt; char *buf;};#define ga() (void) write(rem, "", 1)main(argc, argv) int argc; char **argv;{ char *targ, *host, *src;#ifndef NAMESERVER char *suser, *tuser;#else /* NAMESERVER */ char *suser, *tuser, *thost;#endif /* NAMESERVER */ int i; char buf[BUFSIZ], cmd[16]; struct servent *sp; sp = getservbyname("shell", "tcp"); if (sp == NULL) { fprintf(stderr, "rcp: shell/tcp: unknown service\n"); exit(1); } port = sp->s_port; pwd = getpwuid(userid = getuid()); if (pwd == 0) { fprintf(stderr, "who are you?\n"); exit(1); }#ifdef NOT_DEF /* * This is a kludge to allow seteuid to user before touching * files and seteuid root before doing rcmd so we can open * the socket. */ myuid = getuid(); if (setruid(0) < 0) { perror("setruid root"); exit(1); } seteuid(myuid);#endif for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) { (*argv)++; while (**argv) switch (*(*argv)++) { case 'r': iamrecursive++; break; case 'p': /* preserve mtimes and atimes */ pflag++; break; /* The rest of these are not for users. */ case 'd': targetshouldbedirectory = 1; break; case 'f': /* "from" */ iamremote = 1; (void) response(); source(--argc, ++argv); exit(errs); case 't': /* "to" */ iamremote = 1; sink(--argc, ++argv); exit(errs); default: usage(); exit(1); } }if (iamremote){ close(2); open("/dev/tty", 2);} if (argc < 2) { usage(); exit(1); } rem = -1; if (argc > 2) targetshouldbedirectory = 1; (void) sprintf(cmd, "rcp%s%s%s", iamrecursive ? " -r" : "", pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); (void) signal(SIGPIPE, lostconn); targ = colon(argv[argc - 1]); if (targ) { /* ... to remote */ *targ++ = 0; if (*targ == 0) targ = ".";#ifndef NAMESERVER tuser = strrchr(argv[argc - 1], '.'); if (tuser) { *tuser++ = 0; if (!okname(tuser)) exit(1); } else tuser = pwd->pw_name;#else /* NAMESERVER */ thost = strchr(argv[argc - 1], '@'); if (thost) { *thost++ = 0; tuser = argv[argc - 1]; if (*tuser == '\0') tuser = pwd->pw_name; else if (!okname(tuser)) exit(1); } else { thost = argv[argc - 1]; tuser = pwd->pw_name; }#endif /* NAMESERVER */ for (i = 0; i < argc - 1; i++) { src = colon(argv[i]); if (src) { /* remote to remote */ *src++ = 0; if (*src == 0) src = ".";#ifndef NAMESERVER suser = strrchr(argv[i], '.'); if (suser) { *suser++ = 0; if (!okname(suser))#else /* NAMESERVER */ host = strchr(argv[i], '@'); if (host) { *host++ = 0; suser = argv[i]; if (*suser == '\0') suser = pwd->pw_name; else if (!okname(suser))#endif /* NAMESERVER */ continue;#ifndef NAMESERVER (void) sprintf(buf, "rsh %s -l %s -n %s %s '%s.%s:%s'", argv[i], suser, cmd, src, argv[argc - 1], tuser, targ); } else (void) sprintf(buf, "rsh %s -n %s %s '%s.%s:%s'", argv[i], cmd, src, argv[argc - 1], tuser, targ);#else /* NAMESERVER */ (void) sprintf(buf, "rsh %s -l %s -n %s %s '%s@%s:%s'", host, suser, cmd, src, tuser, thost, targ); } else (void) sprintf(buf, "rsh %s -n %s %s '%s@%s:%s'", argv[i], cmd, src, tuser, thost, targ);#endif /* NAMESERVER */ (void) susystem(buf); } else { /* local to remote */ if (rem == -1) { (void) sprintf(buf, "%s -t %s", cmd, targ);#ifndef NAMESERVER host = argv[argc - 1];#else /* NAMESERVER */ host = thost;#endif /* NAMESERVER */#ifdef NOT_DEF if (seteuid(0) < 0) { perror("seteuid root"); exit(1); }#endif rem = rcmd(&host, port, pwd->pw_name, tuser, buf, 0);#ifdef NO_DEF seteuid(myuid);#endif if (rem < 0) exit(1); if (response() < 0) exit(1); } source(1, argv+i); } } } else { /* ... to local */ if (targetshouldbedirectory) verifydir(argv[argc - 1]); for (i = 0; i < argc - 1; i++) { src = colon(argv[i]); if (src == 0) { /* local to local */ (void) sprintf(buf, "/bin/cp%s%s %s %s", iamrecursive ? " -r" : "", pflag ? " -p" : "", argv[i], argv[argc - 1]); (void) susystem(buf); } else { /* remote to local */ *src++ = 0; if (*src == 0) src = ".";#ifndef NAMESERVER suser = strrchr(argv[i], '.'); if (suser) { *suser++ = 0; if (!okname(suser))#else /* NAMESERVER */ host = strchr(argv[i], '@'); if (host) { *host++ = 0; suser = argv[i]; if (*suser == '\0') suser = pwd->pw_name; else if (!okname(suser))#endif /* NAMESERVER */ continue;#ifndef NAMESERVER } else#else /* NAMESERVER */ } else { host = argv[i];#endif /* NAMESERVER */ suser = pwd->pw_name;#ifdef NAMESERVER }#endif /* NAMESERVER */ (void) sprintf(buf, "%s -f %s", cmd, src);#ifndef NAMESERVER host = argv[i];#endif /* NAMESERVER */#ifdef NOT_DEF if (seteuid(0) < 0) { perror("seteuid root"); exit(1); }#endif rem = rcmd(&host, port, pwd->pw_name, suser, buf, 0);#ifdef NOT_DEF seteuid(myuid);#endif if (rem < 0) continue; sink(1, argv+argc-1); (void) close(rem); rem = -1; } } } exit(errs);}voidverifydir(cp) char *cp;{ struct stat stb; if (stat(cp, &stb) >= 0) { if ((stb.st_mode & S_IFMT) == S_IFDIR) return; errno = ENOTDIR; } error("rcp: %s: %s.\n", cp, strerror(errno)); exit(1);}char *colon(cp) char *cp;{ while (*cp) { if (*cp == ':') return (cp); if (*cp == '/') return (0); cp++; } return (0);}intokname(cp0) char *cp0;{ register char *cp = cp0; register int c; do { c = *cp; if (c & 0200) goto bad; if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-') goto bad; cp++; } while (*cp); return (1);bad: fprintf(stderr, "rcp: invalid user name %s\n", cp0); return (0);}intsusystem(s) char *s;{ int status, pid, w; register void PROTO ((*istat), (int) ), PROTO ((*qstat), (int) ); if ((pid = vfork()) == 0) {#ifdef NOT_DEF (void) setruid(myuid);#endif execl("/bin/sh", "sh", "-c", s, (char *)0); _exit(127); } istat = signal(SIGINT, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); while ((w = wait(&status)) != pid && w != -1) ; if (w == -1) status = -1; (void) signal(SIGINT, istat); (void) signal(SIGQUIT, qstat); return (status);}voidsource(argc, argv) int argc; char **argv;{ char *last, *name; struct stat stb; static struct buffer buffer; struct buffer *bp; int x, sizerr, f, amt; off_t i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -