V10/dk/cmd/pull.c
/*%cc -o pull % -ldk
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
extern int errno;
char SERVER[]="/usr/lib/Rpush";
int server;
#define MAXCHARS 8192
char args[MAXCHARS];
char *bldargs(argv)
register char *argv[];
{
register char *s, *t;
extern char *strcpy();
s=strcpy(args, SERVER);
s+=strlen(s);
*s++=' ';
while(t= *argv++){ /* assignment = */
while(*s = *t++)
if(s++ >= &args[MAXCHARS-1]){
error("arg list too long", "");
exit(1);
}
*s++=' ';
}
s[-1]='\0';
return(args);
}
char *
basename(s)
register char *s;
{
extern char *strrchr();
register char *t;
t=strrchr(s, '/');
return(t? t+1 : s);
}
char *
str(s, n)
register char *s;
{
static char strbuf[129];
(void)strncpy(strbuf, s, n);
strbuf[n]=0;
return(strbuf);
}
int errors=0;
int vflag;
main(argc, argv)
char *argv[];
{
register n;
char *targetdir;
char buf[512];
if(argc>1 && strcmp(argv[1], "-v")==0){
vflag=1;
argv++;
--argc;
}
if(basename(argv[0])[0]=='R'){
if(argc!=2){
error("arg count", ""); /* It's ok; other guy will decrypt it */
exit(1);
}
targetdir=argv[1];
}else{
if(argc<4){
error("Usage: pull machine <remotefiles|dirs> localdir", "");
exit(1);
}
targetdir=argv[argc-1];
server=0; /* Standard input */
server=tdkexec(argv[1], bldargs(&argv[1]));
if(server<0){
extern char *dkerror;
fprintf(stderr, "pull: can't execute %s (%s)\n", SERVER,
dkerror);
exit(1);
}
}
if(mkdir(targetdir, 0777)==0){
error("can't make directory", argv[1]);
exit(1);
}
while((n=read(server, buf, sizeof buf))>0){
switch(buf[0]){
case 'D':
if(mkdir(str(buf+4, n-4), o3(buf+1))==0)
error("can't make directory", str(buf+1, n-1));
break;
case 'E':
error("(remote)", str(buf+1, n-1));
break;
case 'F':
createfile(str(buf+4, n-4), o3(buf+1));
continue; /* createfile() will read null message */
default:
buf[1]='\0';
error("unknown message", buf);
break;
}
if(read(server, buf, sizeof buf)!=0){
error("synchronization error", "");
do; while(read(server, buf, sizeof buf)>0);
}
}
return(errors);
}
createfile(s, m)
register char *s;
{
char buf[1024];
register f;
register cc;
if(server>1 && vflag)
printf("pull: receive %s\n", s);
if((f=creat(s, m))<0)
error("can't create", s);
else{
if(read(server, buf, sizeof buf)>0){
error("synchronization", "error");
close(f);
return;
}
while((cc=read(server, buf, sizeof buf))>0)
if(write(f, buf, cc)!=cc){
error("write error", s);
if(errno==ENOSPC){
error("file system is full; aborting", "");
exit(1);
}
close(f);
return;
}
close(f);
}
}
error(s, t)
char *s, *t;
{
char ebuf[128];
errors=1;
sprintf(ebuf, "%s%s %s\n", server>0? "pull: " : "" ,s, t);
write(2, ebuf, strlen(ebuf));
}
mkdir(s, m)
register char *s;
{
struct stat statbuf;
register pid;
int status;
if(stat(s, &statbuf)<0){
if((pid=fork())==0){
execl("/bin/mkdir", "mkdir", s, 0);
exit(1);
}
(void)wait(&status);
chmod(s, m);
return(!status);
}
return((statbuf.st_mode&S_IFMT)==S_IFDIR);
}
o3(s)
register char *s;
{
return(((s[0]-'0')*0100)+((s[1]-'0')*010)+(s[2]-'0'));
}