home *** CD-ROM | disk | FTP | other *** search
- /*
- * ftp-actions.c : X/FTP interface routines for xarchie
- *
- * George Ferguson, ferguson@cs.rochester.edu, 23 Apr 1993.
- */
-
- #include <stdio.h>
- #include <fcntl.h> /* O_RDONLY, etc. */
- #include <X11/Intrinsic.h>
- #include <X11/Shell.h>
- #include <X11/StringDefs.h>
- #include <X11/Xaw/Form.h>
- #include <X11/Xaw/Command.h>
- #include <X11/Xaw/AsciiText.h>
- #include <X11/Xaw/Dialog.h>
- #include "config.h"
- #ifdef HAVE_SYS_PARAM_H
- #include <sys/param.h>
- #endif
- #include "db.h"
- #include "appres.h"
- #include "xarchie.h"
- #include "selection.h"
- #include "browser.h"
- #include "ftp.h"
- #include "view-file.h"
- #include "status.h"
- #include "popups.h"
- #include "xutil.h"
- #include "alert.h"
- #include "syserr.h"
- #include "debug.h"
-
- /*
- * Functions defined here
- */
- void initFtpActions();
- void ftpGetSelectedItems(),ftpOpenSelectedItems();
- void RegisterFtpFd(),UnregisterFtpFd();
- int ftpPrompt();
-
- static void ftpSelectedItems(),countFileToGet(),countFileToOpen(),addFile();
- static void ftpGetFinished(),ftpOpenOneFinished();
- static void initFtpTraceWidgets();
- static void ftpTraceDoneAction();
- static void ftpTraceReset(),ftpTraceFunc();
- static void inputCallback();
- static void ftpPromptCallback();
-
- /*
- * Data defined here
- */
- static char **ftpFilenames;
- static int numFtpFiles;
- static FtpContext *ftpCurrentContext;
-
- static Widget ftpTraceShell,ftpTraceText;
- static Boolean isPoppedUp;
-
- static XtActionsRec actionTable[] = {
- { "ftp-trace-done", ftpTraceDoneAction },
- };
-
- /* - - - - - - - - */
- /* Interface functions */
-
- void
- initFtpActions()
- {
- XtAppAddActions(appContext,actionTable,XtNumber(actionTable));
- }
-
- void
- ftpGetSelectedItems() /* Called from getAction() */
- {
- ftpSelectedItems(appResources.ftpLocalDir,appResources.ftpType,
- appResources.ftpPrompt,appResources.ftpStrip,
- countFileToGet,NULL,ftpGetFinished);
- }
-
- void
- ftpOpenSelectedItems() /* Called from openBrowser() */
- {
- ftpSelectedItems(tmpDirectory,"ascii",False,True,
- countFileToOpen,ftpOpenOneFinished,ftpGetFinished);
- }
-
- void
- ftpAbortTransfer()
- {
- DEBUG1("ftpAbortTransfer: ftpCurrentContext=0x%x\n",ftpCurrentContext);
- ftpAbort(ftpCurrentContext);
- DEBUG0("ftpAbortTransfer: done\n");
- }
-
- /* - - - - - - - - */
- /*
- * This function starts ftp retrieval of the items selected in the
- * browser into the local directory.
- */
- static void
- ftpSelectedItems(local_dir,typestr,prompt,strip,
- countProc,doneOneProc,doneAllProc)
- char *local_dir,*typestr;
- Boolean prompt,strip;
- void (*countProc)();
- FtpCallbackProc doneOneProc,doneAllProc;
- {
- char *host,*cwd;
- int type;
- #ifdef DEBUG
- int i;
- #endif
-
- DEBUG0("ftpSelectedItems: setting files to transfer\n");
- numFtpFiles = 0;
- forEachSelectedItem(countProc);
- if (numFtpFiles == 0) {
- return;
- }
- ftpFilenames = (char **)XtCalloc(numFtpFiles,sizeof(char *));
- numFtpFiles = 0;
- forEachSelectedItem(addFile);
- #ifdef DEBUG
- for (i=0; i < numFtpFiles; i++)
- fprintf(stderr,"ftpSelectedItems: ftpFilenames[%d] = \"%s\"\n",
- i,ftpFilenames[i]);
- #endif
- /* Is there a host? */
- if ((host=getWidgetString(hostText)) == NULL || *host == '\0') {
- alert0("No host specified for transfer!");
- return;
- }
- DEBUG1("ftpSelectedItems: host = \"%s\"\n",host);
- /* Optional remote directory */
- cwd = getWidgetString(locationText); /* Can be "" */
- DEBUG1("ftpSelectedItems: remote dir = \"%s\"\n",cwd);
- if (cwd && *cwd == '\0')
- cwd = NULL;
- /* Convert type to ARPA code */
- if (typestr == NULL || *typestr == 'a' || *typestr == 'A')
- type = TYPE_A;
- else if (*typestr == 'b' || *typestr == 'B')
- type = TYPE_I;
- else if (*typestr == 'e' || *typestr == 'E')
- type = TYPE_E;
- else
- type = atoi(typestr);
- /* Put up the tracing window if needed */
- if (appResources.ftpTrace) {
- if (ftpTraceShell == NULL)
- initFtpTraceWidgets();
- ftpTraceReset();
- isPoppedUp = True;
- XtPopup(ftpTraceShell,XtGrabNone);
- }
- /* Get the FTP context */
- ftpCurrentContext =
- ftpNewContext(host,"anonymous",appResources.ftpMailAddress,
- cwd,local_dir,type,strip,(numFtpFiles>1 && prompt),
- FTP_GET,ftpFilenames,numFtpFiles,
- (appResources.ftpTrace ? ftpTraceFunc : NULL),
- doneOneProc,doneAllProc);
- XtFree((char *)ftpFilenames);
- /* Here we go... */
- setBrowserState(BROWSER_FTP);
- ftpStart(ftpCurrentContext);
- DEBUG0("ftpSelectedItems: done\n");
- }
-
- /* - - - - - - - - */
- /* Functions called by ftpGetSelectedItems */
-
- /*ARGSUSED*/
- static void
- countFileToGet(dbp,list_index) /* complains about non-files */
- DbEntry *dbp;
- int list_index;
- {
- if (dbp->type == DB_FILE) {
- numFtpFiles += 1;
- } else {
- alert1("Can't retrieve non-file \"%s\".",dbp->name);
- }
- }
-
- /*ARGSUSED*/
- static void
- countFileToOpen(dbp,list_index) /* doesn't complain about non-files */
- DbEntry *dbp;
- int list_index;
- {
- if (dbp->type == DB_FILE) {
- numFtpFiles += 1;
- }
- }
-
- /*ARGSUSED*/
- static void
- addFile(dbp,list_index) /* adds filename to array */
- DbEntry *dbp;
- int list_index;
- {
- if (dbp->type == DB_FILE) {
- ftpFilenames[numFtpFiles++] = XtNewString(dbp->name);
- }
- }
-
- /* - - - - - - - - */
- /* FTP callbacks */
-
- /*
- * This function is called back when the ftp transfer is complete (for
- * whatever reason).
- */
- /*ARGUSED*/
- static void
- ftpGetFinished(ftpc)
- FtpContext *ftpc;
- {
- DEBUG1("ftpGetFinished(0x%x)...\n",ftpc);
- setBrowserState(BROWSER_READY);
- ftpFreeContext(ftpc);
- status0("Ready");
- DEBUG0("ftpGetFinished: done\n");
- }
-
- /*
- * This function is called back when a single file has been successfully
- * retrieved for Open.
- */
- /*ARGSUSED*/
- static void
- ftpOpenOneFinished(ftpc)
- FtpContext *ftpc;
- {
- char filename[MAXPATHLEN];
-
- DEBUG1("ftpOpenOneFinished(0x%x)...\n",ftpc);
- if (ftpc->local_dir && *(ftpc->local_dir))
- sprintf(filename,"%s/%s",ftpc->local_dir,ftpc->files[ftpc->this_file]);
- else
- strcpy(filename,ftpc->files[ftpc->this_file]);
- viewFile(filename);
- DEBUG0("ftpOpenOneFinished: done\n");
- }
-
- /* - - - - - - - - */
- /* Routines for tracing the ftp connection in a window */
-
- static void
- initFtpTraceWidgets()
- {
- Widget form;
-
- ftpTraceShell = XtCreatePopupShell("ftpTraceShell",
- topLevelShellWidgetClass,
- toplevel,NULL,0);
- form = XtCreateManagedWidget("ftpTraceForm",formWidgetClass,
- ftpTraceShell,NULL,0);
- (void)XtCreateManagedWidget("ftpTraceDismissButton",commandWidgetClass,
- form,NULL,0);
- ftpTraceText = XtCreateManagedWidget("ftpTraceText",asciiTextWidgetClass,
- form,NULL,0);
- XtRealizeWidget(ftpTraceShell);
- (void)XSetWMProtocols(XtDisplay(ftpTraceShell),XtWindow(ftpTraceShell),
- &WM_DELETE_WINDOW,1);
- }
-
- void
- setFtpTraceShellState(state)
- int state;
- {
- if (!isPoppedUp)
- return;
- switch (state) {
- case NormalState:
- XtMapWidget(ftpTraceShell);
- break;
- case IconicState:
- XtUnmapWidget(ftpTraceShell);
- break;
- }
- }
-
- /*ARGSUSED*/
- static void
- ftpTraceDoneAction(w,event,params,num_params)
- Widget w;
- XEvent *event;
- String *params;
- Cardinal *num_params;
- {
- isPoppedUp = False;
- XtPopdown(ftpTraceShell);
- }
-
- static void
- ftpTraceReset()
- {
- Arg args[1];
-
- XtSetArg(args[0],XtNstring,"");
- XtSetValues(ftpTraceText,args,1);
- }
-
- /*
- * This function is called back from within the ftp routines to monitor
- * the exchange of messages.
- */
- /*ARGSUSED*/
- static void
- ftpTraceFunc(ftpc,who,text)
- FtpContext *ftpc;
- int who; /* 0 => recvd, non-0 => sent */
- char *text; /* text of this message */
- {
- if (who)
- appendWidgetText(ftpTraceText,"ftp> ");
- appendWidgetText(ftpTraceText,text);
- if (*(text+strlen(text)-1) != '\n')
- appendWidgetText(ftpTraceText,"\n");
- }
-
- /* - - - - - - - - */
- /* File descriptor registration routines: */
-
- /*
- * We need as many of these as there are file descriptors. It's
- * easier to guess big than to figure out where such a magic number lives.
- */
- #define NUMFDS 64
- FtpCallbackProc ftpRegisteredProcs[NUMFDS];
- FtpContext *ftpRegisteredContexts[NUMFDS];
- XtInputId ftpRegisteredIds[NUMFDS];
-
- /*
- * This function is exported and used by the FTP routines to register
- * a file descriptor for notification. We register it by recording the
- * callback information (proc and ftpc) and telling X to register the
- * fd as an external input source. When X calls back to inputCallback(),
- * we use the stored information to call back to the FTP routine.
- * Got that?
- */
- void
- RegisterFtpFd(ftpc,fd,flags,proc)
- FtpContext *ftpc;
- int fd,flags;
- FtpCallbackProc proc;
- {
- XtInputMask condition;
-
- DEBUG3("RegisterFtpFd: ftpc=0x%x, fd=%d, flags=%d\n",ftpc,fd,flags);
- if (fd < 0 || fd >= NUMFDS) {
- fprintf(stderr,"YOW! Attempt to register fd %d!\n",fd);
- #ifdef DEBUG
- abort();
- #endif
- return;
- }
- switch (flags) {
- case O_RDONLY:
- condition = XtInputReadMask;
- break;
- case O_WRONLY:
- condition = XtInputWriteMask;
- break;
- case O_RDWR:
- condition = XtInputReadMask | XtInputWriteMask;
- break;
- }
- ftpRegisteredProcs[fd] = proc;
- ftpRegisteredContexts[fd] = ftpc;
- ftpRegisteredIds[fd] =
- XtAppAddInput(appContext,fd,(XtPointer)condition,inputCallback,NULL);
- DEBUG1("RegisterFtpFd: done: id=0x%x\n",ftpRegisteredIds[fd]);
- }
-
- /*
- * Called back when X says source is ready. We call the function registered
- * by the FTP routines, passing the context.
- */
- /*ARGSUSED*/
- static void
- inputCallback(client_data,source,id)
- XtPointer client_data;
- int *source;
- XtInputId *id;
- {
- if (ftpRegisteredProcs[*source] != NULL) {
- (*(ftpRegisteredProcs[*source]))(ftpRegisteredContexts[*source]);
- } else {
- fprintf(stderr,"YOW! Callback for fd=%d not registered!\n",*source);
- #ifdef DEBUG
- abort();
- #endif
- }
- }
-
- /*
- * This function is exported and used by the FTP routines to undo
- * a previous registration.
- */
- /*ARGSUSED*/
- void
- UnregisterFtpFd(ftpc,fd)
- FtpContext *ftpc;
- int fd;
- {
- DEBUG3("UnregisterFtpFd: ftpc=0x%x, fd=%d, id=0x%x\n",
- ftpc,fd,ftpRegisteredIds[fd]);
- if (fd < 0 || fd >= NUMFDS) {
- fprintf(stderr,"YOW! Attempt to unregister fd %d!\n",fd);
- #ifdef DEBUG
- abort();
- #endif
- return;
- }
- if (ftpRegisteredIds[fd] != (XtInputId)NULL)
- XtRemoveInput(ftpRegisteredIds[fd]);
- ftpRegisteredIds[fd] = (XtInputId)NULL;
- ftpRegisteredProcs[fd] = NULL;
- ftpRegisteredContexts[fd] = NULL;
- DEBUG0("UnregisterFtpFd: done\n");
- }
-
- /* - - - - - - - - */
- /* Routines for prompting during FTP transfers: */
-
- static Widget ftpPromptShell;
- static int ftpPromptResult;
-
- int
- ftpPrompt(ftpc)
- FtpContext *ftpc;
- {
- char str[256];
-
- if (ftpPromptShell == NULL)
- ftpPromptShell = createPopup("ftpPrompt",4,ftpPromptCallback);
- sprintf(str,"%s %s?",
- (ftpc->filecmd==FTP_GET?"GET":"PUT"),ftpc->files[ftpc->this_file]);
- setPopupLabel(ftpPromptShell,"ftpPrompt",str);
- popupMainLoop(ftpPromptShell);
- return(ftpPromptResult);
- }
-
- /*ARGSUSED*/
- static void
- ftpPromptCallback(w,client_data,call_data)
- Widget w;
- XtPointer client_data; /* button number */
- XtPointer call_data;
- {
- switch ((int)client_data) {
- case 0: /* Yes */
- ftpPromptResult = 1;
- break;
- case 1: /* No */
- ftpPromptResult = 0;
- break;
- case 2: /* All */
- ftpCurrentContext->prompt = 0;
- ftpPromptResult = 1;
- break;
- case 3: /* Abort */
- ftpCurrentContext->this_file = ftpCurrentContext->num_files;
- ftpPromptResult = 0;
- break;
- }
- popupDone();
- }
-