4.4BSD/usr/src/contrib/xns/examples/filing_client/xnftp.c
#ifndef lint
static char *rcsid = "$Header: xnftp.c,v 2.13 87/05/28 14:17:14 ed Exp $";
#endif lint
/* $Log: xnftp.c,v $
* Revision 2.13 87/05/28 14:17:14 ed
* I botched the compiler bug fix...
*
* Revision 2.12 87/05/14 11:37:34 ed
* Raise error from hookup if connection not established.
* Better handling of truncated bulk data stream when it overflows buffer.
*
* Revision 2.11 87/05/11 14:40:12 ed
* Incorporated changes from JQ's 4.3e version.
*
* Revision 2.11 87/03/08 07:09:53 jqj
* work around "schain botch" 4.3BSD VAX compiler bug (from Scooter Morris).
*
* Revision 2.10 87/05/05 14:49:00 ed
* Move alarm setting/resetting closer to actual procedure calls.
*
* Revision 2.9 87/04/16 15:23:47 ed
* Fixed lingering bugs in Subset pathname usage.
*
* Revision 2.8 87/04/01 09:33:36 ed
* Changed for new MakeSecondaryCreds call.
* Reset connection on login failure.
*
* Revision 2.7 87/03/27 15:19:19 ed
* Don't assume secondary username is primary name.
* Additional check for underscore translation on text files.
*
* Revision 2.6 87/03/23 12:32:12 ed
* allow round-trip transfer of Viewpoint files, retain/specify uninterpreted
* attributes.
* Serialization/Deserialization of directories from server.
* Wildcard deletion.
* Compatibility with XDE MFileServer.
* New commands: Archive, Restore, Unify.
*
* Revision 2.5 87/01/14 15:59:29 ed
* Use FilingSubset, if rejected attempt Filing
* Allows user override with -F switch
* Maintain FilingSubset mandatory attributes
* User niceties: echo file name/type on transfer commands
* prompt on delete
* guess type which will determine file type implied by content
* New commands: (type related) Guess, Whatis
* (file transfer) Copy, Move, Rename
*
* Revision 2.4 86/12/15 11:41:16 jqj
* Added support for more ViewPoint file types (no other attributes, though)
*
* Revision 2.3 86/12/11 06:12:22 jqj
* Eliminated form, mode, and struct commands. Started adding support for
* more file types.
*
* Revision 2.2 86/09/07 07:43:40 jqj
* Cope with failure return from CourierOpen.
*
* Revision 2.1 86/06/30 12:19:39 jqj
* convert to Authentication v. 2 for compatibility with official spec.
*
* Revision 2.0 85/11/21 07:22:51 jqj
* 4.3BSD standard release
*
* Revision 1.5 85/09/24 14:45:10 jqj
* fix bug in alarm() handling that caused aborts during large file transfers.
*
* Revision 1.4 85/09/17 07:49:47 jqj
* 4.3 changes. Use more routines from CHlookup
*
* Revision 1.1 85/05/27 06:31:07 jqj
* Initial revision
*
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <netns/ns.h>
#include <netns/sp.h>
#include "ftp_var.h"
#include <xnscourier/Filing4.h>
#include <xnscourier/except.h>
#undef __Clearinghouse2 /* Filing4.h defs this */
#include <xnscourier/CH.h>
#define XNS_TIME_DIFFERENCE 2177452800 /* [(1970-1901) years * 365 days/year + 17 leap days */
/* * 24 hours/day * 60 minutes/hour * 60 seconds/minute */
#define ROOT_DIRECTORY "/"
#define MAXNAMES 10
CourierConnection *connected;
Clearinghouse3_ObjectName hostobjname;
Authentication3_Verifier verifier;
/* the following 3 items make up the current session */
FilingSubset1_Session session; /* the current session */
Clearinghouse3_ObjectName username;
int continuetime;
int remoteprocpending;
FilingSubset1_Handle rootHandle;
char cur_dir[512]= 0;
char cur_pathname[512]= 0;
char cur_name[512]= 0;
struct name_entry {
char *pathname;
LongCardinal type;
} ;
static struct name_entry *name_list= 0;
static int name_count= 0;
static int name_size= 0;
static FilingSubset1_ControlSequence nullControls = {0,0};
static FilingSubset1_ScopeSequence nullScope = {0,0};
/* global data used to communicate with BDT procedures
*/
extern GetAttributeSequences(),
GetAllAttributes(),
listproc(), nlistproc(),
storeproc(), retrieveproc(),
rlistproc(), mkdirproc(),
cdproc(), isdirproc(), deleteproc();
char *malloc();
char *AttrToString();
Boolean AttrToBoolean();
LongCardinal AttrToLongCardinal();
Cardinal AttrToCardinal();
char *typetostring();
static (*ProcEachSeq)();
static long bytessent;
static FILE *fout, *fin;
LongCardinal filetypevalue; /* real transfer type */
struct timeval timbuf[2];
Boolean is_a_directory= FALSE;
Boolean files_found= FALSE;
Boolean filing_subset= TRUE;
Boolean isdir= FALSE;
copyhandle(dest,src)
FilingSubset1_Handle dest,src;
{
if (dest == (Unspecified *) 0) {
fprintf(stderr,"Oops. dest is null in copyhandle\n");
exit(1);
}
dest[0] = src[0];
dest[1] = src[1];
}
getfilehandle(filename, handle)
char *filename;
FilingSubset1_Handle handle;
{
FilingSubset1_Attribute pathattr[1];
FilingSubset1_AttributeSequence attrseq;
FilingSubset1_OpenResults openresult;
Filing4_OpenResults openresult2;
if (filename == (char *)0 || *filename == '\000' || (strcmp(filename, "/") == 0) ) {
if ( filing_subset )
copyhandle(handle,FilingSubset1_nullHandle);
else
copyhandle(handle,rootHandle);
return;
}
attrseq.length = 1;
attrseq.sequence = pathattr;
pathattr[0].type = FilingSubset1_pathname;
copyhandle(handle, FilingSubset1_nullHandle);
#ifdef XEROXFSCOMPATIBILITY
if ( filename[0] == '/')
StringToAttr(filename+1, &pathattr[0]);
else
StringToAttr(filename, &pathattr[0]);
#else XEROXFSCOMPATIBILITY
StringToAttr(filename, &pathattr[0]);
#endif XEROXFSCOMPATIBILITY
alarm(0);
if ( filing_subset ) {
openresult = FilingSubset1_Open(connected, NULL, attrseq,
handle, nullControls,
session);
copyhandle(handle, openresult.file);
} else {
openresult2 = Filing4_Open(connected, NULL, attrseq,
handle, nullControls,
session);
copyhandle(handle, openresult2.file);
}
alarm(continuetime);
}
getdirhandle(filename, handle)
char *filename;
FilingSubset1_Handle handle;
{
FilingSubset1_Attribute pathattr[1];
FilingSubset1_AttributeSequence attrseq;
FilingSubset1_OpenResults openresult;
Filing4_OpenResults openresult2;
char *rindex();
char *slash, *bang;
if (filename == (char *)0 || *filename == '\000' || (strcmp(filename, "/") == 0) ) {
strcpy(cur_pathname, "/");
strcpy(cur_name, "/");
if ( filing_subset )
copyhandle(handle,FilingSubset1_nullHandle);
else
copyhandle(handle,rootHandle);
return;
} else if ( filename[0] == '/' ) {
strcpy(cur_pathname, filename);
} else {
strcpy(cur_pathname, cur_dir);
if ( strcmp(cur_pathname, "/") != 0 )
strcat(cur_pathname, "/");
strcat(cur_pathname, filename);
}
if ( (slash= rindex(cur_pathname,'/')) == NULL )
strcpy(cur_name, cur_pathname);
else
strcpy(cur_name, slash+1);
if ( (bang= rindex(cur_name, '!')) != NULL )
*bang= '\0';
if ( filing_subset ) {
copyhandle(handle, FilingSubset1_nullHandle);
} else {
if ( slash == cur_pathname) {
copyhandle(handle, rootHandle);
return;
}
attrseq.length = 1;
attrseq.sequence = pathattr;
pathattr[0].type = FilingSubset1_pathname;
copyhandle(handle, FilingSubset1_nullHandle);
*slash= '\0'; /* separate pathname from name */
#ifdef XEROXFSCOMPATIBILITY
if ( cur_pathname[0] == '/' )
StringToAttr(cur_pathname+1, &pathattr[0]);
else
StringToAttr(cur_pathname, &pathattr[0]);
#else XEROXFSCOMPATIBILITY
StringToAttr(cur_pathname, &pathattr[0]);
#endif XEROXFSCOMPATIBILITY
*slash= '/'; /* and put back */
alarm(0);
if ( filing_subset ) {
openresult = FilingSubset1_Open(connected, NULL, attrseq,
handle, nullControls,
session);
copyhandle(handle, openresult.file);
} else {
openresult2 = Filing4_Open(connected, NULL, attrseq,
handle, nullControls,
session);
copyhandle(handle, openresult2.file);
}
alarm(continuetime);
}
}
freefilehandle(handle)
FilingSubset1_Handle handle;
{
if (handle[0] == FilingSubset1_nullHandle[0] &&
handle[1] == FilingSubset1_nullHandle[1])
return; /* don't free nullHandle */
if (handle[0] == rootHandle[0] &&
handle[1] == rootHandle[1])
return; /* don't free root directory */
alarm(0);
if ( filing_subset )
FilingSubset1_Close(connected, NULL, handle, session);
else
Filing4_Close(connected, NULL, handle, session);
alarm(continuetime);
}
/*
* do a continue to make sure that the session doesn't time out.
* Note that this is usually called by an ALARM interrupt
*/
probe()
{
FilingSubset1_ContinueResults cresult;
Filing4_ContinueResults cresult2;
alarm(0); /* cancel previous alarms */
if ( filing_subset ) {
cresult = FilingSubset1_Continue(connected, NULL, session);
continuetime = cresult.continuance / 5; /* seconds */
} else {
cresult2 = Filing4_Continue(connected, NULL, session);
continuetime = cresult2.continuance / 5; /* seconds */
}
alarm(continuetime); /* reset for another 2 min. or so */
}
CourierConnection *
hookup(name)
char *name;
{
register struct ns_addr *hostaddr;
extern struct ns_addr *getXNSaddr();
Clearinghouse3_ObjectName defaultobjname;
static char hnamebuf[128];
CourierConnection *cconn;
CH_NameDefault(&defaultobjname);
hostobjname = CH_StringToName(name, &defaultobjname);
if ((hostaddr = CH_LookupAddrDN( hostobjname, 0, hnamebuf, 128))) {
/* should check here to be sure host is a file service */
hostaddr->x_port = htons(5); /* ?? */
cconn = CourierOpen(hostaddr);
if ( cconn == (CourierConnection *) 0 ) {
Cardinal problem;
problem= FilingSubset1_noResponse;
raise(FilingSubset1_ConnectionError, &problem);
}
/* reset objname to flush wildcards */
/* clear_Clearinghouse3_ThreePartName(&hostobjname); */
hostobjname = CH_StringToName(hnamebuf, &defaultobjname);
hostname = hnamebuf;
if (verbose)
printf("Connected to %s\n", hnamebuf);
} else {
printf("%s: unknown host\n", name);
usefiling= 0;
cconn = (CourierConnection*)0;
}
return(cconn);
}
login(name,pwd)
char *pwd;
char *name;
{
FilingSubset1_Credentials credentials;
FilingSubset1_LogonResults logonresult;
FilingSubset1_LogonResults *resultptr= &logonresult;
Filing4_LogonResults logonresult2;
FilingSubset1_AttributeSequence attrseq;
FilingSubset1_OpenResults openresult;
Filing4_OpenResults openresult2;
if ( name != 0 )
username = CH_StringToName(name,&hostobjname);
if ( usefiling ) {
usefiling= 0;
filing_subset= FALSE;
if ( name == 0 && pwd == 0 ) {
GetSimpleCredsAndVerifier(&username, 0,
&credentials.primary, &verifier);
} else {
MakeSimpleCredsAndVerifier(&username,pwd,
&credentials.primary, &verifier);
}
logonresult2= Filing4_Logon(connected, NULL, hostobjname,
credentials.primary, verifier);
resultptr= (FilingSubset1_LogonResults *) &logonresult2;
} else {
usefiling= 0;
if ( name == 0 && pwd == 0 ) {
GetSimpleCredsAndVerifier(&username, 0, &credentials.primary, &verifier);
MakeSecondaryCreds(hostobjname.object, 0, 0, &credentials.secondary);
} else {
MakeSimpleCredsAndVerifier(0, pwd, &credentials.primary, &verifier);
MakeSecondaryCreds(hostobjname.object, name, pwd, &credentials.secondary);
}
filing_subset= TRUE;
DURING
logonresult = FilingSubset1_Logon(connected, NULL, hostobjname,
credentials, verifier);
HANDLER {
switch (Exception.Code) {
case REJECT_ERROR:
filing_subset= FALSE;
logonresult2= Filing4_Logon(connected, NULL, hostobjname,
credentials.primary, verifier);
resultptr= (FilingSubset1_LogonResults *) &logonresult2;
break;
default:
connected= (CourierConnection *)0; /* reset */
RERAISE;
}
} END_HANDLER;
}
if ( filing_subset )
session = resultptr->session;
else
session = resultptr->session;
if (verbose)
printf("User %s:%s:%s logged on\n", username.object,
username.domain, username.organization);
attrseq.length= 0;
attrseq.sequence= 0;
if ( filing_subset ) {
openresult= FilingSubset1_Open(connected, NULL, attrseq,
FilingSubset1_nullHandle, nullControls,
session);
copyhandle(rootHandle, openresult.file);
} else {
openresult2= Filing4_Open(connected, NULL, attrseq,
FilingSubset1_nullHandle, nullControls,
session);
copyhandle(rootHandle, openresult2.file);
}
strcpy(cur_dir, ROOT_DIRECTORY);
alarm(0);
signal(SIGALRM, probe);
probe();
}
logout()
{
signal(SIGALRM, SIG_IGN);
if ( filing_subset )
FilingSubset1_Logoff(connected, NULL, session);
else
Filing4_Logoff(connected, NULL, session);
clear_FilingSubset1_Session(&session);
}
domakedir(dest)
char *dest;
{
struct timeval start, stop, time;
FilingSubset1_StoreResults storeresults;
Filing4_StoreResults storeresults2;
FilingSubset1_Handle dirhandle;
FilingSubset1_AttributeSequence attrseq;
FilingSubset1_Attribute attrvals[5];
gettimeofday(&time, (struct timezone *) 0);
if (dest) {
getdirhandle(dest, dirhandle);
} else {
printf("No remote name specified\n");
return;
}
bytessent= 0;
alarm(0);
attrseq.length= 3;
attrseq.sequence= attrvals;
if ( filing_subset ) {
attrvals[0].type= FilingSubset1_pathname;
StringToAttr(cur_pathname, &attrvals[0]);
} else {
attrvals[0].type= FilingSubset1_name;
StringToAttr(cur_name, &attrvals[0]);
}
attrvals[1].type = FilingSubset1_isDirectory;
BooleanToAttr(TRUE, &attrvals[1]);
attrvals[2].type = FilingSubset1_type;
LongCardinalToAttr(FilingSubset1_tDirectory, &attrvals[2]);
gettimeofday(&start, (struct timezone *)0);
if ( filing_subset )
storeresults = FilingSubset1_Store(connected, BDTclosewrite,
dirhandle, attrseq,
nullControls,
BulkData1_immediateSource, session);
else
storeresults2 = Filing4_Store(connected, BDTclosewrite,
dirhandle, attrseq,
nullControls,
BulkData1_immediateSource, session);
alarm(continuetime);
gettimeofday(&stop, (struct timezone *)0);
if ( filing_subset )
freefilehandle(storeresults.file);
else
freefilehandle(storeresults2.file);
freefilehandle(dirhandle);
}
doremovedir(src)
char *src;
{
dodelete(src);
}
dostore(src, dest)
char *src, *dest;
{
sendrequest("STOR", src, dest);
}
doappend(src, dest)
char *src, *dest;
{
NYI();
}
dorename(src, dest)
char *src, *dest;
{
Filing4_Handle srchandle, dirhandle;
Filing4_AttributeSequence attrseq;
Filing4_Attribute attrvals[1];
if ( filing_subset ) {
NotAvailableUnderSubset("Rename function not available");
return;
}
if ( index(dest, '/') != 0 ) { /* rename across directory */
docopy("MOVE", src, dest); /* use move */
return;
}
getdirhandle(src, dirhandle);
getfilehandle(cur_pathname, srchandle);
attrseq.length= 1;
attrseq.sequence= attrvals;
attrvals[0].type= Filing4_name;
StringToAttr(dest, &attrvals[0]);
if (verbose) {
printf("renaming %s to %s...\n", src, dest);
}
alarm(0);
Filing4_ChangeAttributes(connected, NULL, srchandle, attrseq, session);
alarm(continuetime);
freefilehandle(srchandle);
freefilehandle(dirhandle);
}
docopy(cmd, src, dest)
char *cmd, *src, *dest;
{
Filing4_Handle srchandle, srcdirhandle, dirhandle, newhandle;
Filing4_AttributeSequence attrseq;
Filing4_Attribute attrvals[1];
Filing4_AttributeTypeSequence typeseq;
Filing4_AttributeType attrs[2];
Filing4_ScopeSequence scopeseq;
Filing4_Scope scope;
Filing4_CopyResults copyresults;
Boolean copy= FALSE;
if ( filing_subset ) {
NotAvailableUnderSubset("Copy/Move function not available");
return;
}
if ( strcmp(cmd, "COPY") == 0 )
copy= TRUE;
getdirhandle(src, srcdirhandle);
getfilehandle(cur_pathname, srchandle);
freefilehandle(srcdirhandle);
getdirhandle(dest, dirhandle);
typeseq.length= 2; typeseq.sequence= attrs;
attrs[0]= Filing4_isDirectory;
attrs[1]= Filing4_pathname;
scopeseq.length= 1; scopeseq.sequence= &scope;
scope.designator= Filing4_filter;
scope.Filing4_filter_case.designator= Filing4_matches;
scope.Filing4_filter_case.Filing4_matches_case.attribute.type= Filing4_name;
StringToAttr(cur_name, &scope.Filing4_filter_case.Filing4_matches_case.attribute);
ProcEachSeq= isdirproc;
isdir= FALSE;
alarm(0);
Filing4_List(connected, GetAttributeSequences, dirhandle, typeseq,
scopeseq, BulkData1_immediateSink, session);
alarm(continuetime);
if ( isdir ) {
getfilehandle(cur_pathname, dirhandle); /* open directory as file */
attrseq.length= 0;
attrseq.sequence= attrvals;
} else {
attrseq.length= 1;
attrseq.sequence= attrvals;
attrvals[0].type= Filing4_name;
StringToAttr(cur_name, &attrvals[0]);
}
if (verbose) {
if ( copy )
printf("copying ");
else
printf("moving ");
printf("%s to %s%s%s...\n", src, dest, (isdir ? "/" : ""),
(isdir ? src : ""));
}
alarm(0);
if ( copy ) {
copyresults= Filing4_Copy(connected, NULL, srchandle, dirhandle,
attrseq, nullControls, session);
freefilehandle(copyresults.newFile);
} else {
Filing4_Move(connected, NULL, srchandle, dirhandle,
attrseq, session);
}
alarm(continuetime);
freefilehandle(srchandle);
freefilehandle(dirhandle);
}
dounify(remote)
char *remote;
{
Filing4_Handle dirhandle, remotehandle;
if ( filing_subset ) {
NotAvailableUnderSubset("Unify AccessLists");
return;
}
getdirhandle(remote, dirhandle);
getfilehandle(cur_pathname, remotehandle);
freefilehandle(dirhandle);
if ( verbose ) {
printf("unify access lists for %s\n", remote);
}
alarm(0);
Filing4_UnifyAccessLists(connected, NULL, remotehandle, session);
alarm(continuetime);
freefilehandle(remotehandle);
}
recvrequest(cmd, local, remote, mode)
char *cmd, *local, *remote, *mode;
{
FILE *popen();
int (*closefunc)(), pclose(), fclose();
int do_unlink= FALSE;
int pos, i;
struct timeval start, stop;
FilingSubset1_Handle remotehandle; /* note: an array */
FilingSubset1_Handle dirhandle; /* note: an array */
FilingSubset1_AttributeTypeSequence typeseq;
FilingSubset1_AttributeType tsvals[10];
char *dir;
FilingSubset1_ScopeSequence scopeseq;
FilingSubset1_Scope scope;
closefunc = NULL;
fout = stdout;
typeseq.length = 0; typeseq.sequence = tsvals;
scopeseq.length= 1; scopeseq.sequence= &scope;
scope.designator= FilingSubset1_filter;
scope.FilingSubset1_filter_case.designator= FilingSubset1_matches;
if ( filing_subset )
scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_pathname;
else
scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_name;
timbuf[0].tv_sec= 0;
copyhandle(remotehandle, FilingSubset1_nullHandle);
if (strcmp(local, "-") && *local != '|')
if (access(local, 2) < 0) {
dir = rindex(local, '/');
/* get a good error message */
if (dir != NULL) *dir = '\0';
if (access(dir ? local : ".", 2) < 0) {
perror(local);
goto bad;
}
if (dir != NULL) *dir = '/';
}
if (strcmp(local, "-") == 0)
fout = stdout;
else if (*local == '|') {
char *ptr;
ptr= local+1;
while (isspace(*ptr)) ptr++;
fout = popen(ptr, "w");
if (fout == NULL) {
perror(ptr);
goto bad;
}
closefunc = pclose;
} else {
fout = fopen(local, mode);
if (fout == NULL) {
perror(local);
goto bad;
}
closefunc = fclose;
}
if (remote) {
getdirhandle(remote, dirhandle);
}
bytessent= 0;
filetypevalue= typevalue;
if ( filing_subset )
StringToAttr(cur_pathname+1,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
else
StringToAttr(cur_name,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
if (strcmp(cmd,"NLST") == 0) {
typeseq.length = 1;
typeseq.sequence[0] = FilingSubset1_pathname;
ProcEachSeq = nlistproc;
alarm(0);
gettimeofday(&start, (struct timezone *)0);
if ( filing_subset )
FilingSubset1_List(connected, GetAttributeSequences, dirhandle,
typeseq, scopeseq,
BulkData1_immediateSink, session);
else
Filing4_List(connected, GetAttributeSequences, dirhandle,
typeseq, scopeseq,
BulkData1_immediateSink, session);
alarm(continuetime);
}
else if (strcmp(cmd,"LIST") == 0) {
typeseq.length = 7;
if ( filing_subset )
typeseq.sequence[0] = FilingSubset1_pathname;
else
typeseq.sequence[0] = FilingSubset1_name;
typeseq.sequence[1] = FilingSubset1_dataSize;
typeseq.sequence[2] = FilingSubset1_isDirectory;
typeseq.sequence[3] = FilingSubset1_isTemporary;
typeseq.sequence[4] = FilingSubset1_type;
typeseq.sequence[5] = FilingSubset1_createdOn;
typeseq.sequence[6] = FilingSubset1_version;
ProcEachSeq = listproc;
alarm(0);
gettimeofday(&start, (struct timezone *)0);
if ( filing_subset )
FilingSubset1_List(connected, GetAttributeSequences, dirhandle,
typeseq, scopeseq,
BulkData1_immediateSink, session);
else
Filing4_List(connected, GetAttributeSequences, dirhandle,
typeseq, scopeseq,
BulkData1_immediateSink, session);
alarm(continuetime);
}
else if (strcmp(cmd,"RETR") == 0) {
typeseq.length= 4;
typeseq.sequence[0]= FilingSubset1_createdOn;
typeseq.sequence[1]= FilingSubset1_pathname;
typeseq.sequence[2]= FilingSubset1_type;
typeseq.sequence[3]= FilingSubset1_isDirectory;
is_a_directory= FALSE;
ProcEachSeq= rlistproc;
alarm(0);
if ( filing_subset )
FilingSubset1_List(connected, GetAttributeSequences, dirhandle,
typeseq, scopeseq,
BulkData1_immediateSink, session);
else
Filing4_List(connected, GetAttributeSequences, dirhandle,
typeseq, scopeseq,
BulkData1_immediateSink, session);
alarm(continuetime);
if ( files_found ) {
if ( is_a_directory && (filetypevalue == FilingSubset1_tDirectory) ) {
if ( filing_subset ) {
NotAvailableUnderSubset("Cannot retrieve directory files");
do_unlink= TRUE;
goto error;
}
}
if (verbose) {
printf("%s...(%s)...", local, typetostring(filetypevalue));
fflush(stdout);
}
if ( (filetypevalue == FilingSubset1_tDirectory) ||
((filetypevalue > LAST_FILING_TYPE) &&
(filetypevalue != TYPE_Interpress) &&
(filetypevalue != TYPE_VPCanvas)) ) {
if ( filing_subset ) {
NotAvailableUnderSubset("Cannot retrieve Viewpoint files");
do_unlink= TRUE;
goto error;
}
alarm(0);
ProcEachSeq= GetAllAttributes;
Filing4_List(connected, GetAttributeSequences, dirhandle,
Filing4_allAttributeTypes, scopeseq,
BulkData1_immediateSink, session);
alarm(continuetime);
}
bytessent= 0;
getfilehandle(cur_pathname, remotehandle); /* get file handle */
alarm(0);
gettimeofday(&start, (struct timezone *)0);
if ( filing_subset ) {
FilingSubset1_Retrieve(connected, retrieveproc, remotehandle,
BulkData1_immediateSink, session);
} else {
if ( is_a_directory )
Filing4_Serialize(connected, retrieveproc, remotehandle,
BulkData1_immediateSink, session);
else
Filing4_Retrieve(connected, retrieveproc, remotehandle,
BulkData1_immediateSink, session);
}
alarm(continuetime);
}
} else if (strcmp(cmd,"SER") == 0) {
ProcEachSeq= GetAllAttributes;
alarm(0);
if ( filing_subset ) {
NotAvailableUnderSubset("Cannot serialize files");
do_unlink= TRUE;
goto error;
} else {
Filing4_List(connected, GetAttributeSequences, dirhandle,
Filing4_allAttributeTypes, scopeseq,
BulkData1_immediateSink, session);
}
alarm(continuetime);
if ( files_found ) {
if (verbose) {
printf("%s to %s...(%s)...",cur_pathname, local, typetostring(filetypevalue));
fflush(stdout);
}
bytessent= 0;
getfilehandle(cur_pathname, remotehandle); /* get file handle */
alarm(0);
gettimeofday(&start, (struct timezone *)0);
Filing4_Serialize(connected, retrieveproc, remotehandle,
BulkData1_immediateSink, session);
alarm(continuetime);
}
}
else printf("unrecognized command %s\n",cmd);
gettimeofday(&stop, (struct timezone *)0);
freefilehandle(remotehandle);
if ( files_found ) {
if (bytessent > 0 && verbose)
ptransfer("received", bytessent, &start, &stop);
} else {
printf("%s not found\n",cur_pathname);
do_unlink= TRUE;
}
error:
freefilehandle(dirhandle);
bad:
if (closefunc != NULL && fout != NULL) {
(*closefunc)(fout);
if ( closefunc == fclose ) {
if (timbuf[0].tv_sec != 0 )
utimes(local,&timbuf[0]);
}
}
if ( do_unlink )
unlink(local);
fout = NULL;
}
sendrequest(cmd, local, remote)
char *cmd, *local, *remote;
{
FILE *popen();
int (*closefunc)(), pclose(), fclose();
struct stat st;
struct timeval start, stop;
FilingSubset1_StoreResults storeresults;
Filing4_DeserializeResults deserializeresults;
Filing4_StoreResults storeresults2;
FilingSubset1_Handle dirhandle;
FilingSubset1_AttributeSequence attrseq;
FilingSubset1_Attribute attrvals[50];
Boolean GetDirectoryAttribute();
struct timeval time;
long createdate;
long datasize;
gettimeofday(&time,(struct timezone *) 0);
createdate= time.tv_sec + XNS_TIME_DIFFERENCE;
filetypevalue= typevalue;
closefunc = NULL;
if (strcmp(local, "-") == 0) {
fin = stdin;
closefunc = NULL;
} else if (*local == '|') {
char *ptr;
ptr= local+1;
while (isspace(*ptr)) ptr++;
fin = popen(ptr, "r");
if (fin == NULL) {
perror(ptr);
return;
}
closefunc = pclose;
} else {
if (typevalue == TYPE_Guess) {
filetypevalue= get_type(local); /* guess file type */
}
fin = fopen(local, "r");
if (fin == NULL) {
perror(local);
return;
}
closefunc = fclose;
if (fstat(fileno(fin), &st) < 0 ||
(st.st_mode&S_IFMT) != S_IFREG) {
fprintf(stderr, "%s: not a plain file.", local);
fclose(fin);
fin= NULL;
return;
}
createdate= st.st_mtime + XNS_TIME_DIFFERENCE;
datasize= st.st_size;
}
if (filetypevalue == TYPE_Guess) /* if input from file, TYPE_G should already be replaced */
filetypevalue= TYPE_A; /* assume ascii for pipes/stdin... */
if (remote) {
getdirhandle(remote, dirhandle);
} else {
printf("No remote name specified\n");
return;
}
bytessent = 0;
if (strcmp(cmd,"STOR") == 0) {
if (verbose) {
printf("%s to %s...",local,remote);
fflush(stdout);
}
attrseq.length = 1;
attrseq.sequence = attrvals;
if ( filing_subset ) {
attrvals[0].type = FilingSubset1_pathname;
StringToAttr(cur_pathname, &attrvals[0]);
} else {
attrvals[0].type = FilingSubset1_name;
StringToAttr(cur_name, &attrvals[0]);
}
if ( (filetypevalue == TYPE_Directory) ||
((filetypevalue > LAST_FILING_TYPE) &&
(filetypevalue != TYPE_Interpress) &&
(filetypevalue != TYPE_VPCanvas)) ) {
isdir= GetDirectoryAttribute(fin);
} else {
isdir= FALSE;
}
if ( !isdir ) {
attrseq.length += 4;
attrvals[1].type = FilingSubset1_type;
LongCardinalToAttr(filetypevalue, &attrvals[1]);
attrvals[2].type = FilingSubset1_createdOn;
LongCardinalToAttr(createdate,&attrvals[2]);
attrvals[3].type= FilingSubset1_isDirectory;
BooleanToAttr(FALSE, &attrvals[3]);
attrvals[4].type= FilingSubset1_dataSize;
LongCardinalToAttr(datasize, &attrvals[4]);
}
if (verbose) {
printf("(%s)...", typetostring(filetypevalue));
fflush(stdout);
}
if ( (filetypevalue == TYPE_Directory) ||
((filetypevalue > LAST_FILING_TYPE) &&
(filetypevalue != TYPE_Interpress) &&
(filetypevalue != TYPE_VPCanvas)) ) {
if ( filing_subset ) {
NotAvailableUnderSubset("Cannot store Viewpoint files");
goto error;
}
if ( isdir ) {
if ( AddExtendedDeserializeAttributes(fin, &attrseq) == 0 ) {
goto error;
}
} else {
if ( AddExtendedStoreAttributes(fin, &attrseq) == 0 ) {
goto error;
}
}
}
alarm(0);
gettimeofday(&start, (struct timezone *)0);
if ( filing_subset ) {
storeresults = FilingSubset1_Store(connected, storeproc,
dirhandle, attrseq,
nullControls,
BulkData1_immediateSource,
session);
} else {
if ( isdir )
deserializeresults = Filing4_Deserialize(connected, storeproc,
dirhandle, attrseq,
nullControls,
BulkData1_immediateSource,
session);
else
storeresults2 = Filing4_Store(connected, storeproc,
dirhandle, attrseq,
nullControls,
BulkData1_immediateSource,
session);
}
alarm(continuetime);
gettimeofday(&stop, (struct timezone *)0);
if ( filing_subset ) {
freefilehandle(storeresults.file);
} else {
if ( isdir )
freefilehandle(deserializeresults.file);
else
freefilehandle(storeresults2.file);
}
} else if (strcmp(cmd,"DSER") == 0) {
if ( filing_subset ) {
NotAvailableUnderSubset("Cannot Deserialize files");
goto error;
}
if (verbose) {
printf("%s to %s...",local,remote);
fflush(stdout);
}
attrseq.length = 1;
attrseq.sequence = attrvals;
attrvals[0].type = FilingSubset1_name;
StringToAttr(cur_name, &attrvals[0]);
if (verbose) {
printf("(%s)...", typetostring(filetypevalue));
fflush(stdout);
}
if ( AddExtendedDeserializeAttributes(fin, &attrseq) == 0 ) {
goto error;
}
alarm(0);
gettimeofday(&start, (struct timezone *)0);
deserializeresults = Filing4_Deserialize(connected, storeproc,
dirhandle, attrseq, nullControls,
BulkData1_immediateSource, session);
alarm(continuetime);
gettimeofday(&stop, (struct timezone *)0);
freefilehandle(deserializeresults.file);
}
else {
printf("unrecognized command %s\n",cmd);
alarm(continuetime);
}
if (bytessent > 0 && verbose)
ptransfer("sent", bytessent, &start, &stop);
error:
freefilehandle(dirhandle);
if (closefunc != NULL && fin != NULL)
(*closefunc)(fin);
fin = NULL;
}
docd(dest)
char *dest;
{
FilingSubset1_AttributeSequence attrseq;
FilingSubset1_AttributeTypeSequence typeseq;
Boolean current= FALSE;
FilingSubset1_AttributeType cdattrs[2];
FilingSubset1_ScopeSequence scopeseq;
FilingSubset1_Scope scope;
FilingSubset1_Handle remotehandle;
if (dest == (char*)NULL || *dest == '\0' || (strcmp(dest, "/") == 0) ) {
getdirhandle("/", remotehandle);
strcpy(cur_dir, "/");
dopwd();
return;
} else {
getdirhandle(dest, remotehandle);
}
isdir= FALSE;
if ( filing_subset ) {
StringToAttr(cur_pathname+1,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_pathname;
} else {
StringToAttr(cur_name,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_name;
}
typeseq.length = 2; typeseq.sequence = cdattrs;
cdattrs[0] = FilingSubset1_isDirectory;
cdattrs[1] = FilingSubset1_pathname;
scopeseq.length= 1; scopeseq.sequence= &scope;
scope.designator= FilingSubset1_filter;
scope.FilingSubset1_filter_case.designator= FilingSubset1_matches;
ProcEachSeq= cdproc;
alarm(0);
if ( filing_subset )
FilingSubset1_List(connected, GetAttributeSequences, remotehandle, typeseq,
scopeseq, BulkData1_immediateSink, session);
else
Filing4_List(connected, GetAttributeSequences, remotehandle, typeseq,
scopeseq, BulkData1_immediateSink, session);
alarm(continuetime);
freefilehandle(remotehandle);
if ( files_found == FALSE ) {
printf("%s not found\n", dest);
} else if ( !isdir ) {
printf("%s not a directory\n", dest);
} else {
if ( dest[0] != '/' ) {
if ( strcmp(cur_dir, "/") != 0 )
strcat(cur_dir, "/");
strcat(cur_dir, dest);
} else {
strcpy(cur_dir, dest);
}
if (verbose) dopwd();
}
}
dopwd()
{
printf("Remote working directory: %s\n",cur_dir);
}
dodelete(src)
char *src;
{
int i;
FilingSubset1_Handle remotehandle;
FilingSubset1_Handle dirhandle;
FilingSubset1_AttributeSequence attrseq;
FilingSubset1_AttributeTypeSequence typeseq;
FilingSubset1_AttributeType delattrs[2];
FilingSubset1_ScopeSequence scopeseq;
FilingSubset1_Scope scope;
typeseq.length = 2; typeseq.sequence= delattrs;
delattrs[0] = FilingSubset1_type;
delattrs[1]= FilingSubset1_pathname;
scopeseq.length= 1; scopeseq.sequence= &scope;
scope.designator= FilingSubset1_filter;
scope.FilingSubset1_filter_case.designator= FilingSubset1_matches;
name_count= 0;
name_size= MAXNAMES;
if ( (name_list= (struct name_entry *)malloc(sizeof(struct name_entry) * name_size)) == 0 ) {
perror("dodelete");
return;
}
getdirhandle(src, dirhandle);
if ( filing_subset ) {
scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_pathname;
StringToAttr(cur_pathname+1,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
} else {
scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_name;
StringToAttr(cur_name,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
}
ProcEachSeq= deleteproc;
alarm(0);
if ( filing_subset )
FilingSubset1_List(connected, GetAttributeSequences, dirhandle, typeseq,
scopeseq, BulkData1_immediateSink, session);
else
Filing4_List(connected, GetAttributeSequences, dirhandle, typeseq,
scopeseq, BulkData1_immediateSink, session);
alarm(continuetime);
freefilehandle(dirhandle);
for ( i= 0 ; i < name_count ; i++ ) {
struct name_entry *entry;
entry= &name_list[i];
if ( verbose ) {
if ( entry->type == TYPE_Directory ) {
if (!confirm("Delete directory", entry->pathname) ) {
clear_String(&entry->pathname);
continue;
}
} else if ( entry->type == TYPE_VPDrawer ) {
if (!confirm("Delete file drawer", entry->pathname) ) {
clear_String(&entry->pathname);
continue;
}
} else {
if (!confirm("Delete file",entry->pathname) ) {
clear_String(&entry->pathname);
continue;
}
}
}
getfilehandle(entry->pathname,remotehandle);
alarm(0);
if ( filing_subset )
FilingSubset1_Delete(connected, NULL, remotehandle, session);
else
Filing4_Delete(connected, NULL, remotehandle, session);
alarm(continuetime);
clear_String(&entry->pathname);
}
}
NYI()
{
printf("Not yet implemented\n");
}
NotAvailableUnderSubset(message)
char *message;
{
printf("%s under Subset,\n Reopen connection with -F switch and retry\n", message);
}
ptransfer(direction, bytes, t0, t1)
char *direction;
long bytes;
struct timeval *t0, *t1;
{
struct timeval td;
long ms;
float bs;
tvsub(&td, t1, t0);
ms = (td.tv_sec * 1000) + (td.tv_usec / 1000);
#define nz(x) ((x) == 0 ? 1 : (x))
bs = ((1000. * (float) bytes) / (float) nz(ms));
printf("\n%ld bytes %s in %d.%02d seconds (%.2g Kbytes/s)\n",
bytes, direction, td.tv_sec, td.tv_usec / 10000, bs / 1024.);
}
tvadd(tsum, t0)
struct timeval *tsum, *t0;
{
tsum->tv_sec += t0->tv_sec;
tsum->tv_usec += t0->tv_usec;
if (tsum->tv_usec > 1000000)
tsum->tv_sec++, tsum->tv_usec -= 1000000;
}
tvsub(tdiff, t1, t0)
struct timeval *tdiff, *t1, *t0;
{
tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
if (tdiff->tv_usec < 0)
tdiff->tv_sec--, tdiff->tv_usec += 1000000;
}
nlistproc(attr)
FilingSubset1_AttributeSequence attr;
{
int i;
char *thisname;
FilingSubset1_AttributeType t;
files_found= TRUE;
for (i = 0; i < attr.length; i++) {
t = attr.sequence[i].type;
if (t == FilingSubset1_pathname) {
thisname = AttrToString(&attr.sequence[i]);
#ifdef XEROXFSCOMPATIBILITY
/*
* Xerox File servers don't include beginning /
*/
if ( *thisname != '/' )
fputc('/', fout);
#endif XEROXFSCOMPATIIBLITY
fputs(thisname, fout);
fputc('\n', fout);
clear_String(&thisname);
return;
}
}
}
listproc(attr)
FilingSubset1_AttributeSequence attr;
{
int i;
char *thisname;
char *slash;
Boolean istemp = 0;
Boolean isdir = 0;
LongCardinal thistype = 0;
LongCardinal thissize = 0;
LongCardinal thisdate = 0;
FilingSubset1_AttributeType t;
char filetypestr[25];
char filetypebuf[20];
Cardinal thisversion = 0;
char *filedatestr;
char *ctime();
char *rindex();
files_found= TRUE;
for (i = 0; i < attr.length; i++) {
t = attr.sequence[i].type;
if (t == FilingSubset1_name || t == FilingSubset1_pathname)
thisname = AttrToString(&attr.sequence[i]);
else if (t == FilingSubset1_isDirectory)
isdir = AttrToBoolean(&attr.sequence[i]);
else if (t == FilingSubset1_isTemporary)
istemp = AttrToBoolean(&attr.sequence[i]);
else if (t == FilingSubset1_type)
thistype = AttrToLongCardinal(&attr.sequence[i]);
else if (t == FilingSubset1_dataSize)
thissize = AttrToLongCardinal(&attr.sequence[i]);
else if (t == FilingSubset1_version)
thisversion = AttrToCardinal(&attr.sequence[i]);
else if (t == FilingSubset1_createdOn) {
thisdate = AttrToLongCardinal(&attr.sequence[i]);
thisdate = thisdate - XNS_TIME_DIFFERENCE;
filedatestr= ctime(&thisdate);
filedatestr[24]= '\0';
filedatestr += 4;
}
}
strcpy(filetypestr, "(");
strcat(filetypestr, typetostring(thistype));
strcat(filetypestr, ")");
if ( (slash= rindex(thisname, '/')) == NULL )
slash= thisname;
else
slash++;
fprintf(fout, "%c%c%-16s%7ld %s %s",
isdir?'D':' ', istemp?'T':' ',
filetypestr, thissize, filedatestr, slash);
if ( thisversion != 0)
fprintf(fout,"!%d",thisversion);
fprintf(fout,"\n");
clear_String(&thisname);
}
/*
* process used by retrieve to get file type, createdOn and pathname
*/
rlistproc(attr)
FilingSubset1_AttributeSequence attr;
{
int i;
char *thisname;
FilingSubset1_AttributeType t;
char *AttrToString();
files_found= TRUE;
/*
* Xerox file servers will return all versions of the requested file in
* ascending version order. We assume that the last version will be the
* highest and remember that name so that the retrieve will pull the
* highest version of the file. If we request just the file with no
* version, the server will return the oldest version (not what I would
* expect...)
*/
for (i= 0; i < attr.length; i++) {
t= attr.sequence[i].type;
if (t == FilingSubset1_createdOn) {
gettimeofday(&timbuf[0],(struct timezone *)0);
timbuf[1].tv_sec= AttrToLongCardinal(&attr.sequence[i]) - XNS_TIME_DIFFERENCE;
timbuf[1].tv_usec= 0;
} else if (t == FilingSubset1_type) {
if (typevalue == TYPE_Guess) {
filetypevalue= AttrToLongCardinal(&attr.sequence[i]);
}
} else if (t == FilingSubset1_pathname) {
thisname= AttrToString(&attr.sequence[i]);
if (verbose) {
printf("%s to ", thisname);
fflush(stdout);
}
clear_String(&thisname);
} else if (t == FilingSubset1_isDirectory) {
is_a_directory= AttrToBoolean(&attr.sequence[i]);
}
}
}
cdproc(attr)
FilingSubset1_AttributeSequence attr;
{
char *AttrtoString();
char *dest;
int i;
files_found= TRUE;
dest= 0;
for (i= 0; i < attr.length; i++) {
if (attr.sequence[i].type == FilingSubset1_isDirectory
&& AttrToBoolean(&attr.sequence[i])) {
isdir= TRUE; /* if directory, change handles */
}
if (attr.sequence[i].type == FilingSubset1_pathname)
dest= AttrToString(&attr.sequence[i]);
}
if (!isdir || dest == 0) { /* if no directory or pathname */
isdir= FALSE; /* assume failure */
}
}
#define MAXPACKS 20
static
GetAttributeSequences(conn)
CourierConnection *conn;
{
int count, i;
Unspecified buffer[MAXWORDS*MAXPACKS], *bp, *bufend;
FilingSubset1_StreamOfAttributeSequence attrs;
Boolean overflow= FALSE;
files_found= FALSE;
bufend = buffer;
bp = buffer+((MAXWORDS-1)*MAXPACKS); /* end of available space */
while ((count = BDTread(conn, (char*)bufend,
MAXWORDS*sizeof(Unspecified))) > 0) {
bufend += count/sizeof(Unspecified);
bytessent += count;
if (bufend > bp) {
fprintf(stderr,"BDT read too big to fit\n");
BDTabort(conn);
/* should clear out stuff here if we knew how much
* fall back to previous block on the assumption
* we can give a truncated list
*/
bufend -= count/sizeof(Unspecified);
overflow=TRUE;
}
}
bp = buffer;
while (bp < bufend) {
bp += internalize_FilingSubset1_StreamOfAttributeSequence(&attrs,bp);
if (0 == (int) attrs.designator) {
for (i=0; i < attrs.nextSegment_case.segment.length; i++) {
(*ProcEachSeq)(
attrs.nextSegment_case.segment.sequence[i]);
}
free(attrs.nextSegment_case.segment.sequence);
} else {
for (i = 0; i < attrs.lastSegment_case.length; i++) {
(*ProcEachSeq)(
attrs.lastSegment_case.sequence[i]);
}
free(attrs.lastSegment_case.sequence);
return;
}
}
if ( overflow ) {
fprintf(stderr, "\nListing was truncated due to internal bulk data buffer size\n");
overflow= FALSE;
}
}
int
getBDTch(conn,bpp)
CourierConnection *conn;
u_char **bpp;
{
static u_char buffer[SPPMAXDATA];
static int count;
if (*bpp == NULL) {*bpp = buffer; count = 0;}
if (*bpp >= buffer+count) {
count=BDTread(conn,buffer,sizeof(buffer));
*bpp = buffer;
}
if (count <= 0) return(EOF);
else return(*((*bpp)++));
}
retrieveproc(conn)
CourierConnection *conn;
{
int count, ocount, ch, hashbytes;
char buffer[SPPMAXDATA];
int charset, charset16;
char *bp;
switch (filetypevalue) {
default :
errno = ocount = 0;
fflush(fout);
while ((count = BDTread(conn, buffer, sizeof(buffer))) > 0) {
if ((ocount = write(fileno(fout),buffer,count)) < 0) {
perror("write");
BDTabort(conn);
break;
}
bytessent += count;
if (hash) {
putchar('#');
fflush(stdout);
}
}
if (count < 0) perror("netin");
break;
case TYPE_VPMailNote :
case TYPE_A :
charset = 0; charset16 = 0; bp = NULL;
hashbytes = 0;
while ((ch = getBDTch(conn,&bp)) != EOF) {
if (ch == '\377') {
ch = getBDTch(conn,&bp);
if (ch == '\377') charset16 = 1;
else charset = ch;
continue;
}
if (charset16) {
charset = ch;
ch = getBDTch(conn,&bp);
}
switch (charset) {
case 0: /* normal character set -- minimal xlation */
if (ch == '\r') {
int nextch;
putc('\n',fout);
bytessent++;
if ( (nextch = getBDTch(conn,&bp)) != '\n'){
if (nextch == '\r')
putc('\n',fout);
else if ( nextch == ','+0200 )
putc('_',fout);
else if ( nextch != EOF )
putc(nextch,fout);
else
continue;
}
bytessent= bytessent++;
while (hash && bytessent >= hashbytes){
putchar('#');
fflush(stdout);
hashbytes += sizeof(buffer);
}
break;
}
else if (ch == ','+0200) ch = '_';
/* more mapping here */
putc(ch,fout);
bytessent++;
break;
default:
break; /* ignore */
}
}
if (hash) {
while (bytessent >= hashbytes) {
putchar('#');
hashbytes += sizeof(buffer);
}
putchar('\n');
fflush(stdout);
}
/* if (count < 0) perror("netin"); */
break;
}
}
storeproc(conn)
CourierConnection *conn;
{
int count, ocount;
u_char buffer[SPPMAXDATA];
u_char *bp;
errno = ocount = 0;
clearerr(fin);
switch (filetypevalue) {
default :
while ((count = fread(buffer, sizeof(char), SPPMAXDATA, fin)) > 0
&& (ocount = BDTwrite(conn, buffer, count)) > 0) {
bytessent += count;
if (hash) {
putchar('#');
fflush(stdout);
}
}
break;
case TYPE_VPMailNote :
case TYPE_A :
while ((count = fread(buffer, sizeof(char), SPPMAXDATA, fin))
> 0) {
ocount = count;
for (bp = buffer; count > 0; count--, bp++) {
if (*bp == '\n') *bp = '\r';
else if (*bp == '_') *bp = ','+0200;
/* more translations here */
}
if ((ocount = BDTwrite(conn, buffer, ocount)) <= 0)
break;
bytessent += ocount;
if (hash) {
putchar('#');
fflush(stdout);
}
}
break;
}
if (ocount < 0) {
BDTabort(conn);
perror("netout");
}
else if (ferror(fin)) {
BDTabort(conn);
perror("fread");
}
else
BDTclosewrite(conn);
}
isdirproc(attr)
FilingSubset1_AttributeSequence attr;
{
int i;
char *name;
FilingSubset1_AttributeType t;
for ( i= 0; i < attr.length; i++ ) {
t= attr.sequence[i].type;
if ( t == FilingSubset1_isDirectory ) {
isdir= AttrToBoolean(&attr.sequence[i]);
} else if ( t == FilingSubset1_pathname ) {
name= AttrToString(&attr.sequence[1]);
strcpy(cur_pathname, name);
clear_String(&name);
}
}
}
deleteproc(attr)
FilingSubset1_AttributeSequence attr;
{
int i;
char *name;
struct name_entry *entry;
FilingSubset1_AttributeType t;
if ( name_count > name_size ) {
name_size += MAXNAMES;
name_list= (struct name_entry *) realloc(name_list,
sizeof(struct name_entry) * name_size);
}
entry= &name_list[name_count];
for ( i= 0; i < attr.length; i++ ) {
t= attr.sequence[i].type;
if ( t == FilingSubset1_type ) {
entry->type= AttrToLongCardinal(&attr.sequence[i]);
} else if ( t == FilingSubset1_pathname ) {
entry->pathname= AttrToString(&attr.sequence[1]);
}
}
name_count++;
}
GetAllAttributes(attr)
FilingSubset1_AttributeSequence attr;
{
int i;
char *thisname;
FilingSubset1_AttributeType t;
int got_createdon, got_type, got_pathname;
files_found= TRUE;
got_createdon= got_pathname= got_type= 0;
/*
* Xerox file servers will return all versions of the requested file in
* ascending version order. We assume that the last version will be the
* highest and remember that name so that the retrieve will pull the
* highest version of the file. If we request just the file with no
* version, the server will return the oldest version (not what I would
* expect...)
*/
for (i= 0; i < attr.length; i++) {
t= attr.sequence[i].type;
if (t == FilingSubset1_createdOn) {
gettimeofday(&timbuf[0],(struct timezone *)0);
timbuf[1].tv_sec= AttrToLongCardinal(&attr.sequence[i]) - XNS_TIME_DIFFERENCE;
timbuf[1].tv_usec= 0;
got_createdon++;
} else if (t == FilingSubset1_type) {
if (typevalue == TYPE_Guess) {
filetypevalue= AttrToLongCardinal(&attr.sequence[i]);
}
got_type++;
} else if (t == FilingSubset1_pathname) {
thisname= AttrToString(&attr.sequence[i]);
strcpy(cur_pathname, thisname);
clear_String(&thisname);
got_pathname++;
}
if ( got_createdon && got_type && got_pathname )
break;
}
SaveExtendedAttributes(fout, attr);
return;
}