home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / UNIX / ARCHIE / CLIENTS / XARCHIE2.TAR / xarchie.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-12  |  17.7 KB  |  618 lines

  1. /*
  2.  * xarchie : An X browser interface to Archie
  3.  *
  4.  * This file is sort of a mishmash of functions, some of which might get
  5.  * sorted out later. Its primary purpose is to establish the X connection,
  6.  * create the application's widgets, call any other other necessary
  7.  * initialization routines, and enter XtAppMainLoop(). It also provides
  8.  * the callback procedure selectItem() that makes the List widgets work
  9.  * like a browser (in collaboration with the display routines in db.c).
  10.  * Finally, it provides the generic setText(), setLabel(), and status*()
  11.  * routines which could go just about anywhere.
  12.  *
  13.  * George Ferguson, ferguson@cs.rochester.edu, 12 Nov 1991.
  14.  *
  15.  */
  16. #include <stdio.h>
  17. #include <signal.h>
  18. #include <sys/time.h>
  19. #include <X11/Intrinsic.h>
  20. #include <X11/StringDefs.h>
  21. #include <X11/Shell.h>    
  22. #include <X11/Xaw/Paned.h>    
  23. #include <X11/Xaw/Viewport.h>    
  24. #include <X11/Xaw/List.h>    
  25. #include <X11/Xaw/Form.h>    
  26. #include <X11/Xaw/Box.h>
  27. #include <X11/Xaw/Label.h>    
  28. #include <X11/Xaw/AsciiText.h>    
  29. #include <X11/Xaw/Command.h>    
  30. #include <X11/Xaw/Cardinals.h>    
  31. #include "types.h"
  32. #include "appres.h"
  33. #include "classnames.h"
  34. #include "db.h"
  35. #include "actions.h"
  36. #include "settings.h"
  37. #include "patchlevel.h"
  38.  
  39. /*    -    -    -    -    -    -    -    -    */
  40. /*
  41.  * Functions defined in this file:
  42.  */
  43. int main();
  44. void initWidgetsFromString();
  45. void displayHostInfo(), clearHostInfo();
  46. void displayLocationInfo(), clearLocationInfo();
  47. void displayFileInfo(), clearFileInfo();
  48. void setText(), setLabel();
  49. void status0(), status1(), status2();
  50. void fail0(), fail1();
  51.  
  52. static void initGraphics(), initWidgets(), initErrorHandlers();
  53. static void selectItem();
  54. static void syntax();
  55.  
  56. /*
  57.  * Global graphics data
  58.  */
  59. Display *display;
  60. Screen *screen;
  61. Window root;
  62.  
  63. /*
  64.  * Global widget data
  65.  */
  66. XtAppContext appContext;
  67. Widget toplevel;
  68. Widget hostList,locationList,fileList;
  69. Widget searchText;
  70. Widget queryButton,abortButton;        /* global since changes sensitivity */
  71.  
  72. static Widget statusText;
  73. static Widget hostText,locationText,fileText,sizeText,modesText,dateText;
  74.  
  75. /*
  76.  * Other global data
  77.  */
  78. Database *db;
  79. char *progname;
  80.  
  81. /*
  82.  * The application resources
  83.  */
  84. AppResources appResources;
  85.  
  86. /*
  87.  * Non-widget resources obtained from resource manager
  88.  */
  89. static XtResource resources[] = {
  90.     { "widgets", "Widgets", XtRString, sizeof(String),
  91.       XtOffset(AppResources *,widgets), XtRImmediate, "" },
  92.     { "menus", "Menus", XtRString, sizeof(String),
  93.       XtOffset(AppResources *,menus), XtRImmediate, "" },
  94.     { "searchType", "SearchType", GfRSearchType, sizeof(SearchType),
  95.       XtOffset(AppResources *,searchType), XtRImmediate, (XtPointer)GfExact },
  96.     { "sortType", "SortType", GfRSortType, sizeof(SortType),
  97.       XtOffset(AppResources *,sortType), XtRImmediate, (XtPointer)GfDefault },
  98.     { "archieHost", "ArchieHost", XtRString, sizeof(String),
  99.       XtOffset(AppResources *,archieHost), XtRImmediate, "archie.sura.net" },
  100.     { "maxHits", "MaxHits", XtRInt, sizeof(int),
  101.       XtOffset(AppResources *,maxHits), XtRImmediate, (XtPointer)99 },
  102.     { "offset", "Offset", XtRInt, sizeof(int),
  103.       XtOffset(AppResources *,offset), XtRImmediate, (XtPointer)0 },
  104.     { "timeout", "Timeout", XtRInt, sizeof(int),
  105.       XtOffset(AppResources *,timeout), XtRImmediate, (XtPointer)0 },
  106.     { "retries", "Retries", XtRInt, sizeof(int),
  107.       XtOffset(AppResources *,retries), XtRImmediate, (XtPointer)0 },
  108.     { "niceLevel", "NiceLevel", XtRInt, sizeof(int),
  109.       XtOffset(AppResources *,niceLevel), XtRImmediate, (XtPointer)0 },
  110.     { "ftpDir", "FtpDir", XtRString, sizeof(String),
  111.       XtOffset(AppResources *,ftpDir), XtRImmediate, "." },
  112.     { "ftpType", "FtpType", XtRString, sizeof(String),
  113.       XtOffset(AppResources *,ftpType), XtRImmediate, "binary" },
  114.     { "debugLevel", "DebugLevel", XtRInt, sizeof(int),
  115.       XtOffset(AppResources *,debugLevel), XtRImmediate, (XtPointer)0 },
  116.     { "settingsWidgets", "SettingsWidgets", XtRString, sizeof(String),
  117.       XtOffset(AppResources *,settingsWidgets), XtRImmediate, "" },
  118.     { "saveFormatOneLine", "SaveFormatOneLine", XtRBoolean, sizeof(Boolean),
  119.       XtOffset(AppResources *,saveFormatOneLine), XtRImmediate,
  120.                             (XtPointer)False },
  121.     { "expert", "Expert", XtRBoolean, sizeof(Boolean),
  122.       XtOffset(AppResources *,expert), XtRImmediate, (XtPointer)False },
  123. };
  124.  
  125. /*
  126.  * Non-widget resources set on command line.
  127.  */
  128. static XrmOptionDescRec options[] = {
  129.     { "-search",  ".searchType", XrmoptionSepArg, (XtPointer)"exact" },
  130.     { "-e",      ".searchType", XrmoptionNoArg,  (XtPointer)"exact" },
  131.     { "-s",      ".searchType", XrmoptionNoArg,  (XtPointer)"substr" },
  132.     { "-c",      ".searchType", XrmoptionNoArg,  (XtPointer)"subcase" },
  133.     { "-r",      ".searchType", XrmoptionNoArg,  (XtPointer)"regexp" },
  134.     { "-es",      ".searchType", XrmoptionNoArg,  (XtPointer)"exactSubstr" },
  135.     { "-ec",      ".searchType", XrmoptionNoArg,  (XtPointer)"exactSubcase" },
  136.     { "-er",      ".searchType", XrmoptionNoArg,  (XtPointer)"exactRegexp" },
  137.     { "-sort",    ".sortType",     XrmoptionSepArg, (XtPointer)"default" },
  138.     { "-t",      ".sortType",     XrmoptionNoArg,  (XtPointer)"invdate" },
  139.     { "-host",      ".archieHost", XrmoptionSepArg,
  140.                     (XtPointer)"archie.sura.net" },
  141.     { "-maxhits", ".maxHits",     XrmoptionSepArg, (XtPointer)"99" },
  142.     { "-offset",  ".offset",     XrmoptionSepArg, (XtPointer)"0" },
  143.     { "-nice",    ".niceLevel",     XrmoptionSepArg, (XtPointer)"0" },
  144.     { "-N",       ".niceLevel",     XrmoptionSepArg, (XtPointer)"0" },
  145.     { "-debug",      ".debugLevel", XrmoptionSepArg, (XtPointer)"1" },
  146.     { "-D",      ".debugLevel", XrmoptionSepArg, (XtPointer)"1" },
  147.     { "-expert",  ".expert",     XrmoptionNoArg,  (XtPointer)"True" },
  148. };
  149.  
  150. /*
  151.  * Widget and non-widget resources if the application defaults
  152.  * file can't be found.
  153.  * Generated automatically from Xarchie.ad by "ad2c".
  154.  * Comment out the include line (but not the NULL) if you don't want
  155.  * any resources compiled in.
  156.  */
  157. static String fallbackResources[] = {
  158. #include "Xarchie.ad.h"
  159.     NULL
  160. };
  161.  
  162. /*    -    -    -    -    -    -    -    -    */
  163.  
  164. main(argc,argv)
  165. int argc;
  166. char **argv;
  167. {
  168.     char buf[64];
  169.  
  170.     progname = argv[0];
  171.     initGraphics(&argc,argv);
  172.     if (argc > 1) {
  173.     syntax(argc,argv);
  174.     XtDestroyApplicationContext(appContext);
  175.     exit(1);
  176.     }
  177.     initErrorHandlers();
  178.     initSettingsDefaults();
  179.     initWidgets();
  180.     XtRealizeWidget(toplevel);
  181.     /* Set window title to indicate version */
  182.     sprintf(buf,"xarchie %d.%d%s",xarchieMajorVersion,
  183.                   xarchieMinorVersion,
  184.                   xarchieExtraVersion);
  185.     XStoreName(display,XtWindow(toplevel),buf);
  186.     sprintf(buf,"Welcome to xarchie %d.%d%s",xarchieMajorVersion,
  187.                          xarchieMinorVersion,
  188.                          xarchieExtraVersion);
  189.     status0(buf);
  190.     /* get the data structure for responses */
  191.     db = newDb();
  192.     /* do it */
  193.     XtAppMainLoop(appContext);
  194.     /*NOTREACHED*/
  195. }
  196.  
  197. /*    -    -    -    -    -    -    -    -    */
  198. /* Initialization routines */
  199.  
  200. static void
  201. initGraphics(argcp,argv)
  202. int *argcp;
  203. char **argv;
  204. {
  205.     toplevel = XtAppInitialize(&appContext, "Xarchie",
  206.                    options, XtNumber(options),
  207.                    argcp,argv,fallbackResources,NULL,ZERO);
  208.     initConverters(appContext);
  209.     XawSimpleMenuAddGlobalActions(appContext);
  210.     XtAppAddActions(appContext,actionTable,XtNumber(actionTable));
  211.     XtGetApplicationResources(toplevel,(XtPointer)&appResources,
  212.                               resources,XtNumber(resources),NULL,ZERO);
  213.     display = XtDisplay(toplevel);
  214.     screen = XtScreen(toplevel);
  215.     root = RootWindowOfScreen(screen);
  216. }
  217.  
  218. /*
  219.  * initWidgets: Initialize the widgets given in the .widgets resource,
  220.  *    check for required widgets, and set globals vars.
  221.  */
  222. static void
  223. initWidgets()
  224. {
  225.     initWidgetsFromString(appResources.widgets,".widgets");
  226.     /* check for the necessary widgets and set the global variables */
  227.     if ((hostList=XtNameToWidget(toplevel,"*hostList")) == NULL)
  228.     fail0("didn't create widget \"hostList\"");
  229.     if ((locationList=XtNameToWidget(toplevel,"*locationList")) == NULL)
  230.     fail0("didn't create widget \"locationList\"");
  231.     if ((fileList=XtNameToWidget(toplevel,"*fileList")) == NULL)
  232.     fail0("didn't create widget \"fileList\"");
  233.     if ((searchText=XtNameToWidget(toplevel,"*searchText")) == NULL)
  234.     fail0("didn't create widget \"searchText\"");
  235.     /* set globals for optional widgets */
  236.     statusText = XtNameToWidget(toplevel,"*statusText");
  237.     hostText = XtNameToWidget(toplevel,"*hostText");
  238.     locationText = XtNameToWidget(toplevel,"*locationText");
  239.     fileText = XtNameToWidget(toplevel,"*fileText");
  240.     sizeText = XtNameToWidget(toplevel,"*sizeText");
  241.     modesText = XtNameToWidget(toplevel,"*modesText");
  242.     dateText = XtNameToWidget(toplevel,"*dateText");
  243.     queryButton = XtNameToWidget(toplevel,"*queryButton");
  244.     abortButton = XtNameToWidget(toplevel,"*abortButton");
  245.     if (abortButton != NULL)
  246.     XtSetSensitive(abortButton,False);
  247.     /* make the lists behave like a browser should */
  248.     XtAddCallback(hostList,XtNcallback,selectItem,(XtPointer)1);
  249.     XtAddCallback(locationList,XtNcallback,selectItem,(XtPointer)2);
  250.     XtAddCallback(fileList,XtNcallback,selectItem,(XtPointer)3);
  251.     /* since Xaw is so bloody stupid... */
  252.     clearList(hostList);
  253.     clearList(locationList);
  254.     clearList(fileList);
  255.     /* Some people crash when the EzMenu's are created earlier (puke-ola) */
  256.     initWidgetsFromString(appResources.menus,".menus");
  257. }
  258.  
  259. #define ISSPACE(c)    ((c) == ' ' || (c) == '\t' || (c) == '\n')
  260. #define NUL        '\0'
  261.  
  262. /*
  263.  * initWidgetsFromString : Create the widgets specified in resourceStr as
  264.  *    "parent class name" triples. The resourceName is used for
  265.  *    error messages.
  266.  */
  267. void
  268. initWidgetsFromString(resourceStr,resourceName)
  269. char *resourceStr,*resourceName;
  270. {
  271.     char name[32],class[32],parent[256];
  272.     char *s,*t;
  273.     Boolean isShell;
  274.     WidgetClass wc;
  275.     Widget pw;
  276.  
  277.     if ((s=resourceStr) == NULL)
  278.     fail1("no widgets specified in %s resource!",resourceName);
  279.     while (*s) {
  280.     /* skip leading whitespace */
  281.         while (ISSPACE(*s))
  282.             s += 1;
  283.     if (!*s)
  284.         break;
  285.     /* Gather the parent widget name */
  286.         t = parent;
  287.         while (*s && !ISSPACE(*s))
  288.             *t++ = *s++;
  289.         *t = NUL;
  290.     /* skip whitespace */
  291.         while (ISSPACE(*s))
  292.             s += 1;
  293.     if (!*s)
  294.         fail1("missing widget class and name in %s resource",resourceName);
  295.     /* Gather the class name */
  296.         t = class;
  297.         while (*s && !ISSPACE(*s))
  298.             *t++ = *s++;
  299.         *t = NUL;
  300.     /* skip whitespace */
  301.         while (ISSPACE(*s))
  302.             s += 1;
  303.     if (!*s)
  304.         fail1("missing widget name in %s resource",resourceName);
  305.     /* Gather the widget's name */
  306.         t = name;
  307.         while (*s && !ISSPACE(*s))
  308.             *t++ = *s++;
  309.         *t = NUL;
  310.     /* convert class name to WidgetClass */
  311.         if ((wc=classNameToWidgetClass(class,&isShell)) == NULL)
  312.         fail1("can't convert string \"%s\" to widgetClass",class);
  313.     /* convert parent name to Widget */
  314.     if (strcmp(parent,"toplevel") == 0)
  315.         pw = toplevel;
  316.     else if ((pw=XtNameToWidget(toplevel,parent)) == NULL)
  317.         fail1("can't convert string \"%s\" to widget",parent);
  318.     /* finally create the widget */
  319.     if (isShell)
  320.             (void)XtCreatePopupShell(name,wc,pw,NULL,ZERO);
  321.         else
  322.             (void)XtCreateManagedWidget(name,wc,pw,NULL,ZERO);
  323.     }
  324. }
  325.  
  326. /*    -    -    -    -    -    -    -    -    */
  327. /* The following functions attempt to provide information in the event of
  328.  * a crash. If you have trouble compiling them because of UNIX-isms in
  329.  * the signal handlers, then add -DDONT_CATCH_ERRORS to the definition
  330.  * of DEFINES in the Imakefile and re-make (or just #define it here).
  331.  */
  332. #ifndef DONT_CATCH_ERRORS
  333. static void crashHandler();
  334. #endif /* DONT_CATCH_ERRORS */
  335.  
  336. static void
  337. initErrorHandlers()
  338. {
  339. #ifndef DONT_CATCH_ERRORS
  340.     signal(SIGBUS,crashHandler);
  341.     signal(SIGSEGV,crashHandler);
  342. #endif /* DONT_CATCH_ERRORS */
  343. }
  344.  
  345. #ifndef DONT_CATCH_ERRORS
  346. static void
  347. crashHandler(sig)
  348. int sig;
  349. {
  350.     char *s;
  351.  
  352.     switch (sig) {
  353.     case SIGBUS: s = "SIGBUS"; break;
  354.     case SIGSEGV: s = "SIGSEGV"; break;
  355.     default: s = "UNKNOWN";
  356.     }
  357.     fprintf(stderr,"%s: caught a %s signal!\n",progname,s);
  358.     fprintf(stderr,"If a backtrace (using dbx or gdb or something) shows that the crash is\n");
  359.     fprintf(stderr,"is occurring in XtNameToWidget() or something similar, then before\n");
  360.     fprintf(stderr,"reporting an error, please check that your X distribution is up to date.\n");
  361.     fprintf(stderr,"Xarchie may not run under versions of X that are not at least X11R4\n");
  362.     fprintf(stderr,"with all fixes applied. Your copy of \".../include/X11/Intrinsic.h\"\n");
  363.     fprintf(stderr,"should have XConsortium revision number at least 1.139.\n");
  364.     fprintf(stderr,"If you still want to report an error, please indicate your hardware type,\n");
  365.     fprintf(stderr,"operating system, compiler, and your version of X and include a\n");
  366.     fprintf(stderr,"backtrace. Thanks.\n");
  367.     abort();
  368. }
  369.  
  370. #endif /* DONT_CATCH_ERRORS */
  371.  
  372. /*    -    -    -    -    -    -    -    -    */
  373.  
  374. /* Callback procedures */
  375.  
  376. /*ARGSUSED*/
  377. static void
  378. selectItem(w,closure,call_data)
  379. Widget w;
  380. XtPointer closure,call_data;
  381. {
  382.     XawListReturnStruct *item = (XawListReturnStruct*)call_data;
  383.  
  384.     switch ((int)closure) {
  385.     case 1 :
  386.         if (selectedHostEntry &&
  387.         findHostIndexFromEntry(selectedHostEntry) == item->list_index) {
  388.         XawListUnhighlight(hostList);
  389.         clearFileInfo();
  390.         clearList(fileList);
  391.         clearLocationInfo();
  392.         clearList(locationList);
  393.         clearHostInfo();
  394.         selectedHostEntry = HOST_NULL;
  395.         } else {
  396.         selectedHostEntry = findHostEntryFromIndex(item->list_index,
  397.                                db);
  398.         displayHostInfo(selectedHostEntry);
  399.         displayLocs(selectedHostEntry);
  400.         }
  401.         break;
  402.     case 2 :
  403.         if (selectedLocEntry &&
  404.         findLocIndexFromEntry(selectedLocEntry) == item->list_index) {
  405.         XawListUnhighlight(locationList);
  406.         clearFileInfo();
  407.         clearList(fileList);
  408.         clearLocationInfo();
  409.         selectedLocEntry = LOC_NULL;
  410.         } else {
  411.         selectedLocEntry = findLocEntryFromIndex(item->list_index,
  412.                              selectedHostEntry);
  413.         displayLocationInfo(selectedLocEntry);
  414.         displayFiles(selectedLocEntry);
  415.         }
  416.         break;
  417.     case 3 :
  418.         if (selectedFileEntry &&
  419.         findFileIndexFromEntry(selectedFileEntry) == item->list_index) {
  420.         XawListUnhighlight(fileList);
  421.         clearFileInfo();
  422.         selectedFileEntry = FILE_NULL;
  423.         } else {
  424.         selectedFileEntry = findFileEntryFromIndex(item->list_index,
  425.                                selectedLocEntry);
  426.         displayFileInfo(selectedFileEntry);
  427.         }
  428.         break;
  429.     }
  430. }
  431.  
  432. /*    -    -    -    -    -    -    -    -    */
  433.  
  434. void
  435. displayHostInfo(hostp)
  436. HostEntry *hostp;
  437. {
  438.     if (hostText != NULL)
  439.     setText(hostText,hostp->hostname);
  440. }
  441.  
  442. void
  443. clearHostInfo()
  444. {
  445.     if (hostText != NULL)
  446.     setText(hostText,"");
  447. }
  448.  
  449. void
  450. displayLocationInfo(locp)
  451. LocEntry *locp;
  452. {
  453.     if (locationText != NULL)
  454.     setText(locationText,locp->linkpath);
  455. }
  456.  
  457. void
  458. clearLocationInfo()
  459. {
  460.     if (locationText != NULL)
  461.     setText(locationText,"");
  462. }
  463.  
  464. void
  465. displayFileInfo(filep)
  466. FileEntry *filep;
  467. {
  468.     char buf[16];
  469.  
  470.     if (fileText != NULL)
  471.     setText(fileText,filep->name);
  472.     if (sizeText != NULL) {
  473.     sprintf(buf,"%d",filep->size);
  474.     setText(sizeText,buf);
  475.     }
  476.     if (modesText != NULL)
  477.     setText(modesText,filep->modes);
  478.     if (dateText != NULL)
  479.     setText(dateText,filep->date);
  480. }
  481.  
  482. void
  483. clearFileInfo()
  484. {
  485.     if (fileText != NULL)
  486.     setText(fileText,"");
  487.     if (sizeText != NULL)
  488.     setText(sizeText,"");
  489.     if (modesText != NULL)
  490.     setText(modesText,"");
  491.     if (dateText != NULL)
  492.     setText(dateText,"");
  493. }
  494.  
  495. /*    -    -    -    -    -    -    -    -    */
  496. /*
  497.  * setText() : Set the given Text item's value to the given string.
  498.  */
  499. void
  500. setText(item,text)
  501. Widget item;
  502. char *text;
  503. {
  504.     Arg args[1];
  505.  
  506.     if (item != NULL) {
  507.     XtSetArg(args[0],XtNstring,text);
  508.     XtSetValues(item,args,ONE);
  509.     }
  510. }
  511.  
  512. /*
  513.  * setLabel() : Set the given Label item's value to the given string.
  514.  */
  515. void
  516. setLabel(item,text)
  517. Widget item;
  518. char *text;
  519. {
  520.     Arg args[1];
  521.  
  522.     if (item != NULL) {
  523.     XtSetArg(args[0],XtNlabel,text);
  524.     XtSetValues(item,args,ONE);
  525.     }
  526. }
  527.  
  528. /*    -    -    -    -    -    -    -    -    */
  529.  
  530. void
  531. status0(str)
  532. char *str;
  533. {
  534.     if (statusText != NULL)
  535.     setText(statusText,str);
  536. }
  537.  
  538. void
  539. status1(fmt,arg)
  540. char *fmt,*arg;
  541. {
  542.     char buf[256];
  543.  
  544.     sprintf(buf,fmt,arg);
  545.     status0(buf);
  546. }
  547.  
  548. void
  549. status2(fmt,arg1,arg2)
  550. char *fmt,*arg1,*arg2;
  551. {
  552.     char buf[256];
  553.  
  554.     sprintf(buf,fmt,arg1,arg2);
  555.     status0(buf);
  556. }
  557.  
  558. /*    -    -    -    -    -    -    -    -    */
  559.  
  560. void
  561. fail0(str)
  562. char *str;
  563. {
  564.     fprintf(stderr,"%s: %s\n",progname,str);
  565.     XtDestroyApplicationContext(appContext);
  566.     exit(1);
  567. }
  568.  
  569. void
  570. fail1(fmt,arg)
  571. char *fmt,*arg;
  572. {
  573.     char buf[256];
  574.  
  575.     sprintf(buf,fmt,arg);
  576.     fail0(buf);
  577. }
  578.  
  579. /*    -    -    -    -    -    -    -    -    */
  580. /*
  581.  * syntax() : Print whatever caused the error and the usage message.
  582.  */
  583. static void
  584. syntax(argc,argv)
  585. int argc;
  586. char **argv;
  587. {
  588.     char *program;
  589.  
  590.     program = *argv;
  591.     argv += 1;
  592.     if (argc > 2 || (strcmp(*argv,"-help") != 0 && strcmp(*argv,"-?") != 0)) {
  593.     fprintf(stderr,"%s: bad argument(s): ",program);
  594.     while (--argc)
  595.         fprintf(stderr,"%s ",*argv++);
  596.     fprintf(stderr,"\n");
  597.     }
  598.     fprintf(stderr,"Valid options (in addition to X Toolkit options) are:\n");
  599.     fprintf(stderr,"  -search type\tset query type\n");
  600.     fprintf(stderr,"  -e\t\tset query type to exact\n");
  601.     fprintf(stderr,"  -c\t\tset query type to subcase\n");
  602.     fprintf(stderr,"  -s\t\tset query type to substr\n");
  603.     fprintf(stderr,"  -r\t\tset query type to regexp\n");
  604.     fprintf(stderr,"  -ec\t\tset query type to exactSubcase\n");
  605.     fprintf(stderr,"  -es\t\tset query type to exactSubstr\n");
  606.     fprintf(stderr,"  -er\t\tset query type to exactRegexp\n");
  607.     fprintf(stderr,"  -sort type\tset sort mode\n");
  608.     fprintf(stderr,"  -t\t\tset sort mode to invdate\n");
  609.     fprintf(stderr,"  -host host\tconnect to Archie at host\n");
  610.     fprintf(stderr,"  -maxHits num\tset maximum number of matches per query\n");
  611.     fprintf(stderr,"  -offset off\tset Prospero offset\n");
  612.     fprintf(stderr,"  -[nice|N] level\tset query niceness\n");
  613.     fprintf(stderr,"  -[debug|D] level\tset Prospero debugging level\n");
  614.     fprintf(stderr,"  -help\t\tprint this message\n");
  615.     fprintf(stderr,"  -xrm 'resource: value'  pass arbitrary resources\n");
  616.     fprintf(stderr,"Options can be abbreviated to their shortest unique prefix.\n");
  617. }
  618.