home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / uucp / Uucp.framework / unix.subproj / xqtsub.c < prev   
Encoding:
C/C++ Source or Header  |  1995-10-09  |  14.8 KB  |  712 lines

  1. /* xqtsub.c
  2.    System dependent functions used only by uuxqt.
  3.  
  4.    Copyright (C) 1991, 1992, 1993, 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 "uucp.h"
  27.  
  28. #if USE_RCS_ID
  29. const char xqtsub_rcsid[] = "$Id: xqtsub.c,v 1.18 1995/06/21 20:21:14 ian Rel $";
  30. #endif
  31.  
  32. #include "uudefs.h"
  33. #include "uuconf.h"
  34. #include "system.h"
  35. #include "sysdep.h"
  36.  
  37. #include <ctype.h>
  38. #include <errno.h>
  39.  
  40. #if HAVE_FCNTL_H
  41. #include <fcntl.h>
  42. #else
  43. #if HAVE_SYS_FILE_H
  44. #include <sys/file.h>
  45. #endif
  46. #endif
  47.  
  48. #ifndef O_RDONLY
  49. #define O_RDONLY 0
  50. #define O_WRONLY 1
  51. #define O_RDWR 2
  52. #endif
  53.  
  54. #ifndef O_NOCTTY
  55. #define O_NOCTTY 0
  56. #endif
  57.  
  58. #ifndef FD_CLOEXEC
  59. #define FD_CLOEXEC 1
  60. #endif
  61.  
  62. #if HAVE_OPENDIR
  63. #if HAVE_DIRENT_H
  64. #include <dirent.h>
  65. #else /* ! HAVE_DIRENT_H */
  66. #include <sys/dir.h>
  67. #define dirent direct
  68. #endif /* ! HAVE_DIRENT_H */
  69. #endif /* HAVE_OPENDIR */
  70.  
  71. /* Get a value for EX_TEMPFAIL.  */
  72.  
  73. #if HAVE_SYSEXITS_H
  74. #include <sysexits.h>
  75. #endif
  76.  
  77. #ifndef EX_TEMPFAIL
  78. #define EX_TEMPFAIL 75
  79. #endif
  80.  
  81. /* Get the full pathname of the command to execute, given the list of
  82.    permitted commands and the allowed path.  */
  83.  
  84. char *
  85. zsysdep_find_command (zcmd, pzcmds, pzpath, pferr)
  86.      const char *zcmd;
  87.      char **pzcmds;
  88.      char **pzpath;
  89.      boolean *pferr;
  90. {
  91.   char **pz;
  92.   struct stat s;
  93.  
  94.   *pferr = FALSE;
  95.  
  96.   for (pz = pzcmds; *pz != NULL; pz++)
  97.     {
  98.       char *zslash;
  99.  
  100.       if (strcmp (*pz, "ALL") == 0)
  101.     break;
  102.  
  103.       zslash = strrchr (*pz, '/');
  104.       if (zslash != NULL)
  105.     ++zslash;
  106.       else
  107.     zslash = *pz;
  108.       if (strcmp (zslash, zcmd) == 0
  109.       || strcmp (*pz, zcmd) == 0)
  110.     {
  111.       /* If we already have an absolute path, we can get out
  112.          immediately.  */
  113.       if (**pz == '/')
  114.         {
  115.           /* Quick error check.  */
  116.           if (stat (*pz, &s) != 0)
  117.         {
  118.           ulog (LOG_ERROR, "%s: %s", *pz, strerror (errno));
  119.           *pferr = TRUE;
  120.           return NULL;
  121.         }
  122.           return zbufcpy (*pz);
  123.         }
  124.       break;
  125.     }
  126.     }
  127.  
  128.   /* If we didn't find this command, get out.  */
  129.   if (*pz == NULL)
  130.     return NULL;
  131.  
  132.   /* We didn't find an absolute pathname, so we must look through
  133.      the path.  */
  134.   for (pz = pzpath; *pz != NULL; pz++)
  135.     {
  136.       char *zname;
  137.  
  138.       zname = zsysdep_in_dir (*pz, zcmd);
  139.       if (stat (zname, &s) == 0)
  140.     return zname;
  141.     }
  142.  
  143.   return NULL;
  144. }
  145.  
  146. /* Expand a local filename for uuxqt.  This is special because uuxqt
  147.    only wants to expand filenames that start with ~ (it does not want
  148.    to prepend the current directory to other names) and if the ~ is
  149.    double, it is turned into a single ~.  This returns NULL to
  150.    indicate that no change was required; it has no way to return
  151.    error.  */
  152.  
  153. char *
  154. zsysdep_xqt_local_file (qsys, zfile)
  155.      const struct uuconf_system *qsys;
  156.      const char *zfile;
  157. {
  158.   if (*zfile != '~')
  159.     return NULL;
  160.   if (zfile[1] == '~')
  161.     {
  162.       size_t clen;
  163.       char *zret;
  164.  
  165.       clen = strlen (zfile);
  166.       zret = zbufalc (clen);
  167.       memcpy (zret, zfile + 1, clen);
  168.       return zret;
  169.     }
  170.   return zsysdep_local_file (zfile, qsys->uuconf_zpubdir,
  171.                  (boolean *) NULL);
  172. }
  173.  
  174. #if ! ALLOW_FILENAME_ARGUMENTS
  175.  
  176. /* Check to see whether an argument specifies a file name; if it does,
  177.    make sure that the file may legally be sent and/or received.  For
  178.    Unix, we do not permit any occurrence of "/../" in the name, nor
  179.    may it start with "../".  Otherwise, if it starts with "/" we check
  180.    against the list of permitted files.  */
  181.  
  182. boolean
  183. fsysdep_xqt_check_file (qsys, zfile)
  184.      const struct uuconf_system *qsys;
  185.      const char *zfile;
  186. {
  187.   size_t clen;
  188.  
  189.   /* Disallow exact "..", prefix "../", suffix "/..", internal "/../",
  190.      and restricted absolute paths.  */
  191.   clen = strlen (zfile);
  192.   if ((clen == sizeof ".." - 1
  193.        && strcmp (zfile, "..") == 0)
  194.       || strncmp (zfile, "../", sizeof "../" - 1) == 0
  195.       || (clen >= sizeof "/.." - 1
  196.       && strcmp (zfile + clen - (sizeof "/.." - 1), "/..") == 0)
  197.       || strstr (zfile, "/../") != NULL
  198.       || (*zfile == '/'
  199.       && (! fin_directory_list (zfile, qsys->uuconf_pzremote_send,
  200.                     qsys->uuconf_zpubdir, TRUE, FALSE,
  201.                     (const char *) NULL)
  202.           || ! fin_directory_list (zfile, qsys->uuconf_pzremote_receive,
  203.                        qsys->uuconf_zpubdir, TRUE, FALSE,
  204.                        (const char *) NULL))))
  205.     {
  206.       ulog (LOG_ERROR, "Not permitted to refer to file \"%s\"", zfile);
  207.       return FALSE;
  208.     }
  209.  
  210.   return TRUE;
  211. }
  212.  
  213. #endif /* ! ALLOW_FILENAME_ARGUMENTS */
  214.  
  215. /* Invoke the command specified by an execute file.  */
  216.  
  217. /*ARGSUSED*/
  218. boolean
  219. fsysdep_execute (qsys, zuser, pazargs, zfullcmd, zinput, zoutput,
  220.          fshell, iseq, pzerror, pftemp)
  221.      const struct uuconf_system *qsys;
  222.      const char *zuser;
  223.      const char **pazargs;
  224.      const char *zfullcmd;
  225.      const char *zinput;
  226.      const char *zoutput;
  227.      boolean fshell;
  228.      int iseq;
  229.      char **pzerror;
  230.      boolean *pftemp;
  231. {
  232.   int aidescs[3];
  233.   boolean ferr;
  234.   pid_t ipid;
  235.   int ierr;
  236.   char abxqtdir[sizeof XQTDIR + 4];
  237.   const char *zxqtdir;
  238.   int istat;
  239.   char *zpath;
  240. #if ALLOW_SH_EXECUTION
  241.   const char *azshargs[4];
  242. #endif
  243.  
  244.   *pzerror = NULL;
  245.   *pftemp = FALSE;
  246.  
  247.   aidescs[0] = SPAWN_NULL;
  248.   aidescs[1] = SPAWN_NULL;
  249.   aidescs[2] = SPAWN_NULL;
  250.  
  251.   ferr = FALSE;
  252.  
  253.   if (zinput != NULL)
  254.     {
  255.       aidescs[0] = open ((char *) zinput, O_RDONLY | O_NOCTTY, 0);
  256.       if (aidescs[0] < 0)
  257.     {
  258.       ulog (LOG_ERROR, "open (%s): %s", zinput, strerror (errno));
  259.       ferr = TRUE;
  260.     }
  261.       else if (fcntl (aidescs[0], F_SETFD,
  262.               fcntl (aidescs[0], F_GETFD, 0) | FD_CLOEXEC) < 0)
  263.     {
  264.       ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno));
  265.       ferr = TRUE;
  266.     }    
  267.     }
  268.   
  269.   if (! ferr && zoutput != NULL)
  270.     {
  271.       aidescs[1] = creat ((char *) zoutput, IPRIVATE_FILE_MODE);
  272.       if (aidescs[1] < 0)
  273.     {
  274.       ulog (LOG_ERROR, "creat (%s): %s", zoutput, strerror (errno));
  275.       *pftemp = TRUE;
  276.       ferr = TRUE;
  277.     }
  278.       else if (fcntl (aidescs[1], F_SETFD,
  279.               fcntl (aidescs[1], F_GETFD, 0) | FD_CLOEXEC) < 0)
  280.     {
  281.       ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno));
  282.       ferr = TRUE;
  283.     }    
  284.     }
  285.  
  286.   if (! ferr)
  287.     {
  288.       *pzerror = zstemp_file (qsys);
  289.       aidescs[2] = creat (*pzerror, IPRIVATE_FILE_MODE);
  290.       if (aidescs[2] < 0)
  291.     {
  292.       if (errno == ENOENT)
  293.         {
  294.           if (! fsysdep_make_dirs (*pzerror, FALSE))
  295.         {
  296.           *pftemp = TRUE;
  297.           ferr = TRUE;
  298.         }
  299.           else
  300.         aidescs[2] = creat (*pzerror, IPRIVATE_FILE_MODE);
  301.         }
  302.       if (! ferr && aidescs[2] < 0)
  303.         {
  304.           ulog (LOG_ERROR, "creat (%s): %s", *pzerror, strerror (errno));
  305.           *pftemp = TRUE;
  306.           ferr = TRUE;
  307.         }
  308.     }
  309.       if (! ferr
  310.       && fcntl (aidescs[2], F_SETFD,
  311.             fcntl (aidescs[2], F_GETFD, 0) | FD_CLOEXEC) < 0)
  312.     {
  313.       ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno));
  314.       ferr = TRUE;
  315.     }    
  316.     }
  317.  
  318.   if (iseq == 0)
  319.     zxqtdir = XQTDIR;
  320.   else
  321.     {
  322.       sprintf (abxqtdir, "%s%04d", XQTDIR, iseq);
  323.       zxqtdir = abxqtdir;
  324.     }
  325.  
  326.   if (ferr)
  327.     {
  328.       if (aidescs[0] != SPAWN_NULL)
  329.     (void) close (aidescs[0]);
  330.       if (aidescs[1] != SPAWN_NULL)
  331.     (void) close (aidescs[1]);
  332.       if (aidescs[2] != SPAWN_NULL)
  333.     (void) close (aidescs[2]);
  334.       ubuffree (*pzerror);
  335.       return FALSE;
  336.     }
  337.  
  338. #if ALLOW_SH_EXECUTION
  339.   if (fshell)
  340.     {
  341.       azshargs[0] = "/bin/sh";
  342.       azshargs[1] = "-c";
  343.       azshargs[2] = zfullcmd;
  344.       azshargs[3] = NULL;
  345.       pazargs = azshargs;
  346.     }
  347. #else
  348.   fshell = FALSE;
  349. #endif
  350.  
  351.   if (qsys->uuconf_pzpath == NULL)
  352.     zpath = NULL;
  353.   else
  354.     {
  355.       size_t c;
  356.       char **pz;
  357.  
  358.       c = 0;
  359.       for (pz = qsys->uuconf_pzpath; *pz != NULL; pz++)
  360.     c += strlen (*pz) + 1;
  361.       zpath = zbufalc (c);
  362.       *zpath = '\0';
  363.       for (pz = qsys->uuconf_pzpath; *pz != NULL; pz++)
  364.     {
  365.       strcat (zpath, *pz);
  366.       if (pz[1] != NULL)
  367.         strcat (zpath, ":");
  368.     }
  369.     }
  370.  
  371.   /* Pass zchdir as zxqtdir, fnosigs as TRUE, fshell as TRUE if we
  372.      aren't already using the shell.  */
  373.   ipid = ixsspawn (pazargs, aidescs, TRUE, FALSE, zxqtdir, TRUE,
  374.            ! fshell, zpath, qsys->uuconf_zname, zuser);
  375.  
  376.   ierr = errno;
  377.  
  378.   ubuffree (zpath);
  379.  
  380.   if (aidescs[0] != SPAWN_NULL)
  381.     (void) close (aidescs[0]);
  382.   if (aidescs[1] != SPAWN_NULL)
  383.     (void) close (aidescs[1]);
  384.   if (aidescs[2] != SPAWN_NULL)
  385.     (void) close (aidescs[2]);
  386.  
  387.   if (ipid < 0)
  388.     {
  389.       ulog (LOG_ERROR, "ixsspawn: %s", strerror (ierr));
  390.       *pftemp = TRUE;
  391.       return FALSE;
  392.     }
  393.  
  394.   istat = ixswait ((unsigned long) ipid, "Execution");
  395.  
  396.   if (istat == EX_TEMPFAIL)
  397.     *pftemp = TRUE;
  398.  
  399.   return istat == 0;
  400. }
  401.  
  402. /* Lock a uuxqt process.  */
  403.  
  404. int
  405. ixsysdep_lock_uuxqt (zcmd, cmaxuuxqts)
  406.      const char *zcmd;
  407.      int cmaxuuxqts;
  408. {
  409.   char ab[sizeof "LCK.XQT.9999"];
  410.   int i;
  411.  
  412.   if (cmaxuuxqts <= 0 || cmaxuuxqts >= 10000)
  413.     cmaxuuxqts = 9999;
  414.   for (i = 0; i < cmaxuuxqts; i++)
  415.     {
  416.       sprintf (ab, "LCK.XQT.%d", i);
  417.       if (fsdo_lock (ab, TRUE, (boolean *) NULL))
  418.     break;
  419.     }
  420.   if (i >= cmaxuuxqts)
  421.     return -1;
  422.  
  423.   if (zcmd != NULL)
  424.     {
  425.       char abcmd[sizeof "LXQ.123456789"];
  426.  
  427.       sprintf (abcmd, "LXQ.%.9s", zcmd);
  428.       abcmd[strcspn (abcmd, " \t/")] = '\0';
  429.       if (! fsdo_lock (abcmd, TRUE, (boolean *) NULL))
  430.     {
  431.       (void) fsdo_unlock (ab, TRUE);
  432.       return -1;
  433.     }
  434.     }
  435.  
  436.   return i;
  437. }
  438.  
  439. /* Unlock a uuxqt process.  */
  440.  
  441. boolean
  442. fsysdep_unlock_uuxqt (iseq, zcmd, cmaxuuxqts)
  443.      int iseq;
  444.      const char *zcmd;
  445.      int cmaxuuxqts;
  446. {
  447.   char ab[sizeof "LCK.XQT.9999"];
  448.   boolean fret;
  449.  
  450.   fret = TRUE;
  451.  
  452.   sprintf (ab, "LCK.XQT.%d", iseq);
  453.   if (! fsdo_unlock (ab, TRUE))
  454.     fret = FALSE;
  455.  
  456.   if (zcmd != NULL)
  457.     {
  458.       char abcmd[sizeof "LXQ.123456789"];
  459.  
  460.       sprintf (abcmd, "LXQ.%.9s", zcmd);
  461.       abcmd[strcspn (abcmd, " \t/")] = '\0';
  462.       if (! fsdo_unlock (abcmd, TRUE))
  463.     fret = FALSE;
  464.     }
  465.  
  466.   return fret;
  467. }
  468.  
  469. /* See whether a particular uuxqt command is locked (this depends on
  470.    the implementation of fsdo_lock).  */
  471.  
  472. boolean
  473. fsysdep_uuxqt_locked (zcmd)
  474.      const char *zcmd;
  475. {
  476.   char ab[sizeof "LXQ.123456789"];
  477.   struct stat s;
  478.  
  479.   sprintf (ab, "LXQ.%.9s", zcmd);
  480.   return stat (ab, &s) == 0;
  481. }
  482.  
  483. /* Lock a particular execute file.  */
  484.  
  485. boolean
  486. fsysdep_lock_uuxqt_file (zfile)
  487.      const char *zfile;
  488. {
  489.   char *zcopy, *z;
  490.   boolean fret;
  491.  
  492.   zcopy = zbufcpy (zfile);
  493.  
  494.   z = strrchr (zcopy, '/');
  495.   if (z == NULL)
  496.     *zcopy = 'L';
  497.   else
  498.     *(z + 1) = 'L';
  499.  
  500.   fret = fsdo_lock (zcopy, TRUE, (boolean *) NULL);
  501.   ubuffree (zcopy);
  502.   return fret;
  503. }
  504.  
  505. /* Unlock a particular execute file.  */
  506.  
  507. boolean
  508. fsysdep_unlock_uuxqt_file (zfile)
  509.      const char *zfile;
  510. {
  511.   char *zcopy, *z;
  512.   boolean fret;
  513.  
  514.   zcopy = zbufcpy (zfile);
  515.  
  516.   z = strrchr (zcopy, '/');
  517.   if (z == NULL)
  518.     *zcopy = 'L';
  519.   else
  520.     *(z + 1) = 'L';
  521.  
  522.   fret = fsdo_unlock (zcopy, TRUE);
  523.   ubuffree (zcopy);
  524.   return fret;
  525. }
  526.  
  527. /* Lock the execute directory.  Since we use a different directory
  528.    depending on which LCK.XQT.dddd file we got, there is actually no
  529.    need to create a lock file.  We do make sure that the directory
  530.    exists, though.  */
  531.  
  532. boolean
  533. fsysdep_lock_uuxqt_dir (iseq)
  534.      int iseq;
  535. {
  536.   const char *zxqtdir;
  537.   char abxqtdir[sizeof XQTDIR + 4];
  538.  
  539.   if (iseq == 0)
  540.     zxqtdir = XQTDIR;
  541.   else
  542.     {
  543.       sprintf (abxqtdir, "%s%04d", XQTDIR, iseq);
  544.       zxqtdir = abxqtdir;
  545.     }
  546.  
  547.   if (mkdir (zxqtdir, S_IRWXU) < 0
  548.       && errno != EEXIST
  549.       && errno != EISDIR)
  550.     {
  551.       ulog (LOG_ERROR, "mkdir (%s): %s", zxqtdir, strerror (errno));
  552.       return FALSE;
  553.     }
  554.  
  555.   return TRUE;
  556. }
  557.  
  558. /* Unlock the execute directory and clear it out.  The lock is
  559.    actually the LCK.XQT.dddd file, so we don't unlock it, but we do
  560.    remove all the files.  */
  561.  
  562. boolean
  563. fsysdep_unlock_uuxqt_dir (iseq)
  564.      int iseq;
  565. {
  566.   const char *zxqtdir;
  567.   char abxqtdir[sizeof XQTDIR + 4];
  568.   DIR *qdir;
  569.  
  570.   if (iseq == 0)
  571.     zxqtdir = XQTDIR;
  572.   else
  573.     {
  574.       sprintf (abxqtdir, "%s%04d", XQTDIR, iseq);
  575.       zxqtdir = abxqtdir;
  576.     }
  577.  
  578.   qdir = opendir ((char *) zxqtdir);
  579.   if (qdir != NULL)
  580.     {
  581.       struct dirent *qentry;
  582.  
  583.       while ((qentry = readdir (qdir)) != NULL)
  584.     {
  585.       char *z;
  586.  
  587.       if (strcmp (qentry->d_name, ".") == 0
  588.           || strcmp (qentry->d_name, "..") == 0)
  589.         continue;
  590.       z = zsysdep_in_dir (zxqtdir, qentry->d_name);
  591.       if (remove (z) < 0)
  592.         {
  593.           int ierr;
  594.  
  595.           ierr = errno;
  596.           if (! fsysdep_directory (z))
  597.         ulog (LOG_ERROR, "remove (%s): %s", z,
  598.               strerror (ierr));
  599.           else
  600.         (void) fsysdep_rmdir (z);
  601.         }
  602.       ubuffree (z);
  603.     }
  604.  
  605.       closedir (qdir);
  606.     }
  607.  
  608.   return TRUE;
  609. }
  610.  
  611. /* Move files into the execution directory.  */
  612.  
  613. boolean
  614. fsysdep_move_uuxqt_files (cfiles, pzfrom, pzto, fto, iseq, pzinput)
  615.      int cfiles;
  616.      const char *const *pzfrom;
  617.      const char *const *pzto;
  618.      boolean fto;
  619.      int iseq;
  620.      char **pzinput;
  621. {
  622.   char *zinput;
  623.   const char *zxqtdir;
  624.   char abxqtdir[sizeof XQTDIR + 4];
  625.   int i;
  626.  
  627.   if (pzinput == NULL)
  628.     zinput = NULL;
  629.   else
  630.     zinput = *pzinput;
  631.  
  632.   if (iseq == 0)
  633.     zxqtdir = XQTDIR;
  634.   else
  635.     {
  636.       sprintf (abxqtdir, "%s%04d", XQTDIR, iseq);
  637.       zxqtdir = abxqtdir;
  638.     }
  639.  
  640.   for (i = 0; i < cfiles; i++)
  641.     {
  642.       const char *zfrom, *zto;
  643.       char *zfree;
  644.  
  645.       if (pzto[i] == NULL)
  646.     continue;
  647.  
  648.       zfree = zsysdep_in_dir (zxqtdir, pzto[i]);
  649.  
  650.       zfrom = pzfrom[i];
  651.       zto = zfree;
  652.  
  653.       if (zinput != NULL && strcmp (zinput, zfrom) == 0)
  654.     {
  655.       *pzinput = zbufcpy (zto);
  656.       zinput = NULL;
  657.     }
  658.  
  659.       if (! fto)
  660.     {
  661.       const char *ztemp;
  662.       
  663.       ztemp = zfrom;
  664.       zfrom = zto;
  665.       zto = ztemp;
  666.       (void) chmod (zfrom, IPRIVATE_FILE_MODE);
  667.     }
  668.  
  669.       if (rename (zfrom, zto) < 0)
  670.     {
  671. #if HAVE_RENAME
  672.       /* On some systems the system call rename seems to fail for
  673.          arbitrary reasons.  To get around this, we always try to
  674.          copy the file by hand if the rename failed.  */
  675.       errno = EXDEV;
  676. #endif
  677.  
  678.       if (errno != EXDEV)
  679.         {
  680.           ulog (LOG_ERROR, "rename (%s, %s): %s", zfrom, zto,
  681.             strerror (errno));
  682.           ubuffree (zfree);
  683.           break;
  684.         }
  685.  
  686.       if (! fcopy_file (zfrom, zto, FALSE, FALSE, FALSE))
  687.         {
  688.           ubuffree (zfree);
  689.           break;
  690.         }
  691.       if (remove (zfrom) < 0)
  692.         ulog (LOG_ERROR, "remove (%s): %s", zfrom,
  693.           strerror (errno));
  694.     }
  695.  
  696.       if (fto)
  697.     (void) chmod (zto, IPUBLIC_FILE_MODE);
  698.  
  699.       ubuffree (zfree);
  700.     }
  701.  
  702.   if (i < cfiles)
  703.     {
  704.       if (fto)
  705.     (void) fsysdep_move_uuxqt_files (i, pzfrom, pzto, FALSE, iseq,
  706.                      (char **) NULL);
  707.       return FALSE;
  708.     }
  709.  
  710.   return TRUE;
  711. }
  712.