BSD 4_4_Lite2 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 23 Mar 1987 02:42:29 +0000 (18:42 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 23 Mar 1987 02:42:29 +0000 (18:42 -0800)
Work on file usr/src/contrib/xns/examples/archive/xnsarchive.c
Work on file usr/src/contrib/xns/examples/archive/xnsrestore.c

Synthesized-from: CSRG/cd3/4.4BSD-Lite2

usr/src/contrib/xns/examples/archive/xnsarchive.c [new file with mode: 0644]
usr/src/contrib/xns/examples/archive/xnsrestore.c [new file with mode: 0644]

diff --git a/usr/src/contrib/xns/examples/archive/xnsarchive.c b/usr/src/contrib/xns/examples/archive/xnsarchive.c
new file mode 100644 (file)
index 0000000..5c0761c
--- /dev/null
@@ -0,0 +1,592 @@
+#ifndef lint
+static char *rcsid = "$Header: xnsarchive.c,v 1.1 87/03/17 16:27:18 ed Exp $";
+#endif lint
+
+/*
+ * Copyright (c) 1986, 1987 Xerox Corporation.
+ */
+
+/* $Log:       xnsarchive.c,v $
+ * Revision 1.1  87/03/17  16:27:18  ed
+ * Initial revision
+ * 
+ * 
+ */
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <netns/ns.h>
+#include <netns/sp.h>
+#include <xnscourier/Filing4.h>
+#include <xnscourier/except.h>
+#include <xnscourier/CH.h>
+#include <xnscourier/filetypes.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 "/"
+
+CourierConnection *connected;
+Clearinghouse2_ObjectName hostobjname;
+Authentication2_Verifier verifier;
+
+/* the following 3 items make up the current session */
+Filing4_Session session;       /* the current session */
+Clearinghouse2_ObjectName username;
+Filing4_Handle rootHandle;
+char cur_dir[512]= 0;
+char cur_pathname[512]= 0;
+char cur_name[512]= 0;
+
+static Filing4_ControlSequence nullControls = {0,0};
+
+/* global data used to communicate with BDT procedures
+ */
+extern GetAttributeSequences(), GetAllAttributes(), 
+       listproc(), isdirproc(), retrieveproc();
+
+char *AttrToString();
+Boolean AttrToBoolean();
+LongCardinal AttrToLongCardinal();
+Cardinal AttrToCardinal();
+
+static (*ProcEachSeq)();
+static FILE *fout= stdout;
+FILE *lfile= NULL;
+
+Boolean files_found= FALSE;
+Boolean verbose= FALSE;
+Boolean unify= FALSE;
+Boolean is_a_directory= FALSE;
+char *logfile= 0;
+
+char *ctime();
+long time();
+char *service;
+extern int errno;
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       char *remotefile, *localfile;
+       int i;
+       CourierConnection *hookup();
+       int opt;
+       extern int optind;
+       extern char *optarg;
+
+       static char *options= "vul:";
+       static char *usage= "Usage: %s [-v] [-u] [-l log-file] remote-file1 local-file\n";
+
+       if ( argc < 2 ) {
+               fprintf(stderr, usage, argv[0]);
+               exit(1);
+       }
+
+       while ((opt= getopt(argc, argv, options)) != EOF) 
+               switch (opt) {
+                       case 'l' :
+                               logfile= optarg;
+                               break;
+                               
+                       case 'v' :
+                               verbose++;
+                               break;
+
+                       case 'u' :
+                               unify++;        /* unify accesslists */
+                               break;
+
+                       default:
+                               fprintf(stderr, "Invalid command option -%c\n", opt);
+                               exit(1);
+               }
+
+       if ( getserviceandfile(argv[optind], &service, &remotefile) == 1 ) {
+               fprintf(stderr, "Invalid name %s\n", argv[optind]);
+               exit(1);
+       }
+       localfile= argv[++optind];
+
+       DURING {
+               if ( (connected= hookup(service)) == (CourierConnection *)0 ) {
+                       fprintf(stderr, "\nCan't connect to %s\n", service);
+                       exit(1);
+               }
+               login(0,0);
+
+               if ( serializefile(remotefile,localfile) )
+                       exit(1);
+
+       } HANDLER {
+               FilingErrMsg(Exception.Code, Exception.Message);
+       } END_HANDLER;
+
+       return(0);
+}
+
+getserviceandfile(name, srvcptr, fileptr)
+char *name;
+char **srvcptr, **fileptr;
+{
+       char *sptr, *fptr;
+       char *index(), *rindex();
+
+       /*
+        * look for Xerox forms first:
+        *      [host]filename
+        */
+
+       if ( (sptr= index(name, '[')) != 0 ) {
+               if ( (fptr= index(sptr, ']')) != 0 ) {
+                       *fptr= '\0';
+                       *srvcptr= sptr + 1;
+                       *fileptr= fptr + 1;
+                       return(0);
+               } else
+                       return(1);
+       }
+
+       /*
+        *      (host)filename
+        */
+
+       if ( (sptr= index(name, '(')) != 0 ) {
+               if ( (fptr= index(sptr, ')')) != 0 ) {
+                       *fptr= '\0';
+                       *srvcptr= sptr + 1;
+                       *fileptr= fptr + 1;
+                       return(0);
+               } else
+                       return(1);
+       }
+
+       /*
+        * look for XNS style with trailing : delimiter
+        * (assumes no : in file name, use alternate spec instead)
+        *      object:domain:organization:filename
+        *              domain & organization are optional
+        */
+
+       if ( (fptr= rindex(name, ':')) != 0 ) {
+               *fptr= '\0';
+               *srvcptr= name;
+               *fileptr= fptr + 1;
+               return(0);
+       } else
+               return(1);
+}
+
+copyhandle(dest,src)
+       Filing4_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;
+       Filing4_Handle handle;
+{
+       Filing4_Attribute pathattr[1];
+       Filing4_AttributeSequence attrseq;
+       Filing4_OpenResults openresult;
+       Filing4_OpenResults openresult2;
+
+       if (filename == (char *)0 || *filename == '\000' || (strcmp(filename, "/") == 0) ) {
+               copyhandle(handle,rootHandle);
+               return;
+       }
+
+       attrseq.length = 1;
+       attrseq.sequence = pathattr;
+       pathattr[0].type = Filing4_pathname;
+       copyhandle(handle, Filing4_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);
+       openresult2 = Filing4_Open(connected, NULL, attrseq,
+                                 handle, nullControls,
+                                 session);
+       copyhandle(handle, openresult2.file);
+}
+
+getdirhandle(filename, handle)
+       char *filename;
+       Filing4_Handle handle;
+{
+       Filing4_Attribute pathattr[1];
+       Filing4_AttributeSequence attrseq;
+       Filing4_OpenResults openresult;
+       Filing4_OpenResults openresult2;
+       char *rindex();
+       char *slash;
+
+       if (filename == (char *)0 || *filename == '\000' || (strcmp(filename, "/") == 0) ) {
+               strcpy(cur_pathname, "/");
+               strcpy(cur_name, "/");
+               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 ( slash == cur_pathname) {
+               copyhandle(handle, rootHandle);
+               return;
+       }
+
+       attrseq.length = 1;
+       attrseq.sequence = pathattr;
+       pathattr[0].type = Filing4_pathname;
+       copyhandle(handle, Filing4_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);
+       openresult2 = Filing4_Open(connected, NULL, attrseq,
+                                 handle, nullControls, session);
+       copyhandle(handle, openresult2.file);
+}
+
+freefilehandle(handle)
+       Filing4_Handle handle;
+{
+       if (handle[0] == Filing4_nullHandle[0] &&
+           handle[1] == Filing4_nullHandle[1])
+               return;         /* don't free nullHandle */
+       if (handle[0] == rootHandle[0] &&
+           handle[1] == rootHandle[1])
+               return;         /* don't free root directory */
+       alarm(0);
+       Filing4_Close(connected, NULL, handle, session);
+}
+
+CourierConnection *
+hookup(name)
+       char *name;
+{
+       register struct ns_addr *hostaddr;
+       extern struct ns_addr *getXNSaddr();
+       Clearinghouse2_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);
+               /* reset objname to flush wildcards */
+               /* clear_Clearinghouse2_ThreePartName(&hostobjname); */
+               hostobjname = CH_StringToName(hnamebuf, &defaultobjname);
+       }
+       return(cconn);
+}
+
+
+login(name,pwd)
+       char *pwd;
+       char *name;
+{
+       Filing4_Credentials credentials;
+       Filing4_LogonResults logonresult;
+       Filing4_AttributeSequence attrseq;
+       Filing4_OpenResults openresult;
+
+
+       if ( name != 0 )
+               username = CH_StringToName(name,&hostobjname);
+
+       if ( name == 0 && pwd == 0 ) {
+               GetSimpleCredsAndVerifier(&username, 0, 
+                                       &credentials, &verifier);
+       } else {
+               MakeSimpleCredsAndVerifier(&username,pwd,
+                                       &credentials, &verifier);
+       }
+       logonresult= Filing4_Logon(connected, NULL, hostobjname,
+                                       credentials, verifier);
+       session = logonresult.session;
+
+       attrseq.length= 0;
+       attrseq.sequence= 0;
+       openresult= Filing4_Open(connected, NULL, attrseq,
+                                Filing4_nullHandle, nullControls,
+                                session);
+       copyhandle(rootHandle, openresult.file);
+       strcpy(cur_dir, ROOT_DIRECTORY);
+}
+
+logout()
+{
+       Filing4_Logoff(connected, NULL, session);
+       clear_Filing4_Session(&session);
+}
+
+
+serializefile(remote, local)
+       char *remote;
+       char *local;
+{
+       FILE *fopen();
+       Filing4_Handle remotehandle; /* note: an array */
+       Filing4_Handle dirhandle; /* note: an array */
+       Filing4_Handle listhandle; /* note: an array */
+       Filing4_AttributeTypeSequence typeseq;
+       Filing4_AttributeType tsvals[10];
+       Filing4_ScopeSequence scopeseq;
+       Filing4_Scope scope;
+       Filing4_ScopeSequence lscopeseq;
+       Filing4_Scope lscope;
+       long date;
+       int i;
+
+       scopeseq.sequence= &scope; lscopeseq.sequence= &lscope;
+
+       getdirhandle(remote, dirhandle);
+       getfilehandle(remote, remotehandle);    /* get file handle */
+
+       if ( (local == NULL) || (*local == '\0') ) {
+               local= cur_name;
+       } else if ( strcmp(local,"-") == 0 ) {
+               fout=stdout;
+       } else {
+               if ( (fout= fopen(local, "w")) == NULL ) {
+                       perror("fopen");
+                       return(1);
+               }
+       }
+
+       scopeseq.length= 1;
+       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);
+
+       if ( unify ) {
+               if ( verbose ) {
+                       fprintf(stderr, "   Unify access lists\n");
+               }
+               Filing4_UnifyAccessLists(connected, NULL, dirhandle, session);
+       }
+
+       if ( logfile ) {
+               if ( (lfile= fopen(logfile, "w")) != NULL ) {
+                       typeseq.length = 2;  typeseq.sequence = tsvals;
+                       typeseq.sequence[0] = Filing4_pathname;
+                       typeseq.sequence[1] = Filing4_isDirectory;
+
+                       is_a_directory= FALSE;
+
+                       ProcEachSeq = isdirproc;
+                       Filing4_List(connected, GetAttributeSequences, dirhandle,
+                                            typeseq, scopeseq,
+                                            BulkData1_immediateSink, session);
+
+                       /*
+                        * for a directory, we list all files...
+                        * for non-directory, just list it...
+                        */
+                       if ( is_a_directory ) {
+                               copyhandle(listhandle, remotehandle);
+                               lscopeseq.length= 1;
+                               lscope.designator= Filing4_depth;
+                               lscope.Filing4_depth_case= Filing4_allDescendants;
+                       } else {
+                               copyhandle(listhandle, dirhandle);
+                               lscopeseq.length= 1;
+                               lscope.designator= Filing4_filter;
+                               lscope.Filing4_filter_case.designator= Filing4_matches;
+                               lscope.Filing4_filter_case.Filing4_matches_case.attribute.type= Filing4_name;
+                               StringToAttr(cur_name,&lscope.Filing4_filter_case.Filing4_matches_case.attribute);
+                       }
+
+                       typeseq.length = 4;
+                       typeseq.sequence[0] = Filing4_pathname;
+                       typeseq.sequence[1] = Filing4_type;
+                       typeseq.sequence[2] = Filing4_createdOn;
+                       typeseq.sequence[3] = Filing4_modifiedOn;
+
+                       date= time(0);
+                       fprintf(lfile, "\n\n\tArchive of %s\n\tPerformed on %s\n\n\n", cur_pathname, ctime(&date));
+                       fprintf(lfile, "\tContents of archive file follows:\n\n");
+                       fprintf(lfile, "    Create date\t\t Modification Date\t    Type\t\t\t\t\tName\n\n");
+
+                       ProcEachSeq = listproc;
+                       Filing4_List(connected, GetAttributeSequences, listhandle,
+                                            typeseq, lscopeseq,
+                                            BulkData1_immediateSink, session);
+                       fclose(lfile);
+               }
+       }
+
+       ProcEachSeq = GetAllAttributes;
+       Filing4_List(connected, GetAttributeSequences, dirhandle,
+                            Filing4_allAttributeTypes, scopeseq,
+                            BulkData1_immediateSink, session);
+
+       if ( verbose ) {
+               fprintf(stderr, "   Serializing %s\n", cur_pathname);
+       }
+
+       Filing4_Serialize(connected, retrieveproc, remotehandle,
+                                BulkData1_immediateSink, session);
+
+       freefilehandle(remotehandle);
+       freefilehandle(dirhandle);
+}
+
+listproc(attr)
+       Filing4_AttributeSequence attr;
+{
+       int i;
+       char *thisname, *typetostring();
+       char createstr[30], modstr[30];
+       LongCardinal thistype, createdate, moddate;
+       Filing4_AttributeType t;
+
+       files_found= TRUE;
+       createdate= moddate= time(0);
+
+       for (i = 0; i < attr.length; i++) {
+               t = attr.sequence[i].type;
+               if (t == Filing4_pathname) {
+                       thisname = AttrToString(&attr.sequence[i]);
+               } else if (t == Filing4_type) {
+                       thistype = AttrToLongCardinal(&attr.sequence[i]);
+               } else if (t == Filing4_createdOn) {
+                       createdate= AttrToLongCardinal(&attr.sequence[i]);
+                       createdate= createdate - XNS_TIME_DIFFERENCE;
+                       strcpy(createstr, ctime(&createdate));
+                       createstr[24]= '\0';
+               } else if (t == Filing4_modifiedOn) {
+                       moddate= AttrToLongCardinal(&attr.sequence[i]);
+                       moddate= moddate - XNS_TIME_DIFFERENCE;
+                       strcpy(modstr, ctime(&moddate));
+                       modstr[24]= '\0';
+               }
+       }
+
+       fprintf(lfile, "%s\t%s\t%-16s\t%s\n", createstr+4, modstr+4, typetostring(thistype), thisname);
+       clear_String(&thisname);
+}
+
+isdirproc(attr)
+       Filing4_AttributeSequence attr;
+{
+       int i;
+       Filing4_AttributeType t;
+
+       files_found= TRUE;
+
+       for (i = 0; i < attr.length; i++) {
+               t = attr.sequence[i].type;
+               if (t == Filing4_isDirectory) {
+                       is_a_directory = AttrToBoolean(&attr.sequence[i]);
+               }
+       }
+
+}
+
+GetAllAttributes(attr)
+Filing4_AttributeSequence attr;
+{
+       SaveExtendedAttributes(fout, attr);
+
+}
+
+#define MAXPACKS 20
+static
+GetAttributeSequences(conn)
+       CourierConnection *conn;
+{
+       int count, i;
+       Unspecified buffer[MAXWORDS*MAXPACKS], *bp, *bufend;
+       Filing4_StreamOfAttributeSequence attrs;
+       
+       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);
+               if (bufend > bp) {
+                       fprintf(stderr,"BDT read too big to fit\n");
+                       BDTabort(conn);
+                       /* should clear out stuff here if we knew how much */
+               }
+       }
+       bp = buffer;
+       while (bp < bufend) {
+               bp += internalize_Filing4_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;
+               }
+       }
+}
+
+retrieveproc(conn)
+       CourierConnection *conn;
+{
+       int count, ocount, ch, fd;
+       char buffer[SPPMAXDATA];
+       char *bp;
+
+       errno = ocount = 0;
+       fflush(fout);
+       fd= fileno(fout);
+
+       while ((count = BDTread(conn, buffer, sizeof(buffer))) > 0) {
+               if ((ocount = write (fd, buffer, count)) < 0) {
+                       perror("write");
+                       BDTabort(conn);
+                       break;
+               }
+       }
+       if (count < 0) perror("netin");
+}
+
diff --git a/usr/src/contrib/xns/examples/archive/xnsrestore.c b/usr/src/contrib/xns/examples/archive/xnsrestore.c
new file mode 100644 (file)
index 0000000..9ca1706
--- /dev/null
@@ -0,0 +1,636 @@
+#ifndef lint
+static char *rcsid = "$Header: xnsrestore.c,v 1.1 87/03/17 16:27:26 ed Exp $";
+#endif lint
+
+/*
+ * Copyright (c) 1986, 1987 Xerox Corporation.
+ */
+
+/* $Log:       xnsrestore.c,v $
+ * Revision 1.1  87/03/17  16:27:26  ed
+ * Initial revision
+ * 
+ * 
+ */
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <netns/ns.h>
+#include <netns/sp.h>
+#include <xnscourier/Filing4.h>
+#include <xnscourier/except.h>
+#include <xnscourier/CH.h>
+#include <xnscourier/filetypes.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 "/"
+
+CourierConnection *connected;
+Clearinghouse2_ObjectName hostobjname;
+Authentication2_Verifier verifier;
+
+/* the following 3 items make up the current session */
+Filing4_Session session;       /* the current session */
+Clearinghouse2_ObjectName username;
+Filing4_Handle rootHandle;
+char cur_dir[512]= 0;
+char cur_pathname[512]= 0;
+char cur_name[512]= 0;
+
+static Filing4_ControlSequence nullControls = {0,0};
+
+/* global data used to communicate with BDT procedures
+ */
+extern GetAttributeSequences(), 
+       listproc(), isdirproc(), storeproc();
+
+char *AttrToString();
+Boolean AttrToBoolean();
+LongCardinal AttrToLongCardinal();
+Cardinal AttrToCardinal();
+
+static (*ProcEachSeq)();
+static FILE *fin= NULL;
+FILE *lfile= NULL;
+
+Boolean files_found= FALSE;
+Boolean verbose= FALSE;
+Boolean is_a_directory= FALSE;
+char *logfile= 0;
+
+char *ctime();
+long time();
+char *service;
+extern int errno;
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       char *remotefile;
+       char *localfile;
+       int i;
+       CourierConnection *hookup();
+       int opt;
+       extern int optind;
+       extern char *optarg;
+
+       static char *options= "vl:";
+       static char *usage= "Usage: %s [-v] [-l log-file] local-file remote-file\n";
+
+       if ( argc < 3 ) {
+               fprintf(stderr, usage, argv[0]);
+               exit(1);
+       }
+
+       while ((opt= getopt(argc, argv, options)) != EOF) 
+               switch (opt) {
+                       case 'l' :
+                               logfile= optarg;
+                               break;
+
+                       case 'v' :
+                               verbose++;
+                               break;
+
+                       default:
+                               fprintf(stderr, "Invalid command option -%c\n", opt);
+                               exit(1);
+               }
+
+       localfile= argv[optind];
+       optind++;
+       if ( getserviceandfile(argv[optind], &service, &remotefile) == 0 ) {
+               fprintf(stderr, "Invalid name %s\n", argv[optind]);
+               exit(1);
+       }
+       DURING {
+               if ( (connected= hookup(service)) == (CourierConnection *)0 ) {
+                               fprintf(stderr, "\nCan't connect to %s\n", service);
+                               exit(1);
+               }
+               login(0,0);
+
+               deserializefile(localfile, remotefile);
+
+       } HANDLER {
+               FilingErrMsg(Exception.Code, Exception.Message);
+       } END_HANDLER;
+
+       return(0);
+}
+
+getserviceandfile(name, srvcptr, fileptr)
+char *name;
+char **srvcptr, **fileptr;
+{
+       char *sptr, *fptr;
+       char *index(), *rindex();
+
+       /*
+        * look for Xerox forms first:
+        *      [host]filename
+        */
+
+       if ( (sptr= index(name, '[')) != 0 ) {
+               if ( (fptr= index(sptr, ']')) != 0 ) {
+                       *fptr= '\0';
+                       *srvcptr= sptr + 1;
+                       *fileptr= fptr + 1;
+                       return(1);
+               } else
+                       return(0);
+       }
+
+       /*
+        *      (host)filename
+        */
+
+       if ( (sptr= index(name, '(')) != 0 ) {
+               if ( (fptr= index(sptr, ')')) != 0 ) {
+                       *fptr= '\0';
+                       *srvcptr= sptr + 1;
+                       *fileptr= fptr + 1;
+                       return(1);
+               } else
+                       return(0);
+       }
+
+       /*
+        * look for XNS style with trailing : delimiter
+        * (assumes no : in file name, use alternate spec instead)
+        *      object:domain:organization:filename
+        *              domain & organization are optional
+        */
+
+       if ( (fptr= rindex(name, ':')) != 0 ) {
+               *fptr= '\0';
+               *srvcptr= name;
+               *fileptr= fptr + 1;
+               return(1);
+       } else
+               return(0);
+}
+
+copyhandle(dest,src)
+       Filing4_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;
+       Filing4_Handle handle;
+{
+       Filing4_Attribute pathattr[1];
+       Filing4_AttributeSequence attrseq;
+       Filing4_OpenResults openresult;
+       Filing4_OpenResults openresult2;
+
+       if (filename == (char *)0 || *filename == '\000' || (strcmp(filename, "/") == 0) ) {
+               copyhandle(handle,rootHandle);
+               return;
+       }
+
+       attrseq.length = 1;
+       attrseq.sequence = pathattr;
+       pathattr[0].type = Filing4_pathname;
+       copyhandle(handle, Filing4_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);
+       openresult2 = Filing4_Open(connected, NULL, attrseq,
+                                 handle, nullControls,
+                                 session);
+       copyhandle(handle, openresult2.file);
+}
+
+getdirhandle(filename, handle)
+       char *filename;
+       Filing4_Handle handle;
+{
+       Filing4_Attribute pathattr[1];
+       Filing4_AttributeSequence attrseq;
+       Filing4_OpenResults openresult;
+       Filing4_OpenResults openresult2;
+       char *rindex();
+       char *slash;
+
+       if (filename == (char *)0 || *filename == '\000' || (strcmp(filename, "/") == 0) ) {
+               strcpy(cur_pathname, "/");
+               strcpy(cur_name, "/");
+               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 ( slash == cur_pathname) {
+               copyhandle(handle, rootHandle);
+               return;
+       }
+
+       attrseq.length = 1;
+       attrseq.sequence = pathattr;
+       pathattr[0].type = Filing4_pathname;
+       copyhandle(handle, Filing4_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);
+       openresult2 = Filing4_Open(connected, NULL, attrseq,
+                                 handle, nullControls, session);
+       copyhandle(handle, openresult2.file);
+}
+
+freefilehandle(handle)
+       Filing4_Handle handle;
+{
+       if (handle[0] == Filing4_nullHandle[0] &&
+           handle[1] == Filing4_nullHandle[1])
+               return;         /* don't free nullHandle */
+       if (handle[0] == rootHandle[0] &&
+           handle[1] == rootHandle[1])
+               return;         /* don't free root directory */
+       alarm(0);
+       Filing4_Close(connected, NULL, handle, session);
+}
+
+CourierConnection *
+hookup(name)
+       char *name;
+{
+       register struct ns_addr *hostaddr;
+       extern struct ns_addr *getXNSaddr();
+       Clearinghouse2_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);
+               /* reset objname to flush wildcards */
+               /* clear_Clearinghouse2_ThreePartName(&hostobjname); */
+               hostobjname = CH_StringToName(hnamebuf, &defaultobjname);
+       }
+       return(cconn);
+}
+
+
+login(name,pwd)
+       char *pwd;
+       char *name;
+{
+       Filing4_Credentials credentials;
+       Filing4_LogonResults logonresult;
+       Filing4_AttributeSequence attrseq;
+       Filing4_OpenResults openresult;
+
+
+       if ( name != 0 )
+               username = CH_StringToName(name,&hostobjname);
+
+       if ( name == 0 && pwd == 0 ) {
+               GetSimpleCredsAndVerifier(&username, 0, 
+                                       &credentials, &verifier);
+       } else {
+               MakeSimpleCredsAndVerifier(&username,pwd,
+                                       &credentials, &verifier);
+       }
+       logonresult= Filing4_Logon(connected, NULL, hostobjname,
+                                       credentials, verifier);
+       session = logonresult.session;
+
+       attrseq.length= 0;
+       attrseq.sequence= 0;
+       openresult= Filing4_Open(connected, NULL, attrseq,
+                                Filing4_nullHandle, nullControls,
+                                session);
+       copyhandle(rootHandle, openresult.file);
+       strcpy(cur_dir, ROOT_DIRECTORY);
+}
+
+logout()
+{
+       Filing4_Logoff(connected, NULL, session);
+       clear_Filing4_Session(&session);
+}
+
+
+deserializefile(local, remote)
+       char *local;
+       char *remote;
+{
+       FILE *fopen();
+       Filing4_Handle remotehandle; /* note: an array */
+       Filing4_Handle dirhandle; /* note: an array */
+       Filing4_Handle listhandle; /* note: an array */
+       Filing4_DeserializeResults results;
+       Filing4_AttributeSequence attrseq;
+       Filing4_Attribute attrvals[50];
+       Filing4_AttributeTypeSequence typeseq;
+       Filing4_AttributeType tsvals[10];
+       Filing4_ScopeSequence scopeseq;
+       Filing4_Scope scope;
+       Filing4_ScopeSequence lscopeseq;
+       Filing4_Scope lscope;
+       int i;
+       char *name, *rindex();
+       long date;
+       Boolean piping= FALSE;
+
+       name= '\0';
+
+       scopeseq.sequence= &scope; lscopeseq.sequence= &lscope;
+       attrseq.sequence= attrvals;
+
+       if ( strcmp(local, "-") == 0 ) {
+               fin= stdin;
+               piping= TRUE;
+       } else {
+               if ( (fin= fopen(local, "r")) == NULL ) {
+                       perror("Cannot open local file ");
+                       return(1);
+               }
+               if ( (name= rindex(local, '/')) == 0 ) {
+                       name= local;
+               } else {
+                       name++;
+               }
+       }
+
+       getdirhandle(remote, dirhandle);
+
+       scopeseq.length= 1;
+       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);
+
+       typeseq.length = 2;  typeseq.sequence = tsvals;
+       typeseq.sequence[0] = Filing4_name;
+       typeseq.sequence[1] = Filing4_isDirectory;
+
+       is_a_directory= FALSE;
+
+       ProcEachSeq = isdirproc;
+       Filing4_List(connected, GetAttributeSequences, dirhandle,
+                                    typeseq, scopeseq,
+                                    BulkData1_immediateSink, session);
+
+       if ( files_found ) {
+               if ( is_a_directory ) {
+                       if ( piping ) {
+                               fprintf(stderr, "Must specify file name when pinput is from stdin\n");
+                               return(1);
+                       }
+                       freefilehandle(dirhandle);
+                       getfilehandle(remote, dirhandle);
+                       strcat(cur_pathname, "/");
+                       strcat(cur_pathname, name);
+               } else {
+                       name= cur_name;
+               }
+       } else {
+               name= cur_name;
+       }
+
+       attrseq.length= 1;
+       attrvals[0].type= Filing4_name;
+       StringToAttr(name, &attrvals[0]);
+
+       if ( AddExtendedDeserializeAttributes(fin, &attrseq) != -1 ) {
+               fprintf(stderr, "Cannot determine extended attributes\n");
+               fclose(fin);
+               return(1);
+       }
+
+       if ( verbose ) {
+               fprintf(stdout, "   Restoring %s\n", cur_pathname);
+       }
+
+       results= Filing4_Deserialize(connected, storeproc, dirhandle,
+                                attrseq, nullControls,
+                                BulkData1_immediateSink, session);
+
+       if ( logfile ) {
+               if ( (lfile= fopen(logfile, "w")) != NULL ) {
+                       scopeseq.length= 1;
+                       scope.designator= Filing4_filter;
+                       scope.Filing4_filter_case.designator= Filing4_matches;
+                       scope.Filing4_filter_case.Filing4_matches_case.attribute.type= Filing4_name;
+                       StringToAttr(name,&scope.Filing4_filter_case.Filing4_matches_case.attribute);
+       
+                       typeseq.length = 2;  typeseq.sequence = tsvals;
+                       typeseq.sequence[0] = Filing4_pathname;
+                       typeseq.sequence[1] = Filing4_isDirectory;
+       
+                       is_a_directory= FALSE;
+       
+                       ProcEachSeq = isdirproc;
+                       Filing4_List(connected, GetAttributeSequences, dirhandle,
+                                            typeseq, scopeseq,
+                                            BulkData1_immediateSink, session);
+
+                       /*
+                        * for a directory, we list all files...
+                        * for non-directory, just list it...
+                        */
+                       if ( is_a_directory ) {
+                               copyhandle(listhandle, results.file);
+                               lscopeseq.length= 1;
+                               lscope.designator= Filing4_depth;
+                               lscope.Filing4_depth_case= Filing4_allDescendants;
+                       } else {
+                               copyhandle(listhandle, dirhandle);
+                               lscopeseq.length= 1;
+                               lscope.designator= Filing4_filter;
+                               lscope.Filing4_filter_case.designator= Filing4_matches;
+                               lscope.Filing4_filter_case.Filing4_matches_case.attribute.type= Filing4_name;
+                               StringToAttr(name,&lscope.Filing4_filter_case.Filing4_matches_case.attribute);
+       
+                       }
+
+                       typeseq.length = 4;
+                       typeseq.sequence[0] = Filing4_pathname;
+                       typeseq.sequence[1] = Filing4_type;
+                       typeseq.sequence[2] = Filing4_createdOn;
+                       typeseq.sequence[3] = Filing4_modifiedOn;
+
+                       date= time(0);
+                       fprintf(lfile, "\n\n\tRestore of %s\n\tPerformed on %s\n\n\n", cur_pathname, ctime(&date));
+                       fprintf(lfile, "\tFiles restored as follows:\n\n");
+                       fprintf(lfile, "    Create Date\t\t Modification Date\t    Type\t\t\t\t\t\tName\n\n");
+       
+                       ProcEachSeq = listproc;
+                       Filing4_List(connected, GetAttributeSequences, listhandle,
+                                            typeseq, lscopeseq,
+                                            BulkData1_immediateSink, session);
+                       fclose(lfile);
+               }
+       }
+
+       freefilehandle(results.file);
+       freefilehandle(dirhandle);
+}
+
+listproc(attr)
+       Filing4_AttributeSequence attr;
+{
+       int i;
+       char *thisname, *typetostring();
+       char createstr[30], modstr[30];
+       LongCardinal thistype, createdate, moddate;
+       Filing4_AttributeType t;
+
+       files_found= TRUE;
+       createdate= moddate= time(0);
+
+       for (i = 0; i < attr.length; i++) {
+               t = attr.sequence[i].type;
+               if (t == Filing4_pathname) {
+                       thisname = AttrToString(&attr.sequence[i]);
+               } else if (t == Filing4_type) {
+                       thistype = AttrToLongCardinal(&attr.sequence[i]);
+               } else if (t == Filing4_createdOn) {
+                       createdate= AttrToLongCardinal(&attr.sequence[i]);
+                       createdate= createdate - XNS_TIME_DIFFERENCE;
+                       strcpy(createstr, ctime(&createdate));
+                       createstr[24]= '\0';
+               } else if (t == Filing4_modifiedOn) {
+                       moddate= AttrToLongCardinal(&attr.sequence[i]);
+                       moddate= moddate - XNS_TIME_DIFFERENCE;
+                       strcpy(modstr, ctime(&moddate));
+                       modstr[24]= '\0';
+               }
+       }
+
+       fprintf(lfile, "%s\t%s\t%-16s\t%s\n", createstr+4, modstr+4, typetostring(thistype), thisname);
+       clear_String(&thisname);
+}
+
+isdirproc(attr)
+       Filing4_AttributeSequence attr;
+{
+       int i;
+       Filing4_AttributeType t;
+       char *thisname;
+
+       files_found= TRUE;
+
+       for (i = 0; i < attr.length; i++) {
+               t = attr.sequence[i].type;
+               if (t == Filing4_isDirectory) {
+                       is_a_directory = AttrToBoolean(&attr.sequence[i]);
+               } else if (t == Filing4_name) {
+                       thisname= AttrToString(&attr.sequence[i]);
+                       strcpy(cur_name, thisname);
+                       clear_String(&thisname);
+               }
+       }
+
+}
+
+#define MAXPACKS 20
+static
+GetAttributeSequences(conn)
+       CourierConnection *conn;
+{
+       int count, i;
+       Unspecified buffer[MAXWORDS*MAXPACKS], *bp, *bufend;
+       Filing4_StreamOfAttributeSequence attrs;
+       
+       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);
+               if (bufend > bp) {
+                       fprintf(stderr,"BDT read too big to fit\n");
+                       BDTabort(conn);
+                       /* should clear out stuff here if we knew how much */
+               }
+       }
+       bp = buffer;
+       while (bp < bufend) {
+               bp += internalize_Filing4_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;
+               }
+       }
+}
+
+storeproc(conn)
+       CourierConnection *conn;
+{
+       int count, ocount, ch;
+       char buffer[SPPMAXDATA];
+       char *bp;
+
+       errno = ocount = 0;
+       clearerr(fin);
+
+       while ( ((count= fread(buffer, sizeof(char), SPPMAXDATA, fin)) != 0)
+                && (ocount= BDTwrite (conn, buffer, count)) > 0) {
+                       ;
+       }
+       if ( count < 0 ) {
+               BDTabort(conn);
+               perror("netout");
+               exit(1);
+       } else if ( ferror(fin) ) {
+               BDTabort(conn);
+               perror("fread");
+               exit(1);
+       } else {
+               BDTclosewrite(conn);
+       }
+}
+