home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lynx2.8.1dev.10.tar.gz / lynx2.8.1dev.10.tar / lynx2-8 / src / HTInit.c < prev    next >
C/C++ Source or Header  |  1998-05-02  |  30KB  |  995 lines

  1. /*        Configuration-specific Initialialization    HTInit.c
  2. **        ----------------------------------------
  3. */
  4.  
  5. /*    Define a basic set of suffixes and presentations
  6. **    ------------------------------------------------
  7. */
  8.  
  9. #include <HTUtils.h>
  10. #include <tcp.h>
  11.  
  12. /* Implements:
  13. */
  14. #include <HTInit.h>
  15.  
  16. #include <HTML.h>
  17. #include <HTPlain.h>
  18. #include <HTMLGen.h>
  19. #include <HTFile.h>
  20. #include <HTFormat.h>
  21. #include <HTMIME.h>
  22. #include <HTWSRC.h>
  23.  
  24. #include <HTSaveToFile.h>  /* LJM */
  25. #include <userdefs.h>
  26. #include <LYStrings.h>
  27. #include <LYUtils.h>
  28. #include <LYGlobalDefs.h>
  29. #include <LYSignal.h>
  30. #include <LYSystem.h>
  31.  
  32. #include <LYexit.h>
  33. #include <LYLeaks.h>
  34.  
  35. #define FREE(x) if (x) {free(x); x = NULL;}
  36.  
  37. #ifdef VMS
  38. #define DISPLAY "DECW$DISPLAY"
  39. #else
  40. #define DISPLAY "DISPLAY"
  41. #endif /* VMS */
  42.  
  43. PRIVATE int HTLoadTypesConfigFile PARAMS((char *fn));
  44. PRIVATE int HTLoadExtensionsConfigFile PARAMS((char *fn));
  45.  
  46. PUBLIC void HTFormatInit NOARGS
  47. {
  48.  FILE *fp = NULL;
  49.  char *cp = NULL;
  50.  
  51. #ifdef NeXT
  52.   HTSetPresentation("application/postscript",   "open %s", 1.0, 2.0, 0.0, 0);
  53.   HTSetPresentation("image/x-tiff",             "open %s", 2.0, 2.0, 0.0, 0);
  54.   HTSetPresentation("image/tiff",               "open %s", 1.0, 2.0, 0.0, 0);
  55.   HTSetPresentation("audio/basic",              "open %s", 1.0, 2.0, 0.0, 0);
  56.   HTSetPresentation("*",                        "open %s", 1.0, 0.0, 0.0, 0);
  57. #else
  58.  if ((cp = getenv(DISPLAY)) != NULL && *cp != '\0') {    /* Must have X11 */
  59.   HTSetPresentation("application/postscript", "ghostview %s&",
  60.                                   1.0, 3.0, 0.0, 0);
  61.   HTSetPresentation("image/gif",        XLoadImageCommand,  1.0, 3.0, 0.0, 0);
  62.   HTSetPresentation("image/x-xbm",      XLoadImageCommand,  1.0, 3.0, 0.0, 0);
  63.   HTSetPresentation("image/x-xbitmap",  XLoadImageCommand,  1.0, 3.0, 0.0, 0);
  64.   HTSetPresentation("image/x-png",      XLoadImageCommand,  2.0, 3.0, 0.0, 0);
  65.   HTSetPresentation("image/png",    XLoadImageCommand,  1.0, 3.0, 0.0, 0);
  66.   HTSetPresentation("image/x-rgb",      XLoadImageCommand,  1.0, 3.0, 0.0, 0);
  67.   HTSetPresentation("image/x-tiff",     XLoadImageCommand,  2.0, 3.0, 0.0, 0);
  68.   HTSetPresentation("image/tiff",    XLoadImageCommand,  1.0, 3.0, 0.0, 0);
  69.   HTSetPresentation("image/jpeg",       XLoadImageCommand,  1.0, 3.0, 0.0, 0);
  70.   HTSetPresentation("video/mpeg",       "mpeg_play %s &",   1.0, 3.0, 0.0, 0);
  71.  
  72.  }
  73. #endif
  74.  
  75. #ifdef EXEC_SCRIPTS
  76.  /* set quality to 999.0 for protected exec applications */
  77. #ifndef VMS
  78.  HTSetPresentation("application/x-csh",    "csh %s", 999.0, 3.0, 0.0, 0);
  79.  HTSetPresentation("application/x-sh",    "sh %s",  999.0, 3.0, 0.0, 0);
  80.  HTSetPresentation("application/x-ksh",    "ksh %s", 999.0, 3.0, 0.0, 0);
  81. #else
  82.  HTSetPresentation("application/x-VMS_script",    "@%s", 999.0, 3.0, 0.0, 0);
  83. #endif /* not VMS */
  84. #endif /* EXEC_SCRIPTS */
  85.  
  86. /*
  87.  *  Add our header handlers.
  88.  */
  89.  HTSetConversion("www/mime",  "www/present",  HTMIMEConvert, 1.0, 0.0, 0.0, 0);
  90.  HTSetConversion("www/mime",  "www/download", HTMIMEConvert, 1.0, 0.0, 0.0, 0);
  91.  HTSetConversion("www/mime",  "www/source",   HTMIMEConvert, 1.0, 0.0, 0.0, 0);
  92.  HTSetConversion("www/mime",  "www/dump",     HTMIMEConvert, 1.0, 0.0, 0.0, 0);
  93.  
  94. /*
  95.  *  Add our compressed file handlers.
  96.  */
  97.  HTSetConversion("www/compressed", "www/present",
  98.                            HTCompressed,   1.0, 0.0, 0.0, 0);
  99.  HTSetConversion("www/compressed", "www/download",
  100.                            HTCompressed,   1.0, 0.0, 0.0, 0);
  101.  HTSetConversion("www/compressed", "www/present",
  102.                            HTCompressed,   1.0, 0.0, 0.0, 0);
  103.  HTSetConversion("www/compressed", "www/source",
  104.                            HTCompressed,   1.0, 0.0, 0.0, 0);
  105.  HTSetConversion("www/compressed", "www/dump",
  106.                            HTCompressed,   1.0, 0.0, 0.0, 0);
  107.  
  108.  /*
  109.   * Added the following to support some content types beginning to surface.
  110.   */
  111.  HTSetConversion("application/html", "text/x-c",
  112.                      HTMLToC,    0.5, 0.0, 0.0, 0);
  113.  HTSetConversion("application/html", "text/plain",
  114.                      HTMLToPlain,    0.5, 0.0, 0.0, 0);
  115.  HTSetConversion("application/html", "www/present",
  116.                      HTMLPresent,    2.0, 0.0, 0.0, 0);
  117.  HTSetConversion("application/html", "www/source",
  118.                      HTPlainPresent,    1.0, 0.0, 0.0, 0);
  119.  HTSetConversion("application/x-wais-source", "www/source",
  120.                     HTPlainPresent,    1.0, 0.0, 0.0, 0);
  121.  HTSetConversion("application/x-wais-source", "www/present",
  122.                         HTWSRCConvert,    2.0, 0.0, 0.0, 0);
  123.  HTSetConversion("application/x-wais-source", "www/download",
  124.                     HTWSRCConvert,    1.0, 0.0, 0.0, 0);
  125.  HTSetConversion("application/x-wais-source", "www/dump",
  126.                     HTWSRCConvert,    1.0, 0.0, 0.0, 0);
  127.  
  128.  /*
  129.   *  Save all unknown mime types to disk.
  130.   */
  131.  HTSetConversion("www/source",  "www/present",
  132.                      HTSaveToFile,    1.0, 3.0, 0.0, 0);
  133.  HTSetConversion("www/source",  "www/source",
  134.                      HTSaveToFile,    1.0, 3.0, 0.0, 0);
  135.  HTSetConversion("www/source",  "www/download",
  136.                      HTSaveToFile,    1.0, 3.0, 0.0, 0);
  137.  HTSetConversion("www/source",  "*",    HTSaveToFile,    1.0, 3.0, 0.0, 0);
  138.  
  139.  /*
  140.   *  Output all www/dump presentations to stdout.
  141.   */
  142.  HTSetConversion("www/source",  "www/dump",
  143.                      HTDumpToStdout,    1.0, 3.0, 0.0, 0);
  144.  
  145. /*
  146.  *  Now add our basic conversions.
  147.  */
  148.  HTSetConversion("text/x-sgml",
  149.                    "www/source",  HTPlainPresent, 1.0, 0.0, 0.0, 0);
  150.  HTSetConversion("text/x-sgml",
  151.                    "www/present", HTMLPresent,    2.0, 0.0, 0.0, 0);
  152.  HTSetConversion("text/sgml", "www/source",  HTPlainPresent, 1.0, 0.0, 0.0, 0);
  153.  HTSetConversion("text/sgml", "www/present", HTMLPresent,    1.0, 0.0, 0.0, 0);
  154.  HTSetConversion("text/plain","www/present", HTPlainPresent, 1.0, 0.0, 0.0, 0);
  155.  HTSetConversion("text/plain","www/source",  HTPlainPresent, 1.0, 0.0, 0.0, 0);
  156.  HTSetConversion("text/html", "www/source",  HTPlainPresent, 1.0, 0.0, 0.0, 0);
  157.  HTSetConversion("text/html", "text/x-c",    HTMLToC,          0.5, 0.0, 0.0, 0);
  158.  HTSetConversion("text/html", "text/plain",  HTMLToPlain,    0.5, 0.0, 0.0, 0);
  159.  HTSetConversion("text/html", "www/present", HTMLPresent,    1.0, 0.0, 0.0, 0);
  160.  
  161.  /*
  162.   *  These should override the default types as necessary.
  163.   */
  164.  HTLoadTypesConfigFile(global_type_map);
  165.  
  166.  /*
  167.   *  Load the local maps.
  168.   */
  169.  if ((fp = fopen(personal_type_map,"r")) != NULL) {
  170.      fclose(fp);
  171.      /* These should override everything else. */
  172.      HTLoadTypesConfigFile(personal_type_map);
  173.  } else {
  174.      char buffer[256];
  175. #ifdef VMS
  176.      sprintf(buffer, "sys$login:%s", personal_type_map);
  177. #else
  178.      sprintf(buffer, "%s/%s", (Home_Dir() ? Home_Dir() : ""),
  179.                   personal_type_map);
  180. #endif
  181.      HTLoadTypesConfigFile(buffer);
  182.  }
  183.  
  184.  /*
  185.   *  Put text/html and text/plain at beginning of list. - kw
  186.   */
  187.  HTReorderPresentation(WWW_PLAINTEXT, WWW_PRESENT);
  188.  HTReorderPresentation(WWW_HTML, WWW_PRESENT);
  189. }
  190.  
  191. PUBLIC void HTPreparsedFormatInit NOARGS
  192. {
  193.  if (LYPreparsedSource) {
  194.      HTSetConversion("text/html", "www/source", HTMLParsedPresent, 1.0, 0.0, 0.0, 0);
  195.      HTSetConversion("text/html", "www/dump",    HTMLParsedPresent, 1.0, 0.0, 0.0, 0);
  196.  }
  197. }
  198.  
  199. /* Some of the following is taken from: */
  200.  
  201. /*
  202. Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)
  203.  
  204. Permission to use, copy, modify, and distribute this material
  205. for any purpose and without fee is hereby granted, provided
  206. that the above copyright notice and this permission notice
  207. appear in all copies, and that the name of Bellcore not be
  208. used in advertising or publicity pertaining to this
  209. material without the specific, prior written permission
  210. of an authorized representative of Bellcore.  BELLCORE
  211. MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY
  212. OF THIS MATERIAL FOR ANY PURPOSE.  IT IS PROVIDED "AS IS",
  213. WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
  214. */
  215. /******************************************************
  216.     Metamail -- A tool to help diverse mail readers
  217.                 cope with diverse multimedia mail formats.
  218.  
  219.     Author:  Nathaniel S. Borenstein, Bellcore
  220.  
  221.  ******************************************************* */
  222.  
  223. struct MailcapEntry {
  224.     char *contenttype;
  225.     char *command;
  226.     char *testcommand;
  227.     int needsterminal;
  228.     int copiousoutput;
  229.     int needtofree;
  230.     char *label;
  231.     char *printcommand;
  232.     float quality;
  233.     long int maxbytes;
  234. };
  235.  
  236.  
  237. PRIVATE int ExitWithError PARAMS((char *txt));
  238. PRIVATE int PassesTest PARAMS((struct MailcapEntry *mc));
  239.  
  240. #define LINE_BUF_SIZE        2048
  241. #define TMPFILE_NAME_SIZE    256
  242.  
  243. PRIVATE char *GetCommand ARGS2(
  244.     char *,        s,
  245.     char **,    t)
  246. {
  247.     char *s2;
  248.     int quoted = 0;
  249.  
  250.     /* marca -- added + 1 for error case -- oct 24, 1993. */
  251.     s2 = malloc(strlen(s)*2 + 1); /* absolute max, if all % signs */
  252.     if (!s2)
  253.     ExitWithError("Out of memory");
  254.  
  255.     *t = s2;
  256.     while (s && *s) {
  257.     if (quoted) {
  258.         if (*s == '%') *s2++ = '%'; /* Quote through next level, ugh! */
  259.  
  260.         *s2++ = *s++;
  261.         quoted = 0;
  262.     } else {
  263.         if (*s == ';') {
  264.         *s2 = '\0';
  265.         return(++s);
  266.         }
  267.         if (*s == '\\') {
  268.         quoted = 1;
  269.         ++s;
  270.         } else {
  271.         *s2++ = *s++;
  272.         }
  273.     }
  274.     }
  275.     *s2 = '\0';
  276.     return(NULL);
  277. }
  278.  
  279. /* no leading or trailing space, all lower case */
  280. PRIVATE char *Cleanse ARGS1(
  281.     char *,        s)
  282. {
  283.     LYTrimLeading(s);
  284.     LYTrimTrailing(s);
  285.     LYLowerCase(s);
  286.     return(s);
  287. }
  288.  
  289. PRIVATE int ProcessMailcapEntry ARGS2(
  290.     FILE *,            fp,
  291.     struct MailcapEntry *,    mc)
  292. {
  293.     size_t rawentryalloc = 2000, len;
  294.     char *rawentry, *s, *t, *LineBuf;
  295.  
  296.     LineBuf = (char *)malloc(LINE_BUF_SIZE);
  297.     if (!LineBuf)
  298.     ExitWithError("Out of memory");
  299.     rawentry = (char *)malloc(1 + rawentryalloc);
  300.     if (!rawentry)
  301.     ExitWithError("Out of memory");
  302.     *rawentry = '\0';
  303.     while (fgets(LineBuf, LINE_BUF_SIZE, fp)) {
  304.     if (LineBuf[0] == '#')
  305.         continue;
  306.     len = strlen(LineBuf);
  307.     if (len == 0)
  308.         continue;
  309.     if (LineBuf[len-1] == '\n')
  310.         LineBuf[--len] = '\0';
  311.     if ((len + strlen(rawentry)) > rawentryalloc) {
  312.         rawentryalloc += 2000;
  313.         rawentry = realloc(rawentry, rawentryalloc+1);
  314.         if (!rawentry)
  315.             ExitWithError("Out of memory");
  316.     }
  317.     if (len > 0 && LineBuf[len-1] == '\\') {
  318.         LineBuf[len-1] = '\0';
  319.         strcat(rawentry, LineBuf);
  320.     } else {
  321.         strcat(rawentry, LineBuf);
  322.         break;
  323.     }
  324.     }
  325.  
  326.     FREE(LineBuf);
  327.  
  328.     s = LYSkipBlanks(rawentry);
  329.     if (!*s) {
  330.     /* totally blank entry -- quietly ignore */
  331.     FREE(rawentry);
  332.     return(0);
  333.     }
  334.     s = strchr(rawentry, ';');
  335.     if (s == NULL) {
  336.     CTRACE(tfp, "ProcessMailcapEntry: Ignoring invalid mailcap entry: %s\n",
  337.             rawentry);
  338.     FREE(rawentry);
  339.     return(0);
  340.     }
  341.     *s++ = '\0';
  342.     if (!strncasecomp(rawentry, "text/html", 9) ||
  343.     !strncasecomp(rawentry, "text/plain", 10)) {
  344.     --s;
  345.     *s = ';';
  346.     CTRACE(tfp, "ProcessMailcapEntry: Ignoring mailcap entry: %s\n",
  347.             rawentry);
  348.     FREE(rawentry);
  349.     return(0);
  350.     }
  351.     LYRemoveBlanks(rawentry);
  352.     LYLowerCase(rawentry);
  353.  
  354.     mc->needsterminal = 0;
  355.     mc->copiousoutput = 0;
  356.     mc->needtofree = 1;
  357.     mc->testcommand = NULL;
  358.     mc->label = NULL;
  359.     mc->printcommand = NULL;
  360.     mc->contenttype = (char *)malloc(1 + strlen(rawentry));
  361.     if (!mc->contenttype)
  362.     ExitWithError("Out of memory");
  363.     strcpy(mc->contenttype, rawentry);
  364.     mc->quality = 1.0;
  365.     mc->maxbytes = 0;
  366.     t = GetCommand(s, &mc->command);
  367.     if (!t) {
  368.     goto assign_presentation;
  369.     }
  370.     s = LYSkipBlanks(t);
  371.     while (s) {
  372.     char *arg, *eq, *mallocd_string;
  373.  
  374.     t = GetCommand(s, &mallocd_string);
  375.     arg = mallocd_string;
  376.     eq = strchr(arg, '=');
  377.     if (eq) {
  378.         *eq++ = '\0';
  379.     }
  380.     if (arg && *arg) {
  381.         arg = Cleanse(arg);
  382.         if (!strcmp(arg, "needsterminal")) {
  383.         mc->needsterminal = 1;
  384.         } else if (!strcmp(arg, "copiousoutput")) {
  385.         mc->copiousoutput = 1;
  386.         } else if (eq && !strcmp(arg, "test")) {
  387.         mc->testcommand = NULL;
  388.         StrAllocCopy(mc->testcommand, eq);
  389.         CTRACE(tfp, "ProcessMailcapEntry: Found testcommand:%s\n",
  390.                 mc->testcommand);
  391.         } else if (eq && !strcmp(arg, "description")) {
  392.         mc->label = eq;
  393.         } else if (eq && !strcmp(arg, "label")) {
  394.         mc->label = eq; /* bogus old name for description */
  395.         } else if (eq && !strcmp(arg, "print")) {
  396.         mc->printcommand = eq;
  397.         } else if (eq && !strcmp(arg, "textualnewlines")) {
  398.         /* no support for now.  What does this do anyways? */
  399.         /* ExceptionalNewline(mc->contenttype, atoi(eq)); */
  400.         } else if (eq && !strcmp(arg, "q")) {
  401.             mc->quality = atof(eq);
  402.         if (mc->quality > 0.000 && mc->quality < 0.001)
  403.             mc->quality = 0.001;
  404.         } else if (eq && !strcmp(arg, "mxb")) {
  405.             mc->maxbytes = atol(eq);
  406.         if (mc->maxbytes < 0)
  407.             mc->maxbytes = 0;
  408.         } else if (strcmp(arg, "notes")) { /* IGNORE notes field */
  409.         if (*arg)
  410.             CTRACE(tfp, "ProcessMailcapEntry: Ignoring mailcap flag '%s'.\n",
  411.                     arg);
  412.         }
  413.  
  414.     }
  415.       FREE(mallocd_string);
  416.       s = t;
  417.     }
  418.  
  419. assign_presentation:
  420.     FREE(rawentry);
  421.  
  422.     if (PassesTest(mc)) {
  423.     CTRACE(tfp, "ProcessMailcapEntry Setting up conversion %s : %s\n",
  424.             mc->contenttype, mc->command);
  425.     HTSetPresentation(mc->contenttype, mc->command,
  426.               mc->quality, 3.0, 0.0, mc->maxbytes);
  427.     }
  428.     FREE(mc->command);
  429.     FREE(mc->contenttype);
  430.  
  431.     return(1);
  432. }
  433.  
  434. PRIVATE void BuildCommand ARGS5(
  435.     char **,     pBuf,
  436.     size_t,        Bufsize,
  437.     char *,        controlstring,
  438.     char *,        TmpFileName,
  439.     size_t,        TmpFileLen)
  440. {
  441.     char *from, *to;
  442.     int prefixed = 0;
  443.  
  444.     for (from = controlstring, to = *pBuf; *from != '\0'; from++) {
  445.     if (prefixed) {
  446.         prefixed = 0;
  447.         switch(*from) {
  448.         case '%':
  449.             *to++ = '%';
  450.             break;
  451.         case 'n':
  452.         case 'F':
  453.             CTRACE(tfp, "BuildCommand: Bad mailcap \"test\" clause: %s\n",
  454.                 controlstring);
  455.         case 's':
  456.             if (TmpFileLen && TmpFileName) {
  457.             if ((to - *pBuf) + TmpFileLen + 1 > Bufsize) {
  458.                 *to = '\0';
  459.                 CTRACE(tfp, "BuildCommand: Too long mailcap \"test\" clause,\n");
  460.                 CTRACE(tfp, "              ignoring: %s%s...\n",
  461.                     *pBuf, TmpFileName);
  462.                 **pBuf = '\0';
  463.                 return;
  464.             }
  465.             strcpy(to, TmpFileName);
  466.             to += strlen(TmpFileName);
  467.             }
  468.             break;
  469.         default:
  470.             CTRACE(tfp,
  471.   "BuildCommand: Ignoring unrecognized format code in mailcap file '%%%c'.\n",
  472.             *from);
  473.             break;
  474.         }
  475.     } else if (*from == '%') {
  476.         prefixed = 1;
  477.     } else {
  478.         *to++ = *from;
  479.     }
  480.     if (to >= *pBuf + Bufsize) {
  481.         (*pBuf)[Bufsize - 1] = '\0';
  482.         CTRACE(tfp, "BuildCommand: Too long mailcap \"test\" clause,\n");
  483.         CTRACE(tfp, "              ignoring: %s...\n",
  484.             *pBuf);
  485.         **pBuf = '\0';
  486.         return;
  487.     }
  488.     }
  489.     *to = '\0';
  490. }
  491.  
  492. PRIVATE int PassesTest ARGS1(
  493.     struct MailcapEntry *,    mc)
  494. {
  495.     int result;
  496.     char *cmd, TmpFileName[TMPFILE_NAME_SIZE];
  497.     char *cp = NULL;
  498.  
  499.     /*
  500.      *  Make sure we have a command
  501.      */
  502.     if (!mc->testcommand)
  503.     return(1);
  504.  
  505.     /*
  506.      *  Save overhead of system() calls by faking these. - FM
  507.      */
  508.     if (0 == strcasecomp(mc->testcommand, "test -n \"$DISPLAY\"")) {
  509.     FREE(mc->testcommand);
  510.     CTRACE(tfp, "PassesTest: Testing for XWINDOWS environment.\n");
  511.         if ((cp = getenv(DISPLAY)) != NULL && *cp != '\0') {
  512.         CTRACE(tfp, "PassesTest: Test passed!\n");
  513.         return(0 == 0);
  514.     } else {
  515.         CTRACE(tfp, "PassesTest: Test failed!\n");
  516.         return(-1 == 0);
  517.     }
  518.     }
  519.     if (0 == strcasecomp(mc->testcommand, "test -z \"$DISPLAY\"")) {
  520.     FREE(mc->testcommand);
  521.     CTRACE(tfp, "PassesTest: Testing for NON_XWINDOWS environment.\n");
  522.         if (!((cp = getenv(DISPLAY)) != NULL && *cp != '\0')) {
  523.         CTRACE(tfp,"PassesTest: Test passed!\n");
  524.         return(0 == 0);
  525.     } else {
  526.         CTRACE(tfp,"PassesTest: Test failed!\n");
  527.         return(-1 == 0);
  528.     }
  529.     }
  530.  
  531.     /*
  532.      *  Why do anything but return success for this one! - FM
  533.      */
  534.     if (0 == strcasecomp(mc->testcommand, "test -n \"$LYNX_VERSION\"")){
  535.     FREE(mc->testcommand);
  536.     CTRACE(tfp, "PassesTest: Testing for LYNX environment.\n");
  537.     CTRACE(tfp, "PassesTest: Test passed!\n");
  538.     return(0 == 0);
  539.     } else
  540.     /*
  541.      *  ... or failure for this one! - FM
  542.      */
  543.     if (0 == strcasecomp(mc->testcommand, "test -z \"$LYNX_VERSION\"")) {
  544.     FREE(mc->testcommand);
  545.     CTRACE(tfp, "PassesTest: Testing for non-LYNX environment.\n");
  546.     CTRACE(tfp, "PassesTest: Test failed!\n");
  547.     return(-1 == 0);
  548.     }
  549.  
  550.     /*
  551.      *  Build the command and execute it.
  552.      */
  553.     tempname(TmpFileName, NEW_FILE);
  554.     cmd = (char *)malloc(1024);
  555.     if (!cmd)
  556.     ExitWithError("Out of memory");
  557.     BuildCommand(&cmd, 1024,
  558.          mc->testcommand,
  559.          TmpFileName,
  560.          strlen(TmpFileName));
  561.     CTRACE(tfp, "PassesTest: Executing test command: %s\n", cmd);
  562.     result = system(cmd);
  563.     FREE(cmd);
  564.  
  565.     /*
  566.      *  Free the test command as well since
  567.      *  we wont be needing it anymore.
  568.      */
  569.     FREE(mc->testcommand);
  570.  
  571.     if (result) {
  572.     CTRACE(tfp,"PassesTest: Test failed!\n");
  573.     } else {
  574.     CTRACE(tfp,"PassesTest: Test passed!\n");
  575.     }
  576.  
  577.     return(result == 0);
  578. }
  579.  
  580. PRIVATE int ProcessMailcapFile ARGS1(
  581.     char *,        file)
  582. {
  583.     struct MailcapEntry mc;
  584.     FILE *fp;
  585.  
  586.     CTRACE(tfp, "ProcessMailcapFile: Loading file '%s'.\n",
  587.         file);
  588.     if ((fp = fopen(file, "r")) == NULL) {
  589.     CTRACE(tfp, "ProcessMailcapFile: Could not open '%s'.\n",
  590.             file);
  591.     return(-1 == 0);
  592.     }
  593.  
  594.     while (fp && !feof(fp)) {
  595.     ProcessMailcapEntry(fp, &mc);
  596.     }
  597.     fclose(fp);
  598.     return(0 == 0);
  599. }
  600.  
  601. PRIVATE int ExitWithError ARGS1(
  602.     char *,        txt)
  603. {
  604.     if (txt)
  605.     fprintf(tfp, "metamail: %s\n", txt);
  606. #ifndef NOSIGHUP
  607.     (void) signal(SIGHUP, SIG_DFL);
  608. #endif /* NOSIGHUP */
  609.     (void) signal(SIGTERM, SIG_DFL);
  610. #ifndef VMS
  611.     (void) signal(SIGINT, SIG_DFL);
  612. #endif /* !VMS */
  613. #ifdef SIGTSTP
  614.     if (no_suspend)
  615.     (void) signal(SIGTSTP,SIG_DFL);
  616. #endif /* SIGTSTP */
  617.     exit(-1);
  618.     return(-1);
  619. }
  620.  
  621.  
  622. PRIVATE int HTLoadTypesConfigFile ARGS1(
  623.     char *,        fn)
  624. {
  625.   return ProcessMailcapFile(fn);
  626. }
  627.  
  628.  
  629.  
  630.  
  631. /* ------------------------------------------------------------------------ */
  632. /* ------------------------------------------------------------------------ */
  633. /* ------------------------------------------------------------------------ */
  634.  
  635. /*    Define a basic set of suffixes
  636. **    ------------------------------
  637. **
  638. **    The LAST suffix for a type is that used for temporary files
  639. **    of that type.
  640. **    The quality is an apriori bias as to whether the file should be
  641. **    used.  Not that different suffixes can be used to represent files
  642. **    which are of the same format but are originals or regenerated,
  643. **    with different values.
  644. */
  645.  
  646. PUBLIC void HTFileInit NOARGS
  647. {
  648.     FILE *fp;
  649.  
  650.     CTRACE(tfp, "HTFileInit: Loading default (HTInit) extension maps.\n");
  651.  
  652.     /* default suffix interpretation */
  653.     HTSetSuffix("*",        "text/plain", "7bit", 1.0);
  654.     HTSetSuffix("*.*",        "text/plain", "7bit", 1.0);
  655.  
  656. #ifdef EXEC_SCRIPTS
  657.     /*
  658.      *  define these extentions for exec scripts.
  659.      */
  660. #ifndef VMS
  661.     /* for csh exec links */
  662.     HTSetSuffix(".csh",        "application/x-csh", "8bit", 0.8);
  663.     HTSetSuffix(".sh",        "application/x-sh", "8bit", 0.8);
  664.     HTSetSuffix(".ksh",        "application/x-ksh", "8bit", 0.8);
  665. #else
  666.     HTSetSuffix(".com",        "application/x-VMS_script", "8bit", 0.8);
  667. #endif /* !VMS */
  668. #endif /* EXEC_SCRIPTS */
  669.  
  670.  
  671.     HTSetSuffix(".saveme",    "application/x-Binary", "binary", 1.0);
  672.     HTSetSuffix(".dump",    "application/x-Binary", "binary", 1.0);
  673.     HTSetSuffix(".bin",        "application/x-Binary", "binary", 1.0);
  674.  
  675.     HTSetSuffix(".arc",        "application/x-Compressed", "binary", 1.0);
  676.  
  677.     HTSetSuffix(".alpha-exe",    "application/x-Executable", "binary", 1.0);
  678.     HTSetSuffix(".alpha_exe",    "application/x-Executable", "binary", 1.0);
  679.     HTSetSuffix(".AXP-exe",    "application/x-Executable", "binary", 1.0);
  680.     HTSetSuffix(".AXP_exe",    "application/x-Executable", "binary", 1.0);
  681.     HTSetSuffix(".VAX-exe",    "application/x-Executable", "binary", 1.0);
  682.     HTSetSuffix(".VAX_exe",    "application/x-Executable", "binary", 1.0);
  683.     HTSetSuffix(".exe",        "application/x-Executable", "binary", 1.0);
  684.  
  685.     HTSetSuffix(".exe.Z",    "application/x-Comp. Executable",
  686.                                      "binary", 1.0);
  687.  
  688.     HTSetSuffix(".Z",            "application/UNIX Compressed", "binary", 1.0);
  689.  
  690.     HTSetSuffix(".tar_Z",    "application/UNIX Compr. Tar", "binary", 1.0);
  691.     HTSetSuffix(".tar.Z",    "application/UNIX Compr. Tar", "binary", 1.0);
  692.  
  693.     HTSetSuffix("-gz",        "application/GNU Compressed", "binary", 1.0);
  694.     HTSetSuffix("_gz",        "application/GNU Compressed", "binary", 1.0);
  695.     HTSetSuffix(".gz",        "application/GNU Compressed", "binary", 1.0);
  696.  
  697.     HTSetSuffix5(".tar.gz",    "application/x-tar", "binary", "GNU Compr. Tar", 1.0);
  698.     HTSetSuffix5(".tgz",    "application/x-tar", "gzip", "GNU Compr. Tar", 1.0);
  699.  
  700.     HTSetSuffix(".src",        "application/x-WAIS-source", "8bit", 1.0);
  701.     HTSetSuffix(".wsrc",    "application/x-WAIS-source", "8bit", 1.0);
  702.  
  703.     HTSetSuffix(".zip",        "application/x-Zip File", "binary", 1.0);
  704.  
  705.     HTSetSuffix(".uu",        "application/x-UUencoded", "8bit", 1.0);
  706.  
  707.     HTSetSuffix(".hqx",        "application/x-Binhex", "8bit", 1.0);
  708.  
  709.     HTSetSuffix(".o",        "application/x-Prog. Object", "binary", 1.0);
  710.     HTSetSuffix(".a",        "application/x-Prog. Library", "binary", 1.0);
  711.  
  712.     HTSetSuffix5(".oda",    "application/oda", "binary", "ODA", 1.0);
  713.  
  714.     HTSetSuffix5(".pdf",    "application/pdf", "binary", "PDF", 1.0);
  715.  
  716.     HTSetSuffix(".eps",        "application/Postscript", "8bit", 1.0);
  717.     HTSetSuffix(".ai",        "application/Postscript", "8bit", 1.0);
  718.     HTSetSuffix(".ps",        "application/Postscript", "8bit", 1.0);
  719.  
  720.     HTSetSuffix(".rtf",        "application/RTF", "8bit", 1.0);
  721.  
  722.     HTSetSuffix(".dvi",        "application/x-DVI", "8bit", 1.0);
  723.  
  724.     HTSetSuffix(".hdf",        "application/x-HDF", "8bit", 1.0);
  725.  
  726.     HTSetSuffix(".cdf",        "application/x-netcdf", "8bit", 1.0);
  727.     HTSetSuffix(".nc",        "application/x-netcdf", "8bit", 1.0);
  728.  
  729.     HTSetSuffix(".latex",    "application/x-Latex", "8bit", 1.0);
  730.     HTSetSuffix(".tex",      "application/x-Tex", "8bit", 1.0);
  731.     HTSetSuffix(".texinfo",    "application/x-Texinfo", "8bit", 1.0);
  732.     HTSetSuffix(".texi",    "application/x-Texinfo", "8bit", 1.0);
  733.  
  734.     HTSetSuffix(".t",        "application/x-Troff", "8bit", 1.0);
  735.     HTSetSuffix(".tr",        "application/x-Troff", "8bit", 1.0);
  736.     HTSetSuffix(".roff",    "application/x-Troff", "8bit", 1.0);
  737.  
  738.     HTSetSuffix(".man",        "application/x-Troff-man", "8bit", 1.0);
  739.     HTSetSuffix(".me",        "application/x-Troff-me", "8bit", 1.0);
  740.     HTSetSuffix(".ms",        "application/x-Troff-ms", "8bit", 1.0);
  741.  
  742.     HTSetSuffix(".zoo",        "application/x-Zoo File", "binary", 1.0);
  743.  
  744.     HTSetSuffix(".bak",        "application/x-VMS BAK File", "binary", 1.0);
  745.     HTSetSuffix(".bkp",        "application/x-VMS BAK File", "binary", 1.0);
  746.     HTSetSuffix(".bck",        "application/x-VMS BAK File", "binary", 1.0);
  747.  
  748.     HTSetSuffix(".bkp_gz",    "application/x-GNU BAK File", "binary", 1.0);
  749.     HTSetSuffix(".bkp-gz",    "application/x-GNU BAK File", "binary", 1.0);
  750.     HTSetSuffix(".bck_gz",    "application/x-GNU BAK File", "binary", 1.0);
  751.     HTSetSuffix(".bck-gz",    "application/x-GNU BAK File", "binary", 1.0);
  752.  
  753.     HTSetSuffix(".bkp-Z",    "application/x-Comp. BAK File", "binary", 1.0);
  754.     HTSetSuffix(".bkp_Z",    "application/x-Comp. BAK File", "binary", 1.0);
  755.     HTSetSuffix(".bck-Z",    "application/x-Comp. BAK File", "binary", 1.0);
  756.     HTSetSuffix(".bck_Z",    "application/x-Comp. BAK File", "binary", 1.0);
  757.  
  758.     HTSetSuffix(".hlb",        "application/x-VMS Help Libr.", "binary", 1.0);
  759.     HTSetSuffix(".olb",        "application/x-VMS Obj. Libr.", "binary", 1.0);
  760.     HTSetSuffix(".tlb",        "application/x-VMS Text Libr.", "binary", 1.0);
  761.     HTSetSuffix(".obj",        "application/x-VMS Prog. Obj.", "binary", 1.0);
  762.     HTSetSuffix(".decw$book",    "application/x-DEC BookReader", "binary", 1.0);
  763.     HTSetSuffix(".mem",        "application/x-RUNOFF-MANUAL", "8bit", 1.0);
  764.  
  765.     HTSetSuffix(".vsd",        "application/visio", "binary", 1.0);
  766.  
  767.     HTSetSuffix(".lha",        "application/x-lha File", "binary", 1.0);
  768.     HTSetSuffix(".lzh",        "application/x-lzh File", "binary", 1.0);
  769.  
  770.     HTSetSuffix(".sea",        "application/x-sea File", "binary", 1.0);
  771.     HTSetSuffix(".sit",        "application/x-sit File", "binary", 1.0);
  772.  
  773.     HTSetSuffix(".dms",        "application/x-dms File", "binary", 1.0);
  774.  
  775.     HTSetSuffix(".iff",        "application/x-iff File", "binary", 1.0);
  776.  
  777.     HTSetSuffix(".bcpio",    "application/x-bcpio", "binary", 1.0);
  778.     HTSetSuffix(".cpio",    "application/x-cpio", "binary", 1.0);
  779.  
  780.     HTSetSuffix(".gtar",    "application/x-gtar", "binary", 1.0);
  781.  
  782.     HTSetSuffix(".shar",    "application/x-shar", "8bit", 1.0);
  783.     HTSetSuffix(".share",    "application/x-share", "8bit", 1.0);
  784.  
  785.     HTSetSuffix(".sh",        "application/x-sh", "8bit", 1.0); /* xtra */
  786.  
  787.     HTSetSuffix(".sv4cpio",    "application/x-sv4cpio", "binary", 1.0);
  788.     HTSetSuffix(".sv4crc",    "application/x-sv4crc", "binary", 1.0);
  789.  
  790.     HTSetSuffix5(".tar",    "application/x-tar", "binary", "Tar File", 1.0);
  791.     HTSetSuffix(".ustar",    "application/x-ustar", "binary", 1.0);
  792.  
  793.     HTSetSuffix(".snd",        "audio/basic", "binary", 1.0);
  794.     HTSetSuffix(".au",        "audio/basic", "binary", 1.0);
  795.  
  796.     HTSetSuffix(".aifc",    "audio/x-aiff", "binary", 1.0);
  797.     HTSetSuffix(".aif",        "audio/x-aiff", "binary", 1.0);
  798.     HTSetSuffix(".aiff",    "audio/x-aiff", "binary", 1.0);
  799.     HTSetSuffix(".wav",        "audio/x-wav", "binary", 1.0);
  800.     HTSetSuffix(".midi",    "audio/midi", "binary", 1.0);
  801.     HTSetSuffix(".mod",        "audio/mod", "binary", 1.0);
  802.  
  803.     HTSetSuffix(".gif",        "image/gif", "binary", 1.0);
  804.     HTSetSuffix(".ief",        "image/ief", "binary", 1.0);
  805.     HTSetSuffix(".jfif",    "image/jpeg", "binary", 1.0); /* xtra */
  806.     HTSetSuffix(".jfif-tbnl",    "image/jpeg", "binary", 1.0); /* xtra */
  807.     HTSetSuffix(".jpe",        "image/jpeg", "binary", 1.0);
  808.     HTSetSuffix(".jpg",        "image/jpeg", "binary", 1.0);
  809.     HTSetSuffix(".jpeg",    "image/jpeg", "binary", 1.0);
  810.     HTSetSuffix(".tif",        "image/tiff", "binary", 1.0);
  811.     HTSetSuffix(".tiff",    "image/tiff", "binary", 1.0);
  812.     HTSetSuffix(".ham",        "image/ham", "binary", 1.0);
  813.     HTSetSuffix(".ras",        "image/x-cmu-rast", "binary", 1.0);
  814.     HTSetSuffix(".pnm",        "image/x-portable-anymap", "binary", 1.0);
  815.     HTSetSuffix(".pbm",        "image/x-portable-bitmap", "binary", 1.0);
  816.     HTSetSuffix(".pgm",        "image/x-portable-graymap", "binary", 1.0);
  817.     HTSetSuffix(".ppm",        "image/x-portable-pixmap", "binary", 1.0);
  818.     HTSetSuffix(".png",        "image/png", "binary", 1.0);
  819.     HTSetSuffix(".rgb",        "image/x-rgb", "binary", 1.0);
  820.     HTSetSuffix(".xbm",        "image/x-xbitmap", "binary", 1.0);
  821.     HTSetSuffix(".xpm",        "image/x-xpixmap", "binary", 1.0);
  822.     HTSetSuffix(".xwd",        "image/x-xwindowdump", "binary", 1.0);
  823.  
  824.     HTSetSuffix(".rtx",        "text/richtext", "8bit", 1.0);
  825.     HTSetSuffix(".tsv",        "text/tab-separated-values", "8bit", 1.0);
  826.     HTSetSuffix(".etx",        "text/x-setext", "8bit", 1.0);
  827.  
  828.     HTSetSuffix(".mpg",        "video/mpeg", "binary", 1.0);
  829.     HTSetSuffix(".mpe",        "video/mpeg", "binary", 1.0);
  830.     HTSetSuffix(".mpeg",    "video/mpeg", "binary", 1.0);
  831.     HTSetSuffix(".mov",        "video/quicktime", "binary", 1.0);
  832.     HTSetSuffix(".qt",        "video/quicktime", "binary", 1.0);
  833.     HTSetSuffix(".avi",        "video/x-msvideo", "binary", 1.0);
  834.     HTSetSuffix(".movie",    "video/x-sgi-movie", "binary", 1.0);
  835.     HTSetSuffix(".mv",        "video/x-sgi-movie", "binary", 1.0);
  836.  
  837.     HTSetSuffix(".mime",    "message/rfc822", "8bit", 1.0);
  838.  
  839.     HTSetSuffix(".c",        "text/plain", "8bit", 1.0);
  840.     HTSetSuffix(".cc",        "text/plain", "8bit", 1.0);
  841.     HTSetSuffix(".c++",        "text/plain", "8bit", 1.0);
  842.     HTSetSuffix(".h",        "text/plain", "8bit", 1.0);
  843.     HTSetSuffix(".pl",        "text/plain", "8bit", 1.0);
  844.     HTSetSuffix(".text",    "text/plain", "8bit", 1.0);
  845.     HTSetSuffix(".txt",        "text/plain", "8bit", 1.0);
  846.  
  847.     HTSetSuffix(".html3",    "text/html", "8bit", 1.0);
  848.     HTSetSuffix(".ht3",        "text/html", "8bit", 1.0);
  849.     HTSetSuffix(".phtml",    "text/html", "8bit", 1.0);
  850.     HTSetSuffix(".shtml",    "text/html", "8bit", 1.0);
  851.     HTSetSuffix(".htmlx",    "text/html", "8bit", 1.0);
  852.     HTSetSuffix(".htm",        "text/html", "8bit", 1.0);
  853.     HTSetSuffix(".html",    "text/html", "8bit", 1.0);
  854.  
  855.     /* These should override the default extensions as necessary. */
  856.     HTLoadExtensionsConfigFile(global_extension_map);
  857.  
  858.     if ((fp = fopen(personal_extension_map,"r")) != NULL) {
  859.     fclose(fp);
  860.     /* These should override everything else. */
  861.     HTLoadExtensionsConfigFile(personal_extension_map);
  862.     } else {
  863.     char buffer[256];
  864. #ifdef VMS
  865.     sprintf(buffer, "sys$login:%s", personal_extension_map);
  866. #else
  867.     sprintf(buffer, "%s/%s", (Home_Dir() ? Home_Dir() : ""),
  868.                   personal_extension_map);
  869. #endif /* VMS */
  870.     /* These should override everything else. */
  871.     HTLoadExtensionsConfigFile(buffer);
  872.     }
  873. }
  874.  
  875.  
  876. /* -------------------- Extension config file reading --------------------- */
  877.  
  878. /*
  879.  *  The following is lifted from NCSA httpd 1.0a1, by Rob McCool;
  880.  *  NCSA httpd is in the public domain, as is this code.
  881.  *
  882.  *  Modified Oct 97 - KW
  883.  */
  884.  
  885. #define MAX_STRING_LEN 256
  886.  
  887. PRIVATE int HTGetLine ARGS3(
  888.     char *,        s,
  889.     int,        n,
  890.     FILE *,        f)
  891. {
  892.     register int i = 0, r;
  893.  
  894.     if (!f)
  895.     return(1);
  896.  
  897.     while (1) {
  898.     r = fgetc(f);
  899.     s[i] = (char)r;
  900.  
  901.     if (s[i] == CR) {
  902.         r = fgetc(f);
  903.         if (r == LF)
  904.         s[i] = r;
  905.         else if (r != EOF)
  906.         ungetc(r, f);
  907.     }
  908.  
  909.     if ((r == EOF) || (s[i] == LF) || (s[i] == CR) || (i == (n-1))) {
  910.         s[i] = '\0';
  911.         return (feof(f) ? 1 : 0);
  912.     }
  913.     ++i;
  914.     }
  915. }
  916.  
  917. PRIVATE void HTGetWord ARGS4(
  918.     char *,        word,
  919.     char *,        line,
  920.     char ,        stop,
  921.     char ,        stop2)
  922. {
  923.     int x = 0, y;
  924.  
  925.     for (x = 0; line[x] && line[x] != stop && line[x] != stop2; x++) {
  926.     word[x] = line[x];
  927.     }
  928.  
  929.     word[x] = '\0';
  930.     if (line[x])
  931.     ++x;
  932.     y=0;
  933.  
  934.     while ((line[y++] = line[x++]))
  935.     ;
  936.  
  937.     return;
  938. }
  939.  
  940. PRIVATE int HTLoadExtensionsConfigFile ARGS1(
  941.     char *,        fn)
  942. {
  943.     char l[MAX_STRING_LEN],w[MAX_STRING_LEN],*ct;
  944.     FILE *f;
  945.     int count = 0;
  946.  
  947.     CTRACE(tfp, "HTLoadExtensionsConfigFile: Loading file '%s'.\n", fn);
  948.  
  949.     if ((f = fopen(fn,"r")) == NULL) {
  950.     CTRACE(tfp, "HTLoadExtensionsConfigFile: Could not open '%s'.\n", fn);
  951.     return count;
  952.     }
  953.  
  954.     while (!(HTGetLine(l,MAX_STRING_LEN,f))) {
  955.     HTGetWord(w, l, ' ', '\t');
  956.     if (l[0] == '\0' || w[0] == '#')
  957.         continue;
  958.     ct = (char *)malloc(sizeof(char) * (strlen(w) + 1));
  959.     if (!ct)
  960.         outofmem(__FILE__, "HTLoadExtensionsConfigFile");
  961.     strcpy(ct,w);
  962.     LYLowerCase(ct);
  963.  
  964.     while(l[0]) {
  965.         HTGetWord(w, l, ' ', '\t');
  966.         if (w[0] && (w[0] != ' ')) {
  967.         char *ext = (char *)malloc(sizeof(char) * (strlen(w)+1+1));
  968.             if (!ct)
  969.                 outofmem(__FILE__, "HTLoadExtensionsConfigFile");
  970.  
  971.         sprintf(ext, ".%s", w);
  972.         LYLowerCase(ext);
  973.  
  974.         CTRACE (tfp, "SETTING SUFFIX '%s' to '%s'.\n", ext, ct);
  975.  
  976.             if (strstr(ct, "tex") != NULL ||
  977.                 strstr(ct, "postscript") != NULL ||
  978.             strstr(ct, "sh") != NULL ||
  979.             strstr(ct, "troff") != NULL ||
  980.             strstr(ct, "rtf") != NULL)
  981.             HTSetSuffix (ext, ct, "8bit", 1.0);
  982.             else
  983.             HTSetSuffix (ext, ct, "binary", 1.0);
  984.         count++;
  985.  
  986.         FREE(ext);
  987.         }
  988.     }
  989.     FREE(ct);
  990.     }
  991.     fclose(f);
  992.  
  993.     return count;
  994. }
  995.