home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / uucp / uuconv / uuconv.c < prev   
Encoding:
C/C++ Source or Header  |  1995-08-20  |  56.2 KB  |  2,107 lines

  1. /* uuconv.c
  2.    Convert one type of UUCP configuration file to another.
  3.  
  4.    Copyright (C) 1991, 1992, 1993, 1994, 1995 Ian Lance Taylor
  5.  
  6.    This file is part of the Taylor UUCP package.
  7.  
  8.    This program is free software; you can redistribute it and/or
  9.    modify it under the terms of the GNU General Public License as
  10.    published by the Free Software Foundation; either version 2 of the
  11.    License, or (at your option) any later version.
  12.  
  13.    This program is distributed in the hope that it will be useful, but
  14.    WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.    General Public License for more details.
  17.  
  18.    You should have received a copy of the GNU General Public License
  19.    along with this program; if not, write to the Free Software
  20.    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  21.  
  22.    The author of the program may be contacted at ian@airs.com or
  23.    c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
  24.    */
  25.  
  26. #include "uucnfi.h"
  27.  
  28. #if USE_RCS_ID
  29. const char uuconv_rcsid[] = "$Id: uuconv.c,v 1.27 1995/06/29 19:36:27 ian Rel $";
  30. #endif
  31.  
  32. #include "getopt.h"
  33.  
  34. /* Local functions.  */
  35.  
  36. static void uvusage P((void));
  37. static void uvhelp P((void));
  38. static void uvwrite_time P((FILE *e, struct uuconf_timespan *qtime));
  39. static void uvwrite_string P((FILE *e, const char *zarg, const char *zcmd));
  40. static void uvwrite_size P((FILE *e, struct uuconf_timespan *qsize,
  41.                 const char *zcmd));
  42. static void uvwrite_boolean P((FILE *e, int iarg, const char *zcmd));
  43. static void uvwrite_string_array P((FILE *e, char **pz, const char *zcmd));
  44. static void uvwrite_chat_script P((FILE *e, char **pz));
  45. static void uvwrite_chat P((FILE *e, const struct uuconf_chat *qchat,
  46.                 const struct uuconf_chat *qlast,
  47.                 const char *zprefix, boolean fforce));
  48. static void uvwrite_proto_params P((FILE *e,
  49.                     const struct uuconf_proto_param *qparam,
  50.                     const char *zprefix));
  51. static void uvwrite_taylor_system P((FILE *e,
  52.                      const struct uuconf_system *qsys));
  53. static void uvwrite_v2_system P((FILE *e,
  54.                  const struct uuconf_system *qsys));
  55. static void uvwrite_hdb_system P((FILE *e,
  56.                   const struct uuconf_system *qsys));
  57. static boolean fvperm_string_cmp P((const char *z1, const char *z2));
  58. static boolean fvperm_array_cmp P((const char **pz1, const char **pz2));
  59. static void uvadd_perm P((struct shpermissions *qadd));
  60. static void uvwrite_perms P((void));
  61. static void uvwrite_perm_array P((FILE *e, const char **pz,
  62.                   const char *zcmd, size_t *pccol));
  63. static void uvwrite_perm_boolean P((FILE *e, int f, const char *zcmd,
  64.                     size_t *pccol, boolean fsendfiles));
  65. static void uvwrite_perm_rw_array P((FILE *e, const char **pz,
  66.                      const char *zcmd, size_t *pccol));
  67. static void uvwrite_perm_string P((FILE *e, const char *z, const char *zcmd,
  68.                    size_t *pccol));
  69. static int ivwrite_taylor_port P((struct uuconf_port *qport,
  70.                   pointer pinfo));
  71. static int ivwrite_v2_port P((struct uuconf_port *qport, pointer pinfo));
  72. static int ivwrite_hdb_port P((struct uuconf_port *qport, pointer pinfo));
  73. static void uvwrite_taylor_port P((FILE *e, struct uuconf_port *qport,
  74.                    const char *zprefix));
  75. static void uvwrite_taylor_dialer P((FILE *e, struct uuconf_dialer *qdialer,
  76.                      const char *zprefix));
  77. static void uvwrite_hdb_dialer P((FILE *e, struct uuconf_dialer *qdialer));
  78. static void uvuuconf_error P((pointer puuconf, int iret));
  79.  
  80. /* The program name.  */
  81. const char *zProgram;
  82.  
  83. /* A list of Permissions entries built when writing out HDB system
  84.    information.  */
  85. static struct shpermissions *qVperms;
  86.  
  87. /* Type of configuration file.  */
  88. enum tconfig
  89. {
  90.   CONFIG_TAYLOR,
  91.   CONFIG_V2,
  92.   CONFIG_HDB
  93. };
  94.  
  95. /* Long getopt options.  */
  96. static const struct option asVlongopts[] =
  97. {
  98.   { "input", required_argument, NULL, 'i' },
  99.   { "output", required_argument, NULL, 'o' },
  100.   { "program", required_argument, NULL, 'p' },
  101.   { "config", required_argument, NULL, 'I' },
  102.   { "debug", required_argument, NULL, 'x' },
  103.   { "version", no_argument, NULL, 'v' },
  104.   { "help", no_argument, NULL, 1 },
  105.   { NULL, 0, NULL, 0 }
  106. };
  107.  
  108. int
  109. main (argc, argv)
  110.      int argc;
  111.      char **argv;
  112. {
  113.   /* -I: The configuration file name.  */
  114.   const char *zconfig = NULL;
  115.   /* -i: Input type.  */
  116.   const char *zinput = NULL;
  117.   /* -o: Output type.  */
  118.   const char *zoutput = NULL;
  119.   /* -p: Program name.  */
  120.   const char *zprogram = NULL;
  121.   int iopt;
  122.   enum tconfig tinput, toutput;
  123.   int iret;
  124.   pointer pinput;
  125.  
  126.   zProgram = argv[0];
  127.  
  128.   while ((iopt = getopt_long (argc, argv, "i:I:o:p:vx:", asVlongopts,
  129.                   (int *) NULL)) != EOF)
  130.     {
  131.       switch (iopt)
  132.     {
  133.     case 'i':
  134.       /* Input type.  */
  135.       zinput = optarg;
  136.       break;
  137.  
  138.     case 'o':
  139.       /* Output type.  */
  140.       zoutput = optarg;
  141.       break;
  142.  
  143.     case 'p':
  144.       /* Program name.  */
  145.       zprogram = optarg;
  146.       break;
  147.  
  148.     case 'I':
  149.       /* Set the configuration file name.  */
  150.       zconfig = optarg;
  151.       break;
  152.  
  153.     case 'x':
  154.       /* Set the debugging level.  */
  155.       break;
  156.  
  157.     case 'v':
  158.       /* Print version and exit.  */
  159.       fprintf
  160.         (stderr,
  161.          "%s: Taylor UUCP %s, copyright (C) 1991, 92, 93, 94, 1995 Ian Lance Taylor\n",
  162.          zProgram, VERSION);
  163.       exit (EXIT_SUCCESS);
  164.       /*NOTREACHED*/
  165.  
  166.     case 1:
  167.       /* --help.  */
  168.       uvhelp ();
  169.       exit (EXIT_SUCCESS);
  170.       /*NOTREACHED*/
  171.  
  172.     case 0:
  173.       /* Long option found, and flag value set.  */
  174.       break;
  175.  
  176.     default:
  177.       uvusage ();
  178.       break;
  179.     }
  180.     }
  181.  
  182.   if (optind != argc
  183.       || zinput == NULL
  184.       || zoutput == NULL)
  185.     uvusage ();
  186.  
  187.   if (strcasecmp (zinput, "taylor") == 0)
  188.     tinput = CONFIG_TAYLOR;
  189.   else if (strcasecmp (zinput, "v2") == 0)
  190.     tinput = CONFIG_V2;
  191.   else if (strcasecmp (zinput, "hdb") == 0)
  192.     tinput = CONFIG_HDB;
  193.   else
  194.     {
  195.       uvusage ();
  196.       tinput = CONFIG_TAYLOR;
  197.     }
  198.  
  199.   if (strcasecmp (zoutput, "taylor") == 0)
  200.     toutput = CONFIG_TAYLOR;
  201.   else if (strcasecmp (zoutput, "v2") == 0)
  202.     toutput = CONFIG_V2;
  203.   else if (strcasecmp (zoutput, "hdb") == 0)
  204.     toutput = CONFIG_HDB;
  205.   else
  206.     {
  207.       uvusage ();
  208.       toutput = CONFIG_TAYLOR;
  209.     }
  210.  
  211.   if (tinput == toutput)
  212.     uvusage ();
  213.  
  214.   iret = UUCONF_SUCCESS;
  215.  
  216.   /* Initialize the input.  */
  217.   pinput = NULL;
  218.   switch (tinput)
  219.     {
  220.     case CONFIG_TAYLOR:
  221.       iret = uuconf_taylor_init (&pinput, zprogram, zconfig);
  222.       break;
  223.     case CONFIG_V2:
  224.       iret = uuconf_v2_init (&pinput);
  225.       break;
  226.     case CONFIG_HDB:
  227.       iret = uuconf_hdb_init (&pinput, zprogram);
  228.       break;
  229.     }
  230.   if (iret != UUCONF_SUCCESS)
  231.     {
  232.       uvuuconf_error (pinput, iret);
  233.       exit (EXIT_FAILURE);
  234.     }
  235.  
  236.   {
  237.     char **pzsystems;
  238.     char *zsys;
  239.     char abtaylor[sizeof ZCURDIR + sizeof SYSFILE - 1];
  240.     char abv2[sizeof ZCURDIR + sizeof V2_SYSTEMS - 1];
  241.     char abhdb[sizeof ZCURDIR + sizeof HDB_SYSTEMS - 1];
  242.     FILE *esys;
  243.     char **pz;
  244.  
  245.     /* Get the list of systems.  */
  246.     switch (tinput)
  247.       {
  248.       case CONFIG_TAYLOR:
  249.     iret = uuconf_taylor_system_names (pinput, &pzsystems, FALSE);
  250.     break;
  251.       case CONFIG_V2:
  252.     iret = uuconf_v2_system_names (pinput, &pzsystems, FALSE);
  253.     break;
  254.       case CONFIG_HDB:
  255.     iret = uuconf_hdb_system_names (pinput, &pzsystems, FALSE);
  256.     break;
  257.       }
  258.     if (iret != UUCONF_SUCCESS)
  259.       uvuuconf_error (pinput, iret);
  260.     else
  261.       {
  262.     /* Open the sys file for the output type.  */
  263.     switch (toutput)
  264.       {
  265.       default:
  266.       case CONFIG_TAYLOR:
  267.         sprintf (abtaylor, "%s%s", ZCURDIR, SYSFILE);
  268.         zsys = abtaylor;
  269.         break;
  270.       case CONFIG_V2:
  271.         sprintf (abv2, "%s%s", ZCURDIR, V2_SYSTEMS);
  272.         zsys = abv2;
  273.         break;
  274.       case CONFIG_HDB:
  275.         sprintf (abhdb, "%s%s", ZCURDIR, HDB_SYSTEMS);
  276.         zsys = abhdb;
  277.         break;
  278.       }
  279.     esys = fopen (zsys, "w");
  280.     if (esys == NULL)
  281.       {
  282.         fprintf (stderr, "uuchk:%s: ", zsys);
  283.         perror ("fopen");
  284.         exit (EXIT_FAILURE);
  285.       }
  286.  
  287.     fprintf (esys, "# %s file automatically generated by uuconv.\n",
  288.          zsys);
  289.  
  290.     /* Read and write each system.  We cheat and call the internal
  291.        routines, so that we can easily detect default information and
  292.        not write it out.  This isn't necessary, but it makes the output
  293.        smaller and simpler.  */
  294.     for (pz = pzsystems; *pz != NULL; pz++)
  295.       {
  296.         struct uuconf_system ssys;
  297.  
  298.         switch (tinput)
  299.           {
  300.           case CONFIG_TAYLOR:
  301.         iret = _uuconf_itaylor_system_internal (pinput, *pz, &ssys);
  302.         break;
  303.           case CONFIG_V2:
  304.         iret = _uuconf_iv2_system_internal (pinput, *pz, &ssys);
  305.         break;
  306.           case CONFIG_HDB:
  307.         iret = _uuconf_ihdb_system_internal (pinput, *pz, &ssys);
  308.         break;
  309.           }
  310.         if (iret != UUCONF_SUCCESS)
  311.           uvuuconf_error (pinput, iret);
  312.         else
  313.           {
  314.         switch (toutput)
  315.           {
  316.           case CONFIG_TAYLOR:
  317.             uvwrite_taylor_system (esys, &ssys);
  318.             break;
  319.           case CONFIG_V2:
  320.             uvwrite_v2_system (esys, &ssys);
  321.             break;
  322.           case CONFIG_HDB:
  323.             uvwrite_hdb_system (esys, &ssys);
  324.             break;
  325.           }
  326.         if (toutput != CONFIG_HDB)
  327.           (void) uuconf_system_free (pinput, &ssys);
  328.           }
  329.       }
  330.  
  331.     if (toutput == CONFIG_HDB)
  332.       uvwrite_perms ();
  333.  
  334.     if (ferror (esys)
  335.         || fclose (esys) == EOF)
  336.       {
  337.         fprintf (stderr, "uuchk:%s: error during output\n", zsys);
  338.         exit (EXIT_FAILURE);
  339.       }
  340.       }
  341.   }
  342.  
  343.   {
  344.     /* Open the port file for the output type.  */
  345.     char *zport;
  346.     char abtaylor[sizeof ZCURDIR + sizeof PORTFILE - 1];
  347.     char abv2[sizeof ZCURDIR + sizeof V2_DEVICES - 1];
  348.     char abhdb[sizeof ZCURDIR + sizeof HDB_DEVICES - 1];
  349.     FILE *eport;
  350.     int (*piportfn) P((struct uuconf_port *, pointer));
  351.     struct uuconf_port sport;
  352.  
  353.     switch (toutput)
  354.       {
  355.       default:
  356.       case CONFIG_TAYLOR:
  357.     sprintf (abtaylor, "%s%s", ZCURDIR, PORTFILE);
  358.     zport = abtaylor;
  359.     piportfn = ivwrite_taylor_port;
  360.     break;
  361.       case CONFIG_V2:
  362.     sprintf (abv2, "%s%s", ZCURDIR, V2_DEVICES);
  363.     zport = abv2;
  364.     piportfn = ivwrite_v2_port;
  365.     break;
  366.       case CONFIG_HDB:
  367.     sprintf (abhdb, "%s%s", ZCURDIR, HDB_DEVICES);
  368.     zport = abhdb;
  369.     piportfn = ivwrite_hdb_port;
  370.     break;
  371.       }
  372.     eport = fopen (zport, "w");
  373.     if (eport == NULL)
  374.       {
  375.     fprintf (stderr, "uuchk:%s: ", zport);
  376.     perror ("fopen");
  377.     exit (EXIT_FAILURE);
  378.       }
  379.  
  380.     fprintf (eport, "# %s file automatically generated by uuconv.\n", zport);
  381.  
  382.     switch (tinput)
  383.       {
  384.       case CONFIG_TAYLOR:
  385.     iret = uuconf_taylor_find_port (pinput, (const char *) NULL, 0L,
  386.                     0L, piportfn, (pointer) eport,
  387.                     &sport);
  388.     break;
  389.       case CONFIG_V2:
  390.     iret = uuconf_v2_find_port (pinput, (const char *) NULL, 0L, 0L,
  391.                     piportfn, (pointer) eport, &sport);
  392.     break;
  393.       case CONFIG_HDB:
  394.     iret = uuconf_hdb_find_port (pinput, (const char *) NULL, 0L, 0L,
  395.                      piportfn, (pointer) eport, &sport);
  396.     break;
  397.       }
  398.     
  399.     if (iret != UUCONF_NOT_FOUND)
  400.       uvuuconf_error (pinput, iret);
  401.  
  402.     if (ferror (eport)
  403.     || fclose (eport) == EOF)
  404.       {
  405.     fprintf (stderr, "uuchk:%s: error during output\n", zport);
  406.     exit (EXIT_FAILURE);
  407.       }
  408.   }
  409.  
  410.   /* V2 configuration files don't support dialers.  */
  411.   if (tinput != CONFIG_V2 && toutput != CONFIG_V2)
  412.     {
  413.       char **pzdialers;
  414.       char *zdialer;
  415.       char abtaylor[sizeof ZCURDIR + sizeof DIALFILE - 1];
  416.       char abhdb[sizeof ZCURDIR + sizeof HDB_DIALERS - 1];
  417.       FILE *edialer;
  418.       char **pz;
  419.  
  420.       /* Get the list of dialers.  */
  421.       switch (tinput)
  422.     {
  423.     default:
  424.     case CONFIG_TAYLOR:
  425.       iret = uuconf_taylor_dialer_names (pinput, &pzdialers);
  426.       break;
  427.     case CONFIG_HDB:
  428.       iret = uuconf_hdb_dialer_names (pinput, &pzdialers);
  429.       break;
  430.     }
  431.       if (iret != UUCONF_SUCCESS)
  432.     uvuuconf_error (pinput, iret);
  433.       else
  434.     {
  435.       /* Open the sys file for the output type.  */
  436.       switch (toutput)
  437.         {
  438.         default:
  439.         case CONFIG_TAYLOR:
  440.           sprintf (abtaylor, "%s%s", ZCURDIR, DIALFILE);
  441.           zdialer = abtaylor;
  442.           break;
  443.         case CONFIG_HDB:
  444.           sprintf (abhdb, "%s%s", ZCURDIR, HDB_DIALERS);
  445.           zdialer = abhdb;
  446.           break;
  447.         }
  448.       edialer = fopen (zdialer, "w");
  449.       if (edialer == NULL)
  450.         {
  451.           fprintf (stderr, "uuchk:%s: ", zdialer);
  452.           perror ("fopen");
  453.           exit (EXIT_FAILURE);
  454.         }
  455.  
  456.       fprintf (edialer, "# %s file automatically generated by uuconv.\n",
  457.            zdialer);
  458.  
  459.       /* Read and write each dialer.  */
  460.       for (pz = pzdialers; *pz != NULL; pz++)
  461.         {
  462.           struct uuconf_dialer sdialer;
  463.  
  464.           switch (tinput)
  465.         {
  466.         default:
  467.         case CONFIG_TAYLOR:
  468.           iret = uuconf_taylor_dialer_info (pinput, *pz, &sdialer);
  469.           break;
  470.         case CONFIG_HDB:
  471.           iret = uuconf_hdb_dialer_info (pinput, *pz, &sdialer);
  472.           break;
  473.         }
  474.           if (iret != UUCONF_SUCCESS)
  475.         uvuuconf_error (pinput, iret);
  476.           else
  477.         {
  478.           switch (toutput)
  479.             {
  480.             default:
  481.             case CONFIG_TAYLOR:
  482.               fprintf (edialer, "# Start of dialer %s\n",
  483.                    sdialer.uuconf_zname);
  484.               fprintf (edialer, "dialer %s\n", sdialer.uuconf_zname);
  485.               uvwrite_taylor_dialer (edialer, &sdialer, "");
  486.               break;
  487.             case CONFIG_HDB:
  488.               uvwrite_hdb_dialer (edialer, &sdialer);
  489.               break;
  490.             }
  491.           (void) uuconf_dialer_free (pinput, &sdialer);
  492.         }
  493.         }
  494.  
  495.       if (ferror (edialer)
  496.           || fclose (edialer) == EOF)
  497.         {
  498.           fprintf (stderr, "uuchk:%s: error during output\n", zdialer);
  499.           exit (EXIT_FAILURE);
  500.         }
  501.     }
  502.     }
  503.  
  504.   exit (EXIT_SUCCESS);
  505.  
  506.   /* Avoid complaints about not returning.  */
  507.   return 0;
  508. }
  509.  
  510. /* Print out a usage message and die.  */
  511.  
  512. static void
  513. uvusage ()
  514. {
  515.   fprintf (stderr, "Usage: %s -i input-type -o output-type [-p program]\n",
  516.        zProgram);
  517.   fprintf (stderr, "Use %s --help for help\n", zProgram);
  518.   exit (EXIT_FAILURE);
  519. }
  520.  
  521. /* Print a help message.  */
  522.  
  523. static void
  524. uvhelp ()
  525. {
  526.   fprintf (stderr,
  527.        "Taylor UUCP %s, copyright (C) 1991, 92, 93, 94, 1995 Ian Lance Taylor\n",
  528.        VERSION);
  529.   fprintf (stderr, "Converts UUCP configuration files from one format to another.\n");
  530.   fprintf (stderr,
  531.        "Usage: %s -i input -o output [-p program] [-I file]\n", zProgram);
  532.   fprintf (stderr,
  533.        " -i,--input input: Set input type (one of taylor, v2, hdb)\n");
  534.   fprintf (stderr,
  535.        " -o,--output output: Set output type (one of taylor, v2, hdb)\n");
  536.   fprintf (stderr,
  537.        " -p,--program program: Program to convert (e.g., uucp or cu)\n");
  538.   fprintf (stderr,
  539.        " -I,--config file: Set Taylor UUCP configuration file to use\n");
  540.   fprintf (stderr,
  541.        " -v,--version: Print version and exit\n");
  542.   fprintf (stderr,
  543.        " --help: Print help and exit\n");
  544. }
  545.  
  546. /* Write out a timespan.  */
  547.  
  548. static void
  549. uvwrite_time (e, qtime)
  550.      FILE *e;
  551.      struct uuconf_timespan *qtime;
  552. {
  553.   if (qtime == NULL)
  554.     {
  555.       fprintf (e, "Never");
  556.       return;
  557.     }
  558.  
  559.   if (qtime->uuconf_istart == 0 && qtime->uuconf_iend == 7 * 24 * 60)
  560.     {
  561.       fprintf (e, "Any");
  562.       return;
  563.     }
  564.  
  565.   for (; qtime != NULL; qtime = qtime->uuconf_qnext)
  566.     {
  567.       int idaystart, idayend;
  568.       int ihourstart, ihourend;
  569.       int iminutestart, iminuteend;
  570.       const char * const zdays = "Su\0Mo\0Tu\0We\0Th\0Fr\0Sa";
  571.  
  572.       idaystart = qtime->uuconf_istart / (24 * 60);
  573.       ihourstart = (qtime->uuconf_istart % (24 * 60)) / 60;
  574.       iminutestart = qtime->uuconf_istart % 60;
  575.       if (qtime->uuconf_iend >= 7 * 24 * 60)
  576.     qtime->uuconf_iend = 7 * 24 * 60 - 1;
  577.       idayend = qtime->uuconf_iend / (24 * 60);
  578.       ihourend = (qtime->uuconf_iend % (24 * 60)) / 60;
  579.       iminuteend = qtime->uuconf_iend % 60;
  580.       if (ihourend == 0 && iminuteend == 0)
  581.     --idayend;
  582.  
  583.       if (idaystart == idayend)
  584.     fprintf (e, "%s%02d%02d-%02d%02d", zdays + idaystart * 3,
  585.          ihourstart, iminutestart, ihourend, iminuteend);
  586.       else
  587.     {
  588.       int i;
  589.  
  590.       fprintf (e, "%s%02d%02d-0000", zdays + idaystart * 3,
  591.            ihourstart, iminutestart);
  592.       for (i = idaystart + 1; i < idayend; i++)
  593.         fprintf (e, ",%s", zdays + i * 3);
  594.       if (ihourend != 0 || iminuteend != 0)
  595.         fprintf (e, ",%s0000-%02d%02d", zdays + idayend * 3, ihourend,
  596.              iminuteend);
  597.     }
  598.  
  599.       if (qtime->uuconf_qnext != NULL)
  600.     fprintf (e, ",");
  601.     }
  602. }
  603.  
  604. /* Some subroutines used when writing out Taylor UUCP configuration
  605.    files.  */
  606.  
  607. /* Write a command with a string argument.  */
  608.  
  609. static void
  610. uvwrite_string (e, zarg, zcmd)
  611.      FILE *e;
  612.      const char *zarg;
  613.      const char *zcmd;
  614. {
  615.   if (zarg != (const char *) &_uuconf_unset)
  616.     fprintf (e, "%s %s\n", zcmd, zarg == NULL ? (const char *) "" : zarg);
  617. }
  618.  
  619. /* Write out a size restriction command.  */
  620.  
  621. static void
  622. uvwrite_size (e, qtime, zcmd)
  623.      FILE *e;
  624.      struct uuconf_timespan *qtime;
  625.      const char *zcmd;
  626. {
  627.   if (qtime != (struct uuconf_timespan *) &_uuconf_unset)
  628.     {
  629.       for (; qtime != NULL; qtime = qtime->uuconf_qnext)
  630.     {
  631.       fprintf (e, "%s %ld", zcmd, qtime->uuconf_ival);
  632.       uvwrite_time (e, qtime);
  633.       fprintf (e, "\n");
  634.     }
  635.     }
  636. }
  637.  
  638. /* Write out a boolean argument with a string command.  If the value
  639.    is less than zero, than it was uninitialized and we don't write
  640.    anything.  */
  641.  
  642. static void
  643. uvwrite_boolean (e, fval, zcmd)
  644.      FILE *e;
  645.      int fval;
  646.      const char *zcmd;
  647. {
  648.   if (fval >= 0)
  649.     fprintf (e, "%s %s\n", zcmd, fval > 0 ? "true" : "false");
  650. }
  651.  
  652. /* Write out a string array as a single command.  */
  653.  
  654. static void
  655. uvwrite_string_array (e, pz, zcmd)
  656.      FILE *e;
  657.      char **pz;
  658.      const char *zcmd;
  659. {
  660.   if (pz != (char **) &_uuconf_unset)
  661.     {
  662.       fprintf (e, "%s", zcmd);
  663.       if (pz != NULL)
  664.     for (; *pz != NULL; pz++)
  665.       fprintf (e, " %s", *pz);
  666.       fprintf (e, "\n");
  667.     }
  668. }
  669.  
  670. /* Write out a chat script.  Don't separate subsend/subexpect strings
  671.    by spaces.  */
  672.  
  673. static void
  674. uvwrite_chat_script (e, pzarg)
  675.      FILE *e;
  676.      char **pzarg;
  677. {
  678.   char **pz;
  679.  
  680.   if (pzarg == NULL || pzarg == (char **) &_uuconf_unset)
  681.     return;
  682.  
  683.   for (pz = pzarg; *pz != NULL; pz++)
  684.     {
  685.       if ((*pz)[0] != '-' && pz != pzarg)
  686.     fprintf (e, " ");
  687.       fprintf (e, *pz);
  688.     }
  689. }
  690.  
  691. /* Write out chat information.  If the qlast argument is not NULL,
  692.    then only values that are different from qlast should be written.
  693.    The fforce argument is used to get around a peculiar problem: if
  694.    the ``chat'' command is used with no arguments for a system, then
  695.    uuconf_pzchat will be NULL (not &_uuconf_unset) and the default
  696.    chat script will not be used.  We must distinguish this case from
  697.    the ``chat'' command not appearing at all for a port or dialer, in
  698.    which case the value will again be NULL.  In the former case we
  699.    must output a ``chat'' command, in the latter case we would prefer
  700.    not to.  */
  701.  
  702. static void
  703. uvwrite_chat (e, q, qlast, zprefix, fforce)
  704.      FILE *e;
  705.      const struct uuconf_chat *q;
  706.      const struct uuconf_chat *qlast;
  707.      const char *zprefix;
  708.      boolean fforce;
  709. {
  710.   char **pz;
  711.   char ab[100];
  712.  
  713.   if (q->uuconf_pzchat != (char **) &_uuconf_unset
  714.       && (qlast == NULL
  715.       ? (fforce || q->uuconf_pzchat != NULL)
  716.       : qlast->uuconf_pzchat != q->uuconf_pzchat))
  717.     {
  718.       fprintf (e, "%schat ", zprefix);
  719.       uvwrite_chat_script (e, q->uuconf_pzchat);
  720.       fprintf (e, "\n");
  721.     }
  722.  
  723.   if (q->uuconf_pzprogram != (char **) &_uuconf_unset
  724.       && (qlast == NULL
  725.       ? q->uuconf_pzprogram != NULL
  726.       : qlast->uuconf_pzprogram != q->uuconf_pzprogram))
  727.     {
  728.       sprintf (ab, "%schat-program", zprefix);
  729.       uvwrite_string_array (e, q->uuconf_pzprogram, ab);
  730.     }
  731.  
  732.   if (q->uuconf_ctimeout >= 0
  733.       && (qlast == NULL
  734.       || qlast->uuconf_ctimeout != q->uuconf_ctimeout))
  735.     fprintf (e, "%schat-timeout %d\n", zprefix, q->uuconf_ctimeout);
  736.  
  737.   if (q->uuconf_pzfail != NULL
  738.       && q->uuconf_pzfail != (char **) &_uuconf_unset
  739.       && (qlast == NULL
  740.       || qlast->uuconf_pzfail != q->uuconf_pzfail))
  741.     for (pz = q->uuconf_pzfail; *pz != NULL; pz++)
  742.       fprintf (e, "%schat-fail %s\n", zprefix, *pz);
  743.       
  744.   if (qlast == NULL || qlast->uuconf_fstrip != q->uuconf_fstrip)
  745.     {
  746.       sprintf (ab, "%schat-strip", zprefix);
  747.       uvwrite_boolean (e, q->uuconf_fstrip, ab);
  748.     }
  749. }
  750.  
  751. /* Write out protocol parameters to a Taylor UUCP file.  */
  752.  
  753. static void
  754. uvwrite_proto_params (e, qparams, zprefix)
  755.      FILE *e;
  756.      const struct uuconf_proto_param *qparams;
  757.      const char *zprefix;
  758. {
  759.   const struct uuconf_proto_param *qp;
  760.  
  761.   if (qparams == NULL
  762.       || qparams == (struct uuconf_proto_param *) &_uuconf_unset)
  763.     return;
  764.  
  765.   for (qp = qparams; qp->uuconf_bproto != '\0'; qp++)
  766.     {
  767.       const struct uuconf_proto_param_entry *qe;
  768.  
  769.       for (qe = qp->uuconf_qentries; qe->uuconf_cargs > 0; qe++)
  770.     {
  771.       int i;
  772.  
  773.       fprintf (e, "%sprotocol-parameter %c", zprefix, qp->uuconf_bproto);
  774.       for (i = 0; i < qe->uuconf_cargs; i++)
  775.         fprintf (e, " %s", qe->uuconf_pzargs[i]);
  776.       fprintf (e, "\n");
  777.     }
  778.     }
  779. }
  780.  
  781. /* Write out Taylor UUCP system information.  */
  782.  
  783. static void
  784. uvwrite_taylor_system (e, q)
  785.      FILE *e;
  786.      const struct uuconf_system *q;
  787. {
  788.   char **pz;
  789.   const struct uuconf_system *qlast;
  790.  
  791.   fprintf (e, "# Start of system %s\n", q->uuconf_zname);
  792.  
  793.   fprintf (e, "system %s\n", q->uuconf_zname);
  794.   if (q->uuconf_pzalias != NULL
  795.       && q->uuconf_pzalias != (char **) &_uuconf_unset)
  796.     for (pz = q->uuconf_pzalias; *pz != NULL; pz++)
  797.       uvwrite_string (e, *pz, "alias");
  798.  
  799.   for (qlast = NULL; q != NULL; qlast = q, q = q->uuconf_qalternate)
  800.     {
  801.       struct uuconf_timespan *qtime;
  802.  
  803.       if (qlast != NULL)
  804.     {
  805.       fprintf (e, "alternate");
  806.       if (q->uuconf_zalternate != (char *) &_uuconf_unset
  807.           && q->uuconf_zalternate != NULL)
  808.         fprintf (e, " %s", q->uuconf_zalternate);
  809.       fprintf (e, "\n");
  810.     }
  811.  
  812. #define CHANGED(x) (qlast == NULL || qlast->x != q->x)
  813.  
  814.       if (CHANGED (uuconf_qtimegrade)
  815.       && (q->uuconf_qtimegrade
  816.           != (struct uuconf_timespan *) &_uuconf_unset))
  817.     {
  818.       if (q->uuconf_qtimegrade == NULL)
  819.         fprintf (e, "time never\n");
  820.       else
  821.         {
  822.           for (qtime = q->uuconf_qtimegrade;
  823.            qtime != NULL;
  824.            qtime = qtime->uuconf_qnext)
  825.         {
  826.           if ((char) qtime->uuconf_ival == UUCONF_GRADE_LOW)
  827.             fprintf (e, "time ");
  828.           else
  829.             fprintf (e, "timegrade %c ", (char) qtime->uuconf_ival);
  830.           uvwrite_time (e, qtime);
  831.           if (qtime->uuconf_cretry != 0)
  832.             fprintf (e, " %d", qtime->uuconf_cretry);
  833.           fprintf (e, "\n");
  834.         }
  835.         }
  836.     }
  837.  
  838.       if (CHANGED (uuconf_qcalltimegrade)
  839.       && (q->uuconf_qcalltimegrade
  840.           != (struct uuconf_timespan *) &_uuconf_unset))
  841.     {
  842.       for (qtime = q->uuconf_qcalltimegrade;
  843.            qtime != NULL;
  844.            qtime = qtime->uuconf_qnext)
  845.         {
  846.           fprintf (e, "call-timegrade %c ", (char) qtime->uuconf_ival);
  847.           uvwrite_time (e, qtime);
  848.           fprintf (e, "\n");
  849.         }
  850.     }
  851.  
  852.       if (CHANGED (uuconf_qcalledtimegrade)
  853.       && (q->uuconf_qcalledtimegrade
  854.           != (struct uuconf_timespan *) &_uuconf_unset))
  855.     {
  856.       for (qtime = q->uuconf_qcalledtimegrade;
  857.            qtime != NULL;
  858.            qtime = qtime->uuconf_qnext)
  859.         {
  860.           fprintf (e, "called-timegrade %c ", (char) qtime->uuconf_ival);
  861.           uvwrite_time (e, qtime);
  862.           fprintf (e, "\n");
  863.         }
  864.     }
  865.  
  866.       if (CHANGED (uuconf_qcall_local_size))
  867.     uvwrite_size (e, q->uuconf_qcall_local_size, "call-local-size");
  868.  
  869.       if (CHANGED (uuconf_qcall_remote_size))
  870.     uvwrite_size (e, q->uuconf_qcall_remote_size, "call-remote-size");
  871.  
  872.       if (CHANGED (uuconf_qcalled_local_size))
  873.     uvwrite_size (e, q->uuconf_qcalled_local_size, "called-local-size");
  874.  
  875.       if (CHANGED (uuconf_qcalled_remote_size))
  876.     uvwrite_size (e, q->uuconf_qcalled_remote_size, "called-remote-size");
  877.  
  878.       if (CHANGED (uuconf_ibaud) || CHANGED (uuconf_ihighbaud))
  879.     {
  880.       if (q->uuconf_ibaud >= 0)
  881.         {
  882.           if (q->uuconf_ihighbaud > 0)
  883.         fprintf (e, "baud-range %ld %ld\n", q->uuconf_ibaud,
  884.              q->uuconf_ihighbaud);
  885.           else
  886.         fprintf (e, "baud %ld\n", q->uuconf_ibaud);
  887.         }
  888.     }
  889.  
  890.       if (CHANGED (uuconf_zport) || CHANGED (uuconf_qport))
  891.     {
  892.       if (q->uuconf_zport != NULL
  893.           && q->uuconf_zport != (char *) &_uuconf_unset)
  894.         uvwrite_string (e, q->uuconf_zport, "port");
  895.       else if (q->uuconf_qport != NULL
  896.            && (q->uuconf_qport
  897.                != (struct uuconf_port *) &_uuconf_unset))
  898.         uvwrite_taylor_port (e, q->uuconf_qport, "port ");
  899.     }
  900.  
  901.       if (CHANGED (uuconf_zphone))
  902.     {
  903.       const char *zcmd;
  904.  
  905.       if (q->uuconf_qport != NULL
  906.           && q->uuconf_qport != (struct uuconf_port *) &_uuconf_unset
  907.           && (q->uuconf_qport->uuconf_ttype == UUCONF_PORTTYPE_TCP
  908.           || q->uuconf_qport->uuconf_ttype == UUCONF_PORTTYPE_TLI))
  909.         zcmd = "address";
  910.       else
  911.         zcmd = "phone";
  912.       uvwrite_string (e, q->uuconf_zphone, zcmd);
  913.     }
  914.  
  915.       uvwrite_chat (e, &q->uuconf_schat,
  916.             (qlast == NULL
  917.              ? (struct uuconf_chat *) NULL
  918.              : &qlast->uuconf_schat),
  919.             "", TRUE);
  920.  
  921.       if (CHANGED (uuconf_zcall_login))
  922.     uvwrite_string (e, q->uuconf_zcall_login, "call-login");
  923.  
  924.       if (CHANGED (uuconf_zcall_password))
  925.     uvwrite_string (e, q->uuconf_zcall_password, "call-password");
  926.  
  927.       if (CHANGED (uuconf_zcalled_login))
  928.     uvwrite_string (e, q->uuconf_zcalled_login, "called-login");
  929.  
  930.       if (CHANGED (uuconf_fcallback))
  931.     uvwrite_boolean (e, q->uuconf_fcallback, "callback");
  932.  
  933.       if (CHANGED (uuconf_fsequence))
  934.     uvwrite_boolean (e, q->uuconf_fsequence, "sequence");
  935.  
  936.       if (CHANGED (uuconf_zprotocols))
  937.     uvwrite_string (e, q->uuconf_zprotocols, "protocol");
  938.  
  939.       if (CHANGED (uuconf_qproto_params))
  940.     uvwrite_proto_params (e, q->uuconf_qproto_params, "");
  941.       
  942.       uvwrite_chat (e, &q->uuconf_scalled_chat,
  943.             (qlast == NULL
  944.              ? (struct uuconf_chat *) NULL
  945.              : &qlast->uuconf_scalled_chat),
  946.             "called-", FALSE);
  947.  
  948.       if (CHANGED (uuconf_zdebug))
  949.     uvwrite_string (e, q->uuconf_zdebug, "debug");
  950.  
  951.       if (CHANGED (uuconf_zmax_remote_debug))
  952.     uvwrite_string (e, q->uuconf_zmax_remote_debug, "max-remote-debug");
  953.  
  954.       if ((CHANGED (uuconf_fsend_request)
  955.        || CHANGED (uuconf_frec_request))
  956.       && (q->uuconf_fsend_request >= 0
  957.           || q->uuconf_frec_request >= 0))
  958.     {
  959.       if (q->uuconf_fsend_request >= 0
  960.           && (q->uuconf_fsend_request > 0
  961.           ? q->uuconf_frec_request > 0
  962.           : q->uuconf_frec_request == 0))
  963.         uvwrite_boolean (e, q->uuconf_fsend_request, "request");
  964.       else
  965.         {
  966.           uvwrite_boolean (e, q->uuconf_fsend_request, "send-request");
  967.           uvwrite_boolean (e, q->uuconf_frec_request,
  968.                    "receive-request");
  969.         }
  970.     }
  971.  
  972.       if ((CHANGED (uuconf_fcall_transfer)
  973.        || CHANGED (uuconf_fcalled_transfer))
  974.       && (q->uuconf_fcall_transfer >= 0
  975.           || q->uuconf_fcalled_transfer >= 0))
  976.     {
  977.       if (q->uuconf_fcall_transfer >= 0
  978.           && (q->uuconf_fcall_transfer > 0
  979.           ? q->uuconf_fcalled_transfer > 0
  980.           : q->uuconf_fcalled_transfer == 0))
  981.         uvwrite_boolean (e, q->uuconf_fcall_transfer, "transfer");
  982.       else
  983.         {
  984.           uvwrite_boolean (e, q->uuconf_fcall_transfer, "call-transfer");
  985.           uvwrite_boolean (e, q->uuconf_fcalled_transfer,
  986.                    "called-transfer");
  987.         }
  988.     }
  989.  
  990.       if (CHANGED (uuconf_pzlocal_send))
  991.     uvwrite_string_array (e, q->uuconf_pzlocal_send, "local-send");
  992.  
  993.       if (CHANGED (uuconf_pzremote_send))
  994.     uvwrite_string_array (e, q->uuconf_pzremote_send, "remote-send");
  995.  
  996.       if (CHANGED (uuconf_pzlocal_receive))
  997.     uvwrite_string_array (e, q->uuconf_pzlocal_receive, "local-receive");
  998.  
  999.       if (CHANGED (uuconf_pzremote_receive))
  1000.     uvwrite_string_array (e, q->uuconf_pzremote_receive,
  1001.                   "remote-receive");
  1002.  
  1003.       if (CHANGED (uuconf_pzpath))
  1004.     uvwrite_string_array (e, q->uuconf_pzpath, "command-path");
  1005.  
  1006.       if (CHANGED (uuconf_pzcmds))
  1007.     uvwrite_string_array (e, q->uuconf_pzcmds, "commands");
  1008.  
  1009.       if (CHANGED (uuconf_cfree_space)
  1010.       && q->uuconf_cfree_space >= 0)
  1011.     fprintf (e, "free-space %ld\n", q->uuconf_cfree_space);
  1012.  
  1013.       if (CHANGED (uuconf_pzforward_from))
  1014.     uvwrite_string_array (e, q->uuconf_pzforward_from, "forward-from");
  1015.  
  1016.       if (CHANGED (uuconf_pzforward_to))
  1017.     uvwrite_string_array (e, q->uuconf_pzforward_to, "forward-to");
  1018.  
  1019.       if (CHANGED (uuconf_zpubdir))
  1020.     uvwrite_string (e, q->uuconf_zpubdir, "pubdir");
  1021.  
  1022.       if (CHANGED (uuconf_zlocalname))
  1023.     uvwrite_string (e, q->uuconf_zlocalname, "myname");
  1024.     }
  1025. }
  1026.  
  1027. /* Write out V2 system information.  */
  1028.  
  1029. static void
  1030. uvwrite_v2_system (e, q)
  1031.      FILE *e;
  1032.      const struct uuconf_system *q;
  1033. {
  1034.   for (; q != NULL; q = q->uuconf_qalternate)
  1035.     {
  1036.       fprintf (e, "%s", q->uuconf_zname);
  1037.  
  1038.       if (q->uuconf_qtimegrade != (struct uuconf_timespan *) &_uuconf_unset)
  1039.     {
  1040.       fprintf (e, " ");
  1041.       uvwrite_time (e, q->uuconf_qtimegrade);
  1042.  
  1043.       if (q->uuconf_zport != (char *) &_uuconf_unset
  1044.           || q->uuconf_qport != (struct uuconf_port *) &_uuconf_unset)
  1045.         {
  1046.           struct uuconf_port *qp;
  1047.           boolean ftcp;
  1048.  
  1049.           qp = q->uuconf_qport;
  1050.           ftcp = (qp != (struct uuconf_port *) &_uuconf_unset
  1051.               && qp != NULL
  1052.               && qp->uuconf_ttype == UUCONF_PORTTYPE_TCP);
  1053.           if (ftcp
  1054.           || (q->uuconf_zport != NULL
  1055.               && q->uuconf_zport != (char *) &_uuconf_unset))
  1056.         {
  1057.           if (ftcp)
  1058.             fprintf (e, " TCP");
  1059.           else
  1060.             fprintf (e, " %s", q->uuconf_zport);
  1061.  
  1062.           if (ftcp || q->uuconf_ibaud >= 0)
  1063.             {
  1064.               fprintf (e, " ");
  1065.               if (ftcp)
  1066.             {
  1067.               const char *zport;
  1068.  
  1069.               zport = qp->uuconf_u.uuconf_stcp.uuconf_zport;
  1070.               if (zport == NULL)
  1071.                 zport = "uucp";
  1072.               fprintf (e, "%s", zport);
  1073.             }
  1074.               else
  1075.             fprintf (e, "%ld", q->uuconf_ibaud);
  1076.  
  1077.               if (q->uuconf_zphone != (char *) &_uuconf_unset
  1078.               && q->uuconf_zphone != NULL)
  1079.             {
  1080.               char **pzc;
  1081.               
  1082.               fprintf (e, " %s", q->uuconf_zphone);
  1083.               pzc = q->uuconf_schat.uuconf_pzchat;
  1084.               if (pzc != (char **) &_uuconf_unset
  1085.                   && pzc != NULL)
  1086.                 {
  1087.                   fprintf (e, " ");
  1088.                   uvwrite_chat_script (e, pzc);
  1089.                 }
  1090.             }
  1091.             }
  1092.         }
  1093.         }
  1094.     }
  1095.  
  1096.       fprintf (e, "\n");
  1097.  
  1098.       /* Here we should gather information to write out to USERFILE
  1099.      and L.cmds, and perhaps some day we will.  It's much more
  1100.      likely to happen if somebody else does it, though.  */
  1101.     }
  1102. }
  1103.  
  1104. /* Write out HDB system information.  */
  1105.  
  1106. static void
  1107. uvwrite_hdb_system (e, qsys)
  1108.      FILE *e;
  1109.      const struct uuconf_system *qsys;
  1110. {
  1111.   const struct uuconf_system *q;
  1112.   struct shpermissions sperm;
  1113.   char *azmachine[2];
  1114.   char *azlogname[2];
  1115.  
  1116.   for (q = qsys; q != NULL; q = q->uuconf_qalternate)
  1117.     {
  1118.       if (q->uuconf_fcall)
  1119.     {
  1120.       fprintf (e, "%s", q->uuconf_zname);
  1121.  
  1122.       if (q->uuconf_qtimegrade
  1123.           != (struct uuconf_timespan *) &_uuconf_unset)
  1124.         {
  1125.           const char *zport;
  1126.  
  1127.           fprintf (e, " ");
  1128.           uvwrite_time (e, q->uuconf_qtimegrade);
  1129.  
  1130.           zport = q->uuconf_zport;
  1131.           if (q->uuconf_qport != NULL
  1132.           && q->uuconf_qport != (struct uuconf_port *) &_uuconf_unset
  1133.           && q->uuconf_qport->uuconf_ttype == UUCONF_PORTTYPE_TCP)
  1134.         zport = "TCP";
  1135.           if (zport != NULL && zport != (char *) &_uuconf_unset)
  1136.         {
  1137.           fprintf (e, " %s", zport);
  1138.           if (q->uuconf_zprotocols != (char *) &_uuconf_unset
  1139.               && q->uuconf_zprotocols != NULL)
  1140.             fprintf (e, ",%s", q->uuconf_zprotocols);
  1141.  
  1142.           if (q->uuconf_ibaud >= 0
  1143.               || q->uuconf_zphone != (char *) &_uuconf_unset)
  1144.             {
  1145.               fprintf (e, " ");
  1146.               if (q->uuconf_ibaud < 0)
  1147.             fprintf (e, "Any");
  1148.               else
  1149.             {
  1150.               fprintf (e, "%ld", q->uuconf_ibaud);
  1151.               if (q->uuconf_ihighbaud >= 0)
  1152.                 fprintf (e, "-%ld", q->uuconf_ihighbaud);
  1153.             }
  1154.  
  1155.               if (q->uuconf_zphone != (char *) &_uuconf_unset
  1156.               && q->uuconf_zphone != NULL)
  1157.             {
  1158.               char **pzc;
  1159.               
  1160.               fprintf (e, " %s", q->uuconf_zphone);
  1161.               pzc = q->uuconf_schat.uuconf_pzchat;
  1162.               if (pzc != (char **) &_uuconf_unset
  1163.                   && pzc != NULL)
  1164.                 {
  1165.                   fprintf (e, " ");
  1166.                   uvwrite_chat_script (e, pzc);
  1167.                 }
  1168.             }
  1169.             }
  1170.         }
  1171.         }
  1172.  
  1173.       fprintf (e, "\n");
  1174.     }
  1175.     }
  1176.  
  1177.   /* Build a Permissions entry for this system.  There will be only
  1178.      one MACHINE entry for a given system.  */
  1179.  
  1180.   for (q = qsys; q != NULL; q = q->uuconf_qalternate)
  1181.     if (q->uuconf_fcall)
  1182.       break;
  1183.  
  1184.   if (q != NULL)
  1185.     {
  1186.       sperm.qnext = NULL;
  1187.       sperm.pzlogname = NULL;
  1188.       sperm.pzmachine = NULL;
  1189.       sperm.frequest = -1;
  1190.       sperm.fsendfiles = -1;
  1191.       sperm.pzread = NULL;
  1192.       sperm.pzwrite = NULL;
  1193.       sperm.fcallback = -1;
  1194.       sperm.pzcommands = NULL;
  1195.       sperm.pzvalidate = NULL;
  1196.       sperm.zmyname = NULL;
  1197.       sperm.zpubdir = NULL;
  1198.       sperm.pzalias = NULL;
  1199.  
  1200.       azmachine[0] = q->uuconf_zname;
  1201.       azmachine[1] = NULL;
  1202.       sperm.pzmachine = azmachine;
  1203.       if (q->uuconf_fsend_request >= 0)
  1204.     sperm.frequest = q->uuconf_fsend_request;
  1205.       if (q->uuconf_pzremote_send != (char **) &_uuconf_unset
  1206.       && q->uuconf_pzremote_send != NULL)
  1207.     sperm.pzread = q->uuconf_pzremote_send;
  1208.       if (q->uuconf_pzremote_receive != (char **) &_uuconf_unset
  1209.       && q->uuconf_pzremote_receive != NULL)
  1210.     sperm.pzwrite = q->uuconf_pzremote_receive;
  1211.       if (q->uuconf_pzcmds != (char **) &_uuconf_unset
  1212.       && q->uuconf_pzcmds != NULL)
  1213.     sperm.pzcommands = q->uuconf_pzcmds;
  1214.       if (q->uuconf_zlocalname != (char *) &_uuconf_unset
  1215.       && q->uuconf_zlocalname != NULL)
  1216.     sperm.zmyname = q->uuconf_zlocalname;
  1217.       if (q->uuconf_zpubdir != (char *) &_uuconf_unset
  1218.       && q->uuconf_zpubdir != NULL)
  1219.     sperm.zpubdir = q->uuconf_zpubdir;
  1220.       if (q->uuconf_pzalias != (char **) &_uuconf_unset
  1221.       && q->uuconf_pzalias != NULL)
  1222.     sperm.pzalias = q->uuconf_pzalias;
  1223.  
  1224.       if (q->uuconf_fcalled
  1225.       && q->uuconf_zcalled_login != (char *) &_uuconf_unset
  1226.       && q->uuconf_zcalled_login != NULL)
  1227.     {
  1228.       azlogname[0] = q->uuconf_zcalled_login;
  1229.       azlogname[1] = NULL;
  1230.       sperm.pzlogname = azlogname;
  1231.       if (q->uuconf_fcalled_transfer >= 0)
  1232.         sperm.fsendfiles = q->uuconf_fcalled_transfer;
  1233.       if (q->uuconf_fcallback >= 0)
  1234.         sperm.fcallback = q->uuconf_fcallback;
  1235.       sperm.pzvalidate = azmachine;
  1236.     }
  1237.  
  1238.       uvadd_perm (&sperm);
  1239.     }
  1240.  
  1241.   /* Now add a Permissions entry for each alternative that is not used
  1242.      for calling out.  */
  1243.   for (q = qsys; q != NULL; q = q->uuconf_qalternate)
  1244.     {
  1245.       if (! q->uuconf_fcalled || q->uuconf_fcall)
  1246.     continue;
  1247.  
  1248.       sperm.qnext = NULL;
  1249.       sperm.pzlogname = NULL;
  1250.       sperm.pzmachine = NULL;
  1251.       sperm.frequest = -1;
  1252.       sperm.fsendfiles = -1;
  1253.       sperm.pzread = NULL;
  1254.       sperm.pzwrite = NULL;
  1255.       sperm.fcallback = -1;
  1256.       sperm.pzcommands = NULL;
  1257.       sperm.pzvalidate = NULL;
  1258.       sperm.zmyname = NULL;
  1259.       sperm.zpubdir = NULL;
  1260.       sperm.pzalias = NULL;
  1261.  
  1262.       if (q->uuconf_zcalled_login != (char *) &_uuconf_unset
  1263.       && q->uuconf_zcalled_login != NULL)
  1264.     azlogname[0] = q->uuconf_zcalled_login;
  1265.       else
  1266.     azlogname[0] = (char *) "OTHER";
  1267.       azlogname[1] = NULL;
  1268.       sperm.pzlogname = azlogname;
  1269.  
  1270.       if (q->uuconf_fsend_request >= 0)
  1271.     sperm.frequest = q->uuconf_fsend_request;
  1272.       if (q->uuconf_fcalled_transfer >= 0)
  1273.     sperm.fsendfiles = q->uuconf_fcalled_transfer;
  1274.       if (q->uuconf_pzremote_send != (char **) &_uuconf_unset
  1275.       && q->uuconf_pzremote_send != NULL)
  1276.     sperm.pzread = q->uuconf_pzremote_send;
  1277.       if (q->uuconf_pzremote_receive != (char **) &_uuconf_unset
  1278.       && q->uuconf_pzremote_receive != NULL)
  1279.     sperm.pzwrite = q->uuconf_pzremote_receive;
  1280.       if (q->uuconf_fcallback >= 0)
  1281.     sperm.fcallback = q->uuconf_fcallback;
  1282.       if (q->uuconf_zlocalname != (char *) &_uuconf_unset
  1283.       && q->uuconf_zlocalname != NULL)
  1284.     sperm.zmyname = q->uuconf_zlocalname;
  1285.       if (q->uuconf_zpubdir != (char *) &_uuconf_unset
  1286.       && q->uuconf_zpubdir != NULL)
  1287.     sperm.zpubdir = q->uuconf_zpubdir;
  1288.  
  1289.       uvadd_perm (&sperm);
  1290.     }
  1291. }
  1292.  
  1293. /* Compare two strings from a Permissions entry, returning TRUE if
  1294.    they are the same.  */
  1295.  
  1296. static boolean
  1297. fvperm_string_cmp (z1, z2)
  1298.      const char *z1;
  1299.      const char *z2;
  1300. {
  1301.   if (z1 == NULL)
  1302.     return z2 == NULL;
  1303.  
  1304.   if (z2 == NULL)
  1305.     return FALSE;
  1306.  
  1307.   return strcmp (z1, z2) == 0;
  1308. }
  1309.  
  1310. /* Compare two arrays of strings from a Permissions entry, returning
  1311.    TRUE if they are the same.  */
  1312.  
  1313. static boolean
  1314. fvperm_array_cmp (pz1, pz2)
  1315.      const char **pz1;
  1316.      const char **pz2;
  1317. {
  1318.   if (pz1 == NULL)
  1319.     return pz2 == NULL;
  1320.  
  1321.   if (pz2 == NULL)
  1322.     return FALSE;
  1323.  
  1324.   for (; *pz1 != NULL && *pz2 != NULL; pz1++, pz2++)
  1325.     if (strcmp (*pz1, *pz2) != 0)
  1326.       break;
  1327.  
  1328.   return *pz1 == NULL && *pz2 == NULL;
  1329. }      
  1330.  
  1331. /* Add a Permissions entry to a global list, combining entries where
  1332.    possible.  */
  1333.  
  1334. static void
  1335. uvadd_perm (qadd)
  1336.      struct shpermissions *qadd;
  1337. {
  1338.   struct shpermissions *qlook;
  1339.   struct shpermissions *qnew;
  1340.   int iret;
  1341.  
  1342.   /* If there's no information, don't bother to add this entry.  */
  1343.   if (qadd->pzlogname == NULL
  1344.       && qadd->frequest < 0
  1345.       && qadd->fsendfiles < 0
  1346.       && qadd->pzread == NULL
  1347.       && qadd->pzwrite == NULL
  1348.       && qadd->fcallback < 0
  1349.       && qadd->pzcommands == NULL
  1350.       && qadd->pzvalidate == NULL
  1351.       && qadd->zmyname == NULL
  1352.       && qadd->zpubdir == NULL
  1353.       && qadd->pzalias == NULL)
  1354.     return;
  1355.  
  1356.   for (qlook = qVperms; qlook != NULL; qlook = qlook->qnext)
  1357.     {
  1358.       /* See if we can merge qadd into qlook.  */
  1359.       if (qadd->pzlogname == NULL
  1360.       ? qlook->pzlogname != NULL
  1361.       : qlook->pzlogname == NULL)
  1362.     continue;
  1363.       if (qadd->pzmachine == NULL
  1364.       ? qlook->pzmachine != NULL
  1365.       : qlook->pzmachine == NULL)
  1366.     continue;
  1367.       if (qadd->frequest != qlook->frequest
  1368.       || qadd->fsendfiles != qlook->fsendfiles
  1369.       || qadd->fcallback != qlook->fcallback)
  1370.     continue;
  1371.       if (! fvperm_string_cmp (qadd->zmyname, qlook->zmyname)
  1372.       || ! fvperm_string_cmp (qadd->zpubdir, qlook->zpubdir))
  1373.     continue;
  1374.       if (! fvperm_array_cmp ((const char **) qadd->pzread,
  1375.                   (const char **) qlook->pzread)
  1376.       || ! fvperm_array_cmp ((const char **)  qadd->pzwrite,
  1377.                  (const char **) qlook->pzwrite)
  1378.       || ! fvperm_array_cmp ((const char **) qadd->pzcommands,
  1379.                  (const char **) qlook->pzcommands))
  1380.     continue;
  1381.  
  1382.       /* Merge qadd into qlook.  */
  1383.       if (qadd->pzmachine != NULL)
  1384.     {
  1385.       iret = _uuconf_iadd_string ((struct sglobal *) NULL,
  1386.                       qadd->pzmachine[0], FALSE,
  1387.                       TRUE, &qlook->pzmachine,
  1388.                       (pointer) NULL);
  1389.       if (iret != UUCONF_SUCCESS)
  1390.         uvuuconf_error ((pointer) NULL, iret);
  1391.     }
  1392.       if (qadd->pzlogname != NULL)
  1393.     {
  1394.       iret = _uuconf_iadd_string ((struct sglobal *) NULL,
  1395.                       qadd->pzlogname[0], FALSE,
  1396.                       TRUE, &qlook->pzlogname,
  1397.                       (pointer) NULL);
  1398.       if (iret != UUCONF_SUCCESS)
  1399.         uvuuconf_error ((pointer) NULL, iret);
  1400.     }
  1401.       if (qadd->pzalias != NULL)
  1402.     {
  1403.       char **pz;
  1404.  
  1405.       for (pz = qadd->pzalias; *pz != NULL; pz++)
  1406.         {
  1407.           iret = _uuconf_iadd_string ((struct sglobal *) NULL,
  1408.                       *pz, FALSE, TRUE,
  1409.                       &qlook->pzalias, (pointer) NULL);
  1410.           if (iret != UUCONF_SUCCESS)
  1411.         uvuuconf_error ((pointer) NULL, iret);
  1412.         }
  1413.     }
  1414.  
  1415.       return;
  1416.     }
  1417.  
  1418.   /* We must add qadd as a new entry on the list, which means we must
  1419.      copy it into the heap.  */
  1420.  
  1421.   qnew = (struct shpermissions *) malloc (sizeof (struct shpermissions));
  1422.   if (qnew == NULL)
  1423.     uvuuconf_error ((pointer) NULL, UUCONF_MALLOC_FAILED);
  1424.   *qnew = *qadd;
  1425.   if (qadd->pzmachine != NULL)
  1426.     {
  1427.       qnew->pzmachine = NULL;
  1428.       iret = _uuconf_iadd_string ((struct sglobal *) NULL,
  1429.                   qadd->pzmachine[0], FALSE,
  1430.                   FALSE, &qnew->pzmachine,
  1431.                   (pointer) NULL);
  1432.       if (iret != UUCONF_SUCCESS)
  1433.     uvuuconf_error ((pointer) NULL, iret);
  1434.     }
  1435.   if (qadd->pzlogname != NULL)
  1436.     {
  1437.       qnew->pzlogname = NULL;
  1438.       iret = _uuconf_iadd_string ((struct sglobal *) NULL,
  1439.                   qadd->pzlogname[0], FALSE,
  1440.                   FALSE, &qnew->pzlogname,
  1441.                   (pointer) NULL);
  1442.       if (iret != UUCONF_SUCCESS)
  1443.     uvuuconf_error ((pointer) NULL, iret);
  1444.     }
  1445.   if (qadd->pzvalidate != NULL)
  1446.     qnew->pzvalidate = qnew->pzmachine;
  1447.  
  1448.   qnew->qnext = qVperms;
  1449.   qVperms = qnew;
  1450. }
  1451.  
  1452. /* Write out the Permissions entries.  */
  1453.  
  1454. static void
  1455. uvwrite_perms ()
  1456. {
  1457.   char ab[sizeof ZCURDIR + sizeof HDB_PERMISSIONS - 1];
  1458.   FILE *e;
  1459.   struct shpermissions *q;
  1460.  
  1461.   sprintf (ab, "%s%s", ZCURDIR, HDB_PERMISSIONS);
  1462.   e = fopen (ab, "w");
  1463.   if (e == NULL)
  1464.     {
  1465.       fprintf (stderr, "uuchk:%s: ", ab);
  1466.       perror ("fopen");
  1467.       exit (EXIT_FAILURE);
  1468.     }
  1469.  
  1470.   fprintf (e, "# Permissions file automatically generated by uuconv.\n");
  1471.  
  1472.   for (q = qVperms; q != NULL; q = q->qnext)
  1473.     {
  1474.       size_t ccol;
  1475.  
  1476.       ccol = 0;
  1477.       uvwrite_perm_array (e, (const char **) q->pzlogname, "LOGNAME", &ccol);
  1478.       uvwrite_perm_array (e, (const char **) q->pzmachine, "MACHINE", &ccol);
  1479.       uvwrite_perm_boolean (e, q->frequest, "REQUEST", &ccol, FALSE);
  1480.       uvwrite_perm_boolean (e, q->fsendfiles, "SENDFILES", &ccol, TRUE);
  1481.       uvwrite_perm_rw_array (e, (const char **) q->pzread, "READ", &ccol);
  1482.       uvwrite_perm_rw_array (e, (const char **) q->pzwrite, "WRITE", &ccol);
  1483.       uvwrite_perm_boolean (e, q->fcallback, "CALLBACK", &ccol, FALSE);
  1484.       uvwrite_perm_array (e, (const char **) q->pzcommands, "COMMANDS",
  1485.               &ccol);
  1486.       uvwrite_perm_array (e, (const char **) q->pzvalidate, "VALIDATE",
  1487.               &ccol);
  1488.       uvwrite_perm_string (e, q->zmyname, "MYNAME", &ccol);
  1489.       uvwrite_perm_string (e, q->zpubdir, "PUBDIR", &ccol);
  1490.       uvwrite_perm_array (e, (const char **) q->pzalias, "ALIAS", &ccol);
  1491.  
  1492.       fprintf (e, "\n");
  1493.     }
  1494.  
  1495.   if (ferror (e)
  1496.       || fclose (e) == EOF)
  1497.     {
  1498.       fprintf (stderr, "uuchk:%s: error during output\n", HDB_PERMISSIONS);
  1499.       exit (EXIT_FAILURE);
  1500.     }
  1501. }
  1502.  
  1503. /* Write an array out to the Permissions file.  */
  1504.  
  1505. static void
  1506. uvwrite_perm_array (e, pzarg, zcmd, pccol)
  1507.      FILE *e;
  1508.      const char **pzarg;
  1509.      const char *zcmd;
  1510.      size_t *pccol;
  1511. {
  1512.   size_t c;
  1513.   const char **pz;
  1514.  
  1515.   if (pzarg == NULL)
  1516.     return;
  1517.  
  1518.   c = strlen (zcmd) + 1;
  1519.   
  1520.   for (pz = pzarg; *pz != NULL; pz++)
  1521.     c += strlen (*pz) + 1;
  1522.  
  1523.   if (*pccol > 20 && c + *pccol > 75)
  1524.     {
  1525.       fprintf (e, " \\\n");
  1526.       *pccol = c - 1;
  1527.     }
  1528.   else
  1529.     {
  1530.       if (*pccol != 0)
  1531.     fprintf (e, " ");
  1532.       *pccol += c;
  1533.     }
  1534.  
  1535.   fprintf (e, "%s=", zcmd);
  1536.   for (pz = pzarg; *pz != NULL; pz++)
  1537.     {
  1538.       if (pz != pzarg)
  1539.     fprintf (e, ":");
  1540.       fprintf (e, "%s", *pz);
  1541.     }
  1542. }
  1543.  
  1544. /* Write a boolean value out to the Permissions file.  This may be
  1545.    either a yes/no boolean or a yes/call boolean (the latter is for
  1546.    SENDFILES).  */
  1547.  
  1548. static void
  1549. uvwrite_perm_boolean (e, f, zcmd, pccol, fsendfiles)
  1550.      FILE *e;
  1551.      int f;
  1552.      const char *zcmd;
  1553.      size_t *pccol;
  1554.      boolean fsendfiles;
  1555. {
  1556.   const char *az[2];
  1557.  
  1558.   if (f < 0)
  1559.     return;
  1560.  
  1561.   if (f)
  1562.     az[0] = "yes";
  1563.   else
  1564.     az[0] = fsendfiles ? "call" : "no";
  1565.   az[1] = NULL;
  1566.  
  1567.   uvwrite_perm_array (e, az, zcmd, pccol);
  1568. }
  1569.  
  1570. /* Write a set of READ or WRITE entries to the Permissions file.  We
  1571.    have to separate out all entries that start with '!'.  */
  1572.  
  1573. static void
  1574. uvwrite_perm_rw_array (e, pzarg, zcmd, pccol)
  1575.      FILE *e;
  1576.      const char **pzarg;
  1577.      const char *zcmd;
  1578.      size_t *pccol;
  1579. {
  1580.   size_t c;
  1581.   const char **pz, **pzcopy, **pzset;
  1582.  
  1583.   if (pzarg == NULL)
  1584.     return;
  1585.  
  1586.   c = 0;
  1587.   for (pz = pzarg; *pz != NULL; pz++)
  1588.     c++;
  1589.  
  1590.   pzcopy = (const char **) malloc ((c + 1) * sizeof (char *));
  1591.   if (pzcopy == NULL)
  1592.     uvuuconf_error ((pointer) NULL, UUCONF_MALLOC_FAILED);
  1593.  
  1594.   pzset = pzcopy;
  1595.   for (pz = pzarg; *pz != NULL; pz++)
  1596.     if ((*pz)[0] != '!')
  1597.       *pzset++ = *pz;
  1598.   *pzset = NULL;
  1599.  
  1600.   if (pzset != pzcopy)
  1601.     uvwrite_perm_array (e, (const char **) pzcopy, zcmd, pccol);
  1602.  
  1603.   pzset = pzcopy;
  1604.   for (pz = pzarg; *pz != NULL; pz++)
  1605.     if ((*pz)[0] == '!')
  1606.       *pzset++ = *pz;
  1607.   *pzset = NULL;
  1608.  
  1609.   if (pzset != pzcopy)
  1610.     {
  1611.       char ab[20];
  1612.  
  1613.       sprintf (ab, "NO%s", zcmd);
  1614.       uvwrite_perm_array (e, (const char **) pzcopy, ab, pccol);
  1615.     }
  1616. }
  1617.  
  1618. /* Write a string out to the Permissions file.  */
  1619.  
  1620. static void
  1621. uvwrite_perm_string (e, z, zcmd, pccol)
  1622.      FILE *e;
  1623.      const char *z;
  1624.      const char *zcmd;
  1625.      size_t *pccol;
  1626. {
  1627.   const char *az[2];
  1628.  
  1629.   if (z == NULL)
  1630.     return;
  1631.  
  1632.   az[0] = z;
  1633.   az[1] = NULL;
  1634.  
  1635.   uvwrite_perm_array (e, az, zcmd, pccol);
  1636. }
  1637.  
  1638. /* Write out a Taylor UUCP port.  This is called via uuconf_find_port;
  1639.    the pinfo argument is the port file.  */
  1640.  
  1641. static int
  1642. ivwrite_taylor_port (qport, pinfo)
  1643.      struct uuconf_port *qport;
  1644.      pointer pinfo;
  1645. {
  1646.   FILE *e = (FILE *) pinfo;
  1647.  
  1648.   fprintf (e, "port %s\n", qport->uuconf_zname);
  1649.  
  1650.   uvwrite_taylor_port (e, qport, "");
  1651.  
  1652.   /* Return UUCONF_NOT_FOUND to force uuconf_find_port to keep looking
  1653.      for ports.  */
  1654.   return UUCONF_NOT_FOUND;
  1655. }
  1656.  
  1657. /* Write a port out to a Taylor UUCP configuration file.  This doesn't
  1658.    output the name, since it is called to output a specially defined
  1659.    port in the sys file.  */
  1660.  
  1661. static void
  1662. uvwrite_taylor_port (e, qport, zprefix)
  1663.      FILE *e;
  1664.      struct uuconf_port *qport;
  1665.      const char *zprefix;
  1666. {
  1667.   const char *ztype;
  1668.   char ab[100];
  1669.  
  1670.   switch (qport->uuconf_ttype)
  1671.     {
  1672.     default:
  1673.     case UUCONF_PORTTYPE_UNKNOWN:
  1674.       fprintf (stderr, "uuconv: Bad port type\n");
  1675.       exit (EXIT_FAILURE);
  1676.       break;
  1677.     case UUCONF_PORTTYPE_STDIN:
  1678.       ztype = "stdin";
  1679.       break;
  1680.     case UUCONF_PORTTYPE_MODEM:
  1681.       ztype = "modem";
  1682.       break;
  1683.     case UUCONF_PORTTYPE_DIRECT:
  1684.       ztype = "direct";
  1685.       break;
  1686.     case UUCONF_PORTTYPE_TCP:
  1687.       ztype = "tcp";
  1688.       break;
  1689.     case UUCONF_PORTTYPE_TLI:
  1690.       ztype = "tli";
  1691.       break;
  1692.     case UUCONF_PORTTYPE_PIPE:
  1693.       ztype = "pipe";
  1694.       break;
  1695.     }
  1696.  
  1697.   fprintf (e, "%stype %s\n", zprefix, ztype);
  1698.  
  1699.   if (qport->uuconf_zprotocols != NULL)
  1700.     fprintf (e, "%sprotocol %s\n", zprefix, qport->uuconf_zprotocols);
  1701.  
  1702.   if (qport->uuconf_qproto_params != NULL)
  1703.     uvwrite_proto_params (e, qport->uuconf_qproto_params, zprefix);
  1704.  
  1705.   if ((qport->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
  1706.     {
  1707.       sprintf (ab, "%sseven-bit", zprefix);
  1708.       uvwrite_boolean (e,
  1709.                ((qport->uuconf_ireliable & UUCONF_RELIABLE_EIGHT)
  1710.             == 0),
  1711.                ab);
  1712.       sprintf (ab, "%sreliable", zprefix);
  1713.       uvwrite_boolean (e,
  1714.                ((qport->uuconf_ireliable & UUCONF_RELIABLE_RELIABLE)
  1715.             != 0),
  1716.                ab);
  1717.       sprintf (ab, "%shalf-duplex", zprefix);
  1718.       uvwrite_boolean (e,
  1719.                ((qport->uuconf_ireliable & UUCONF_RELIABLE_FULLDUPLEX)
  1720.             == 0),
  1721.                ab);
  1722.     }
  1723.  
  1724.   if (qport->uuconf_zlockname != NULL)
  1725.     fprintf (e, "%slockname %s\n", zprefix, qport->uuconf_zlockname);
  1726.  
  1727.   switch (qport->uuconf_ttype)
  1728.     {
  1729.     default:
  1730.       break;
  1731.     case UUCONF_PORTTYPE_MODEM:
  1732.       {
  1733.     struct uuconf_modem_port *qm;
  1734.  
  1735.     qm = &qport->uuconf_u.uuconf_smodem;
  1736.     if (qm->uuconf_zdevice != NULL)
  1737.       fprintf (e, "%sdevice %s\n", zprefix, qm->uuconf_zdevice);
  1738.     if (qm->uuconf_zdial_device != NULL)
  1739.       fprintf (e, "%sdial-device %s\n", zprefix, qm->uuconf_zdial_device);
  1740.     if (qm->uuconf_ibaud != 0)
  1741.       fprintf (e, "%sbaud %ld\n", zprefix, qm->uuconf_ibaud);
  1742.     if (qm->uuconf_ilowbaud != 0)
  1743.       fprintf (e, "%sbaud-range %ld %ld\n", zprefix, qm->uuconf_ilowbaud,
  1744.            qm->uuconf_ihighbaud);
  1745.     if (! qm->uuconf_fcarrier)
  1746.       fprintf (e, "%scarrier false\n", zprefix);
  1747.     if (! qm->uuconf_fhardflow)
  1748.       fprintf (e, "%shardflow false\n", zprefix);
  1749.     if (qm->uuconf_pzdialer != NULL)
  1750.       {
  1751.         if (qm->uuconf_pzdialer[1] == NULL)
  1752.           fprintf (e, "%sdialer %s\n", zprefix, qm->uuconf_pzdialer[0]);
  1753.         else
  1754.           {
  1755.         sprintf (ab, "%sdialer-sequence", zprefix);
  1756.         uvwrite_string_array (e, qm->uuconf_pzdialer, ab);
  1757.           }
  1758.       }
  1759.     if (qm->uuconf_qdialer != NULL)
  1760.       {
  1761.         sprintf (ab, "%sdialer ", zprefix);
  1762.         uvwrite_taylor_dialer (e, qm->uuconf_qdialer, ab);
  1763.       }
  1764.       }
  1765.       break;
  1766.     case UUCONF_PORTTYPE_DIRECT:
  1767.       {
  1768.     struct uuconf_direct_port *qd;
  1769.  
  1770.     qd = &qport->uuconf_u.uuconf_sdirect;
  1771.     if (qd->uuconf_zdevice != NULL)
  1772.       fprintf (e, "%sdevice %s\n", zprefix, qd->uuconf_zdevice);
  1773.     if (qd->uuconf_ibaud != 0)
  1774.       fprintf (e, "%sbaud %ld\n", zprefix, qd->uuconf_ibaud);
  1775.     if (qd->uuconf_fcarrier)
  1776.       fprintf (e, "%scarrier true\n", zprefix);
  1777.     if (! qd->uuconf_fhardflow)
  1778.       fprintf (e, "%shardflow false\n", zprefix);
  1779.       }
  1780.       break;
  1781.     case UUCONF_PORTTYPE_TCP:
  1782.       if (qport->uuconf_u.uuconf_stcp.uuconf_zport != NULL)
  1783.     fprintf (e, "%sservice %s\n", zprefix,
  1784.          qport->uuconf_u.uuconf_stcp.uuconf_zport);
  1785.       if (qport->uuconf_u.uuconf_stcp.uuconf_pzdialer != NULL)
  1786.     {
  1787.       sprintf (ab, "%sdialer-sequence", zprefix);
  1788.       uvwrite_string_array (e,
  1789.                 qport->uuconf_u.uuconf_stcp.uuconf_pzdialer,
  1790.                 ab);
  1791.     }
  1792.       break;
  1793.     case UUCONF_PORTTYPE_TLI:
  1794.       {
  1795.     struct uuconf_tli_port *qt;
  1796.  
  1797.     qt = &qport->uuconf_u.uuconf_stli;
  1798.     if (qt->uuconf_zdevice != NULL)
  1799.       fprintf (e, "%sdevice %s\n", zprefix, qt->uuconf_zdevice);
  1800.     sprintf (ab, "%sstream", zprefix);
  1801.     uvwrite_boolean (e, qt->uuconf_fstream, ab);
  1802.     if (qt->uuconf_pzpush != NULL)
  1803.       {
  1804.         sprintf (ab, "%spush", zprefix);
  1805.         uvwrite_string_array (e, qt->uuconf_pzpush, ab);
  1806.       }
  1807.     if (qt->uuconf_pzdialer != NULL)
  1808.       {
  1809.         sprintf (ab, "%sdialer-sequence", zprefix);
  1810.         uvwrite_string_array (e, qt->uuconf_pzdialer, ab);
  1811.       }
  1812.     if (qt->uuconf_zservaddr != NULL)
  1813.       fprintf (e, "%sserver-address %s\n", zprefix,
  1814.            qt->uuconf_zservaddr);
  1815.       }
  1816.       break;
  1817.     case UUCONF_PORTTYPE_PIPE:
  1818.       {
  1819.     struct uuconf_pipe_port *qp;
  1820.  
  1821.     qp = &qport->uuconf_u.uuconf_spipe;
  1822.     if (qp->uuconf_pzcmd != NULL)
  1823.       {
  1824.         sprintf (ab, "%scommad", zprefix);
  1825.         uvwrite_string_array (e, qp->uuconf_pzcmd, ab);
  1826.       }
  1827.       }
  1828.       break;
  1829.     }
  1830. }
  1831.  
  1832. /* Write out a port to the V2 L-devices file.  This is called via
  1833.    uuconf_find_port.  */
  1834.  
  1835. static int
  1836. ivwrite_v2_port (qport, pinfo)
  1837.      struct uuconf_port *qport;
  1838.      pointer pinfo;
  1839. {
  1840.   FILE *e = (FILE *) pinfo;
  1841.  
  1842.   if (qport->uuconf_ttype == UUCONF_PORTTYPE_DIRECT)
  1843.     {
  1844.       fprintf (e, "DIR %s - %ld direct",
  1845.            qport->uuconf_u.uuconf_sdirect.uuconf_zdevice,
  1846.            qport->uuconf_u.uuconf_sdirect.uuconf_ibaud);
  1847.     }
  1848.   else if (qport->uuconf_ttype == UUCONF_PORTTYPE_MODEM)
  1849.     {
  1850.       fprintf (e, "%s %s ", qport->uuconf_zname,
  1851.            qport->uuconf_u.uuconf_smodem.uuconf_zdevice);
  1852.       if (qport->uuconf_u.uuconf_smodem.uuconf_zdial_device != NULL)
  1853.     fprintf (e, "%s", qport->uuconf_u.uuconf_smodem.uuconf_zdial_device);
  1854.       else
  1855.     fprintf (e, "-");
  1856.       fprintf (e, " ");
  1857.       if (qport->uuconf_u.uuconf_smodem.uuconf_ilowbaud != 0L)
  1858.     fprintf (e, "%ld-%ld",
  1859.          qport->uuconf_u.uuconf_smodem.uuconf_ilowbaud,
  1860.          qport->uuconf_u.uuconf_smodem.uuconf_ihighbaud);
  1861.       else if (qport->uuconf_u.uuconf_smodem.uuconf_ibaud != 0L)
  1862.     fprintf (e, "%ld", qport->uuconf_u.uuconf_smodem.uuconf_ibaud);
  1863.       else
  1864.     fprintf (e, "Any");
  1865.       if (qport->uuconf_u.uuconf_smodem.uuconf_pzdialer != NULL)
  1866.     fprintf (e, " %s",
  1867.          qport->uuconf_u.uuconf_smodem.uuconf_pzdialer[0]);
  1868.     }
  1869.   else
  1870.     {
  1871.       fprintf (e, "# Ignoring port %s with unsupported type",
  1872.            qport->uuconf_zname);
  1873.     }
  1874.  
  1875.   fprintf (e, "\n");
  1876.  
  1877.   /* Return UUCONF_NOT_FOUND to force uuconf_find_port to keep looking
  1878.      for a port.  */
  1879.   return UUCONF_NOT_FOUND;
  1880. }
  1881.  
  1882. /* Write out a port to the HDB Devices file.  This is called via
  1883.    uuconf_find_port.  */
  1884.  
  1885. static int
  1886. ivwrite_hdb_port (qport, pinfo)
  1887.      struct uuconf_port *qport;
  1888.      pointer pinfo;
  1889. {
  1890.   FILE *e = (FILE *) pinfo;
  1891.  
  1892.   if (qport->uuconf_ttype == UUCONF_PORTTYPE_DIRECT)
  1893.     {
  1894.       fprintf (e, "Direct");
  1895.       if (qport->uuconf_zprotocols != NULL)
  1896.     fprintf (e, ",%s", qport->uuconf_zprotocols);
  1897.       fprintf (e, " ");
  1898.       if (qport->uuconf_u.uuconf_sdirect.uuconf_zdevice != NULL)
  1899.     fprintf (e, "%s", qport->uuconf_u.uuconf_sdirect.uuconf_zdevice);
  1900.       else
  1901.     fprintf (e, "%s", qport->uuconf_zname);
  1902.       fprintf (e, " - %ld", qport->uuconf_u.uuconf_sdirect.uuconf_ibaud);
  1903.     }
  1904.   else if (qport->uuconf_ttype == UUCONF_PORTTYPE_MODEM)
  1905.     {
  1906.       fprintf (e, "%s", qport->uuconf_zname);
  1907.       if (qport->uuconf_zprotocols != NULL)
  1908.     fprintf (e, ",%s", qport->uuconf_zprotocols);
  1909.       fprintf (e, " ");
  1910.       if (qport->uuconf_u.uuconf_smodem.uuconf_zdevice != NULL)
  1911.     fprintf (e, "%s", qport->uuconf_u.uuconf_smodem.uuconf_zdevice);
  1912.       else
  1913.     fprintf (e, "%s", qport->uuconf_zname);
  1914.       fprintf (e, " ");
  1915.       if (qport->uuconf_u.uuconf_smodem.uuconf_zdial_device != NULL)
  1916.     fprintf (e, "%s", qport->uuconf_u.uuconf_smodem.uuconf_zdial_device);
  1917.       else
  1918.     fprintf (e, "-");
  1919.       fprintf (e, " ");
  1920.       if (qport->uuconf_u.uuconf_smodem.uuconf_ilowbaud != 0L)
  1921.     fprintf (e, "%ld-%ld",
  1922.          qport->uuconf_u.uuconf_smodem.uuconf_ilowbaud,
  1923.          qport->uuconf_u.uuconf_smodem.uuconf_ihighbaud);
  1924.       else if (qport->uuconf_u.uuconf_smodem.uuconf_ibaud != 0L)
  1925.     fprintf (e, "%ld", qport->uuconf_u.uuconf_smodem.uuconf_ibaud);
  1926.       else
  1927.     fprintf (e, "Any");
  1928.       if (qport->uuconf_u.uuconf_smodem.uuconf_pzdialer != NULL)
  1929.     {
  1930.       char **pz;
  1931.  
  1932.       for (pz = qport->uuconf_u.uuconf_smodem.uuconf_pzdialer;
  1933.            *pz != NULL;
  1934.            pz++)
  1935.         fprintf (e, " %s", *pz);
  1936.     }
  1937.     }
  1938.   else if (qport->uuconf_ttype == UUCONF_PORTTYPE_TCP)
  1939.     {
  1940.       char **pz;
  1941.  
  1942.       fprintf (e, "TCP");
  1943.       if (qport->uuconf_zprotocols != NULL)
  1944.     fprintf (e, ",%s", qport->uuconf_zprotocols);
  1945.       fprintf (e, " ");
  1946.       if (qport->uuconf_u.uuconf_stcp.uuconf_zport == NULL)
  1947.     fprintf (e, "uucp");
  1948.       else
  1949.     fprintf (e, "%s", qport->uuconf_u.uuconf_stcp.uuconf_zport);
  1950.       fprintf (e, " - -");
  1951.       pz = qport->uuconf_u.uuconf_stcp.uuconf_pzdialer;
  1952.       if (pz != NULL)
  1953.     for (; *pz != NULL; pz++)
  1954.       fprintf (e, " %s", *pz);
  1955.     }
  1956.   else if (qport->uuconf_ttype == UUCONF_PORTTYPE_TLI)
  1957.     {
  1958.       char **pz;
  1959.  
  1960.       fprintf (e, "%s", qport->uuconf_zname);
  1961.       if (qport->uuconf_zprotocols != NULL)
  1962.     fprintf (e, ",%s", qport->uuconf_zprotocols);
  1963.       fprintf (e, " ");
  1964.       if (qport->uuconf_u.uuconf_stli.uuconf_zdevice != NULL)
  1965.     fprintf (e, "%s", qport->uuconf_u.uuconf_smodem.uuconf_zdevice);
  1966.       else
  1967.     fprintf (e, "-");
  1968.       fprintf (e, " - -");
  1969.       pz = qport->uuconf_u.uuconf_stli.uuconf_pzdialer;
  1970.       if (pz == NULL
  1971.       || *pz == NULL
  1972.       || (strcmp (*pz, "TLI") != 0
  1973.           && strcmp (*pz, "TLIS") != 0))
  1974.     fprintf (e, " TLI%s \\D",
  1975.          qport->uuconf_u.uuconf_stli.uuconf_fstream ? "S" : "");
  1976.       if (pz != NULL)
  1977.     for (; *pz != NULL; pz++)
  1978.       fprintf (e, " %s", *pz);
  1979.     }
  1980.   else
  1981.     {
  1982.       fprintf (e, "# Ignoring port %s with unsupported type",
  1983.            qport->uuconf_zname);
  1984.     }
  1985.  
  1986.   fprintf (e, "\n");
  1987.  
  1988.   /* Return UUCONF_NOT_FOUND to force uuconf_find_port to keep looking
  1989.      for a port.  */
  1990.   return UUCONF_NOT_FOUND;
  1991. }
  1992.  
  1993. /* Write a dialer out to a Taylor UUCP configuration file.  This
  1994.    doesn't output the name, since it is called to output a specially
  1995.    defined dialer in the sys or port file.  */
  1996.  
  1997. static void
  1998. uvwrite_taylor_dialer (e, qdialer, zprefix)
  1999.      FILE *e;
  2000.      struct uuconf_dialer *qdialer;
  2001.      const char *zprefix;
  2002. {
  2003.   char ab[100];
  2004.  
  2005.   /* Reset default values, so we don't output them unnecessarily.  */
  2006.   if (qdialer->uuconf_schat.uuconf_ctimeout == 60)
  2007.     qdialer->uuconf_schat.uuconf_ctimeout = -1;
  2008.   if (qdialer->uuconf_schat.uuconf_fstrip)
  2009.     qdialer->uuconf_schat.uuconf_fstrip = -1;
  2010.   if (qdialer->uuconf_scomplete.uuconf_ctimeout == 60)
  2011.     qdialer->uuconf_scomplete.uuconf_ctimeout = -1;
  2012.   if (qdialer->uuconf_scomplete.uuconf_fstrip)
  2013.     qdialer->uuconf_scomplete.uuconf_fstrip = -1;
  2014.   if (qdialer->uuconf_sabort.uuconf_ctimeout == 60)
  2015.     qdialer->uuconf_sabort.uuconf_ctimeout = -1;
  2016.   if (qdialer->uuconf_sabort.uuconf_fstrip)
  2017.     qdialer->uuconf_sabort.uuconf_fstrip = -1;
  2018.   
  2019.   uvwrite_chat (e, &qdialer->uuconf_schat, (struct uuconf_chat *) NULL,
  2020.         zprefix, FALSE);
  2021.   if (qdialer->uuconf_zdialtone != NULL
  2022.       && strcmp (qdialer->uuconf_zdialtone, ",") != 0)
  2023.     fprintf (e, "%sdialtone %s\n", zprefix, qdialer->uuconf_zdialtone);
  2024.   if (qdialer->uuconf_zpause != NULL
  2025.       && strcmp (qdialer->uuconf_zpause, ",") != 0)
  2026.     fprintf (e, "%spause %s\n", zprefix, qdialer->uuconf_zpause);
  2027.   if (! qdialer->uuconf_fcarrier)
  2028.     fprintf (e, "%scarrier false\n", zprefix);
  2029.   if (qdialer->uuconf_ccarrier_wait != 60)
  2030.     fprintf (e, "%scarrier-wait %d\n", zprefix,
  2031.          qdialer->uuconf_ccarrier_wait);
  2032.   if (qdialer->uuconf_fdtr_toggle)
  2033.     fprintf (e, "%sdtr-toggle %s %s\n", zprefix,
  2034.          qdialer->uuconf_fdtr_toggle ? "true" : "false",
  2035.          qdialer->uuconf_fdtr_toggle_wait ? "true" : "false");
  2036.   sprintf (ab, "%scomplete-", zprefix);
  2037.   uvwrite_chat (e, &qdialer->uuconf_scomplete, (struct uuconf_chat *) NULL,
  2038.         ab, FALSE);
  2039.   sprintf (ab, "%sabort-", zprefix);
  2040.   uvwrite_chat (e, &qdialer->uuconf_sabort, (struct uuconf_chat *) NULL,
  2041.         ab, FALSE);
  2042.   if (qdialer->uuconf_qproto_params != NULL)
  2043.     uvwrite_proto_params (e, qdialer->uuconf_qproto_params, zprefix);
  2044.   if ((qdialer->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
  2045.     {
  2046.       sprintf (ab, "%sseven-bit", zprefix);
  2047.       uvwrite_boolean (e,
  2048.                ((qdialer->uuconf_ireliable & UUCONF_RELIABLE_EIGHT)
  2049.             == 0),
  2050.                ab);
  2051.       sprintf (ab, "%sreliable", zprefix);
  2052.       uvwrite_boolean (e,
  2053.                ((qdialer->uuconf_ireliable & UUCONF_RELIABLE_RELIABLE)
  2054.             != 0),
  2055.                ab);
  2056.       sprintf (ab, "%shalf-duplex", zprefix);
  2057.       uvwrite_boolean (e,
  2058.                ((qdialer->uuconf_ireliable
  2059.              & UUCONF_RELIABLE_FULLDUPLEX) == 0),
  2060.                ab);
  2061.     }
  2062. }
  2063.  
  2064. /* Write a dialer out to an HDB configuration file.  */
  2065.  
  2066. static void
  2067. uvwrite_hdb_dialer (e, qdialer)
  2068.      FILE *e;
  2069.      struct uuconf_dialer *qdialer;
  2070. {
  2071.   fprintf (e, "%s ", qdialer->uuconf_zname);
  2072.  
  2073.   if (qdialer->uuconf_zdialtone != NULL)
  2074.     fprintf (e, "=%c", qdialer->uuconf_zdialtone[0]);
  2075.   if (qdialer->uuconf_zpause != NULL)
  2076.     fprintf (e, "-%c", qdialer->uuconf_zpause[0]);
  2077.  
  2078.   if (qdialer->uuconf_schat.uuconf_pzchat != NULL)
  2079.     {
  2080.       if (qdialer->uuconf_zdialtone == NULL
  2081.       && qdialer->uuconf_zpause == NULL)
  2082.     fprintf (e, "\"\"");
  2083.       fprintf (e, " ");
  2084.       uvwrite_chat_script (e, qdialer->uuconf_schat.uuconf_pzchat);
  2085.     }
  2086.  
  2087.   fprintf (e, "\n");
  2088. }
  2089.  
  2090. /* Display a uuconf error and exit.  */
  2091.  
  2092. static void
  2093. uvuuconf_error (puuconf, iret)
  2094.      pointer puuconf;
  2095.      int iret;
  2096. {
  2097.   char ab[512];
  2098.  
  2099.   (void) uuconf_error_string (puuconf, iret, ab, sizeof ab);
  2100.   if ((iret & UUCONF_ERROR_FILENAME) == 0)
  2101.     fprintf (stderr, "uuconv: %s\n", ab);
  2102.   else
  2103.     fprintf (stderr, "uuconv:%s\n", ab);
  2104.   if (UUCONF_ERROR_VALUE (iret) != UUCONF_FOPEN_FAILED)
  2105.     exit (EXIT_FAILURE);
  2106. }
  2107.