/* execute "time" and "rm"; passing on "get" to ftp.
* stdin = commands generated by "masterslave"
* argv[1] = <ftpcmd> (typically ftp, but proxy-ftp at Bell Labs)
* argv[2] = <host> (like netlib.att.com)
* argv[3] = <directory> (like .)
* argv[4] = <compressed suffix list> (typically /netlib/crc/net/compressed)
*/
/*
* The author of this software is Eric Grosse. Copyright (c) 1993 by AT&T.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#define MESS_SIZE "%s had size %lu, expected %lu\n"
#define MESS_OWN "%s: not owner\n"
#define MESS_BIG "string too big: %s"
#define _POSIX_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utime.h>
#include "suffix.h"
#ifndef LOOSE
typedef unsigned long ulong; /* some vendors, in violation of POSIX,
define this in sys/types.h and don't allow matching redefinition. */
#endif
#ifndef NAME_MAX
#define NAME_MAX 255
#endif
#ifndef PATH_MAX
#define PATH_MAX 1023
#endif
extern int Create(char*,mode_t);
extern int Error(char*,...);
char *progname;
static int debug = 0; /* if 1, print commands, don't actually do them */
static int uncompressed; /* if 1, assume master site has no compression at all */
static int toftp; /* is there any work for ftp? */
static char **ftparg; /* argv[1] argv[2] argv[3] */
static char ftpdir[PATH_MAX+1]; /* relative to starting directory here
and on remote. No '/' on end. */
#define ftpcmd(cmd) printf("%s",cmd)
static int
chtime(char *name, ulong tim, ulong len)
{
struct stat s;
struct utimbuf u;
if(stat(name,&s)!=0){ /* get actual time and length */
fprintf(stderr,"can't stat %s\n",name);
return -1;
}
if((off_t)len!=s.st_size){ /* verify length is same */
fprintf(stderr,MESS_SIZE,name,(ulong)s.st_size,len);
return -1;
}
u.actime = s.st_atime;
u.modtime = (time_t)tim;
if(utime(name,&u)!=0){ /* change mtime */
if(errno==EPERM){
fprintf(stderr,MESS_OWN,name);
return -1;
}
fprintf(stderr,"can't utime %s\n",name);
return -1;
}
return 0;
}
static void
walk(char *olddir, char *newdir)
{
char *so, *sn;
char cdcmd[5+2*PATH_MAX];
/* see how far old and new agree */
for( so=olddir, sn=newdir; *so==*sn; so++, sn++){
if(*so=='/'){
olddir = so+1;
newdir = sn+1;
}else if(*so=='\0'){
olddir = so;
newdir = sn;
break;
}
}
strcpy(cdcmd,"lcd ");
while(so = strrchr(olddir,'/')){ /* walk up */
strcat(cdcmd,"../");
*so = '\0';
}
if(olddir[0]!='\0')
strcat(cdcmd,"../");
strcat(cdcmd,newdir);
strcat(cdcmd,"\n");
if(strcmp(cdcmd,"lcd \n")!=0){
ftpcmd(cdcmd); /* local cd */
ftpcmd(cdcmd+1); /* remote cd */
}
strcpy(olddir,newdir);
}
static int
get(char *name, ulong tim, ulong len, ulong sum, Suffix *suffixlist)
{
char getcmd[5+NAME_MAX], work[PATH_MAX+1], *newdir, *basename, *suf;
if(!debug)
close(Create(name,0666)); /* make directories if necessary */
if(!toftp){
toftp = 1;
printf("%s %s <<'!'\n",ftparg[0],ftparg[1]); ftparg += 2;
ftpcmd("prompt\n");
ftpcmd("binary\n");
ftpcmd("verbose\n");
if(*ftparg){ /* starting directory on remote system */
if(strlen(*ftparg)+5>PATH_MAX) Error(MESS_BIG,*ftparg);
sprintf(work,"cd %s\n",*ftparg++);
ftpcmd(work);
}
}
/* cut path into directory and basename */
if(strlen(name)+1>sizeof(work)) Error("filename overflow");
strcpy(work,name);
if(basename = strrchr(work,'/')){
newdir = work;
*basename++ = '\0';
}else{
newdir = "";
basename = work;
}
walk(ftpdir,newdir); /* cd as necessary */
strcmp(ftpdir,newdir)==0 || Error("dir mismatch: can't happen");
/* at last, get the file */
suf = "";
if(!uncompressed && need_compr(basename,suffixlist))
suf = ".gz";
sprintf(getcmd,"get %s%s\n",basename,suf);
ftpcmd(getcmd);
return 0;
}
int
main(int argc, char **argv)
{
#define DIE Error("can't %s %s",cmd,name)
ulong tim, len, sum;
char cmd[21], name[2001];
Suffix *suffixlist;
int err = 0;
progname = argv[0];
if(strcmp(argv[1],"-d")==0){
debug = 1;
argv++;
argc--;
}
if(argc!=5)
Error("args: <ftpcmd> <host> <directory> <suffixlist>\n");
ftparg = &argv[1];
uncompressed = read_suffix(argv[4],&suffixlist);
while(5==fscanf(stdin,"%20s %2000s %lu %lu %lx",cmd,name,&tim,&len,&sum)){
switch(*cmd){
case 'g': /* get */
get(name,tim,len,sum,suffixlist)==0 || DIE;
break;
case 'r': /* rm */
if(!debug)
unlink(name)==0 || DIE;
break;
case 't': /* time */
if(!debug)
chtime(name,tim,len); /* don't DIE, just keep going */
break;
default:
if(err++ < 10)
fprintf(stderr,"? %s %s\n",cmd,name);
}
}
if(toftp)
printf("quit\n!\n");
if(err)
exit(1);
exit(0);
}
.