archie/prospero/user/vget.c
2024-05-27 16:13:40 +02:00

300 lines
8.0 KiB
C

/*
* Copyright (c) 1991, 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*/
#include <usc-license.h>
#include <sys/param.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <pfs.h>
#include <psite.h>
#include <perrno.h>
#include <pcompat.h>
#include <pmachine.h>
int pfs_debug = 0;
static int
retrieve_link(VLINK vl, char *lclfil, char *debugflag, char *verboseflag,
int forcecopyflag );
static int copy_file(char *inname, char *outname, int forcecopyflag);
static char *progname; /* name of this program */
static char *prognamecolon = NULL;
void
main(argc, argv)
char *argv[];
{
char path[MAX_VPATH];
char *lclfil;
char *method;
VLINK vl;
int message_option = 0;
int avsflag = 0; /* If set - use active VS (no closure) */
char *debugflag = "-";
char *verboseflag = "-v";
int forcecopyflag = 0;
p_initialize("ufP", 0, (struct p_initialize_st *) NULL);
progname = argv[0];
prognamecolon = ((char *) NULL, "%s: ", progname);
argc--;argv++;
while (argc > 0 && *argv[0] == '-' && *(argv[0]+1) != '\0') {
switch (*(argv[0]+1)) {
case 'D':
pfs_debug = 1; /* Default debug level */
sscanf(argv[0],"-D%d",&pfs_debug);
debugflag = argv[0];
break;
case 'a':
avsflag++;
break;
case 'f':
forcecopyflag++;
break;
case 'm':
message_option++;
break;
case 'q':
verboseflag = "-";
break;
case 'v':
verboseflag = "-v";
break;
default:
goto usage;
}
argc--; argv++;
}
/* The next argument must be the name of the file to retrieve */
/* within the virtual file system unless it is to be extracted */
/* from a mail message */
if(argc < 1 && !message_option) {
usage:
fprintf(stderr,"Usage: %s [-a,-f,-m,-q,-v] virtual-file [local-file]\n",
progname);
exit(1);
}
if (argc >= 1) strcpy(path,argv[0]);
/* if stdin is not a tty and OK to use closure */
/* then we have to extract closure info */
if(!avsflag && !isatty(0)) {
char *s;
s = readheader(stdin,"virtual-system-name:");
if(!s) {
fprintf(stderr,"%s: Can't find Virtual-System-Name.\n", progname);
exit(1);
}
sprintf(path,"%s:",s);
if(message_option) {
s = readheader(stdin,"virtual-file-name:");
if(!s) {
fprintf(stderr,"%s: Can't find Virtual-file-name.\n", progname);
exit(1);
}
strcat(path,s);
}
else strcat(path,argv[0]);
}
else if(message_option) {
fprintf(stderr,"%s: Can't find Virtual-file-name.\n", progname);
exit(1);
}
/* If second name was not specified, derive it from first */
if(argc == (message_option ? 0 : 1)) {
char *p;
p = p_uln_rindex(path,'/');
lclfil = (p != NULL) ? p + 1 : path;
}
/* Otherwise local file is the second name */
else lclfil = (message_option ? argv[0] : argv[1]);
vl = rd_vlink(path);
if(!vl) {
if(perrno == PSUCCESS) fprintf(stderr,"%s: File not found\n", progname);
else perrmesg(prognamecolon, 0, NULL);
exit(1);
}
if(retrieve_link(vl, lclfil, debugflag, verboseflag, forcecopyflag) != PSUCCESS)
exit(1);
exit(0);
}
/* This function looks a heck of a lot like lib/pcompat/mapname(). If there's
a bug here, there's one there too. */
static int
retrieve_link(VLINK vl, char *lclfil, char *debugflag, char *verboseflag,
int forcecopyflag)
{
TOKEN am_args;
int am; /* access method number */
#ifdef BSD_UNION_WAIT
union wait status;
#else
int status;
#endif
int pid;
int methods = P_AM_LOCAL | P_AM_AFTP | P_AM_FTP |
P_AM_GOPHER | P_AM_RCP | P_AM_PROSPERO_CONTENTS;
char *vcargv[12]; /* vcache's ARGV. Enough to hold any known
access method arguments. */
char **vcargvp = vcargv; /* pointer to vcache's argv. */
char npath[MAXPATHLEN]; /* local pathname, if needed. */
int tmp;
#ifdef P_NFS
methods |= P_AM_NFS;
#endif P_NFS
#ifdef P_AFS
methods |= P_AM_AFS;
#endif P_AFS
am = pget_am(vl,&am_args,methods);
if (!am) {
if (perrno) perrmesg(": ", 0, NULL);
else fprintf(stderr,"%s: Can't access file using any available \
access method.\n", progname);
RETURNPFAILURE;
}
if(pwarn) pwarnmesg("WARNING: ",0,NULL);
switch(am) {
case P_AM_AFTP:
case P_AM_FTP:
case P_AM_GOPHER:
case P_AM_RCP:
case P_AM_PROSPERO_CONTENTS:
pid = fork();
*vcargvp++ = "vcache";
*vcargvp++ = debugflag;
*vcargvp++ = verboseflag;
*vcargvp++ = lclfil;
for (;am_args; am_args = am_args->next)
*vcargvp++ = am_args->token;
*vcargvp = NULL;
if (pid == 0) {
char vcachebin[MAXPATHLEN];
char *p_binaries = getenv("P_BINARIES");
#ifdef P_BINARIES
if (!p_binaries)
p_binaries = P_BINARIES;
#endif
if (!p_binaries || !*p_binaries) {
DISABLE_PFS(execvp("vcache", vcargv));
strcpy(vcachebin, "vcache"); /* for error message */
} else {
qsprintf(vcachebin, sizeof vcachebin, "%s/vcache", p_binaries);
DISABLE_PFS(execv(vcachebin,vcargv));
}
fprintf(stderr,
"%s: exec failed for %s (errno=%d): ", progname,
vcachebin,errno);
perror(NULL);
RETURNPFAILURE;
}
else wait(&status);
#ifdef BSD_UNION_WAIT
tmp = status.w_T.w_Retcode;
#else
tmp = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
#endif
if(tmp) {
fprintf(stderr,"%s: Retrieve failed\n", progname);
RETURNPFAILURE;
}
return PSUCCESS;
case P_AM_LOCAL:
return copy_file(elt(am_args, 4), lclfil, forcecopyflag);
#ifdef P_NFS
case P_AM_NFS:
/* XXX You must change pmap_nfs() to meet the needs of your site. */
tmp = pmap_nfs(link->host,link->hsoname,npath, sizeof npath, am_args);
if (!tmp) tmp = copy_file(npath, lclfil, forcecopyflag);
return(tmp);
#endif
#ifdef P_AFS
case P_AM_AFS:
strcpy(npath,P_AFS);
strcat(npath,elt(am_args,4)); /* 4th element is the hsoname. */
return copy_file(npath, lclfil, forcecopyflag);
return(PSUCCESS);
#endif
default:
fprintf(stderr,"%s: Can't access file using any available \
access method.\n", progname);
RETURNPFAILURE;
}
}
static int
copy_file(char *inname, char *outname, int forcecopyflag)
{
struct stat st_buf;
/* Check if the local file is a directory. If so, don't copy it. */
if(stat(inname, &st_buf)) {
perror("%s: Can't access file, progname");
RETURNPFAILURE;
}
#ifdef S_ISDIR
if (S_ISDIR(st_buf.st_mode)) {
#else
if ((st_buf.st_mode & S_IFMT) == ST_IFDIR) {
#endif
fprintf(stderr, "%s: Can't retrieve file %s: it is actually a \
directory.", progname, inname);
RETURNPFAILURE;
}
if (isatty(0) && !forcecopyflag) {
fprintf(stderr,
"%s: This file is available in your native filesystem as %s.\n\
\tIf you still want to copy it to %s, invoke %s again with the -f flag.\n",
progname, inname, outname, progname);
RETURNPFAILURE;
}
if (copyFile(inname, outname)) {
fprintf(stderr, "%s: %s", progname, p_err_string);
RETURNPFAILURE;
}
return PSUCCESS;
}