System dependent functions used only by uuxqt.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
const char xqtsub_rcsid
[] = "$Id: xqtsub.c,v 1.1 1993/08/04 19:33:22 jtc Exp $";
#else /* ! HAVE_DIRENT_H */
#endif /* ! HAVE_DIRENT_H */
#endif /* HAVE_OPENDIR */
/* Get a value for EX_TEMPFAIL. */
/* Get the full pathname of the command to execute, given the list of
permitted commands and the allowed path. */
zsysdep_find_command (zcmd
, pzcmds
, pzpath
, pferr
)
for (pz
= pzcmds
; *pz
!= NULL
; pz
++)
if (strcmp (*pz
, "ALL") == 0)
zslash
= strrchr (*pz
, '/');
if (strcmp (zslash
, zcmd
) == 0
|| strcmp (*pz
, zcmd
) == 0)
/* If we already have an absolute path, we can get out
/* If we didn't find this command, get out. */
/* We didn't find an absolute pathname, so we must look through
for (pz
= pzpath
; *pz
!= NULL
; pz
++)
zname
= zsysdep_in_dir (*pz
, zcmd
);
if (stat (zname
, &s
) == 0)
/* Expand a local filename for uuxqt. This is special because uuxqt
only wants to expand filenames that start with ~ (it does not want
to prepend the current directory to other names) and if the ~ is
double, it is turned into a single ~. This returns NULL to
indicate that no change was required; it has no way to return
zsysdep_xqt_local_file (qsys
, zfile
)
const struct uuconf_system
*qsys
;
memcpy (zret
, zfile
+ 1, clen
);
return zsysdep_local_file (zfile
, qsys
->uuconf_zpubdir
);
#if ! ALLOW_FILENAME_ARGUMENTS
/* Check to see whether an argument specifies a file name; if it does,
make sure that the file may legally be sent and/or received. For
Unix, we do not permit any occurrence of "/../" in the name, nor
may it start with "../". Otherwise, if it starts with "/" we check
against the list of permitted files. */
fsysdep_xqt_check_file (qsys
, zfile
)
const struct uuconf_system
*qsys
;
if ((clen
== sizeof "../" - 1
&& strcmp (zfile
, "../") == 0)
|| (clen
>= sizeof "/.." - 1
&& strcmp (zfile
+ clen
- (sizeof "/.." - 1), "/..") == 0)
|| strstr (zfile
, "/../") != NULL
&& (! fin_directory_list (zfile
, qsys
->uuconf_pzremote_send
,
qsys
->uuconf_zpubdir
, TRUE
, FALSE
,
|| ! fin_directory_list (zfile
, qsys
->uuconf_pzremote_receive
,
qsys
->uuconf_zpubdir
, TRUE
, FALSE
,
ulog (LOG_ERROR
, "Not permitted to refer to file \"%s\"", zfile
);
#endif /* ! ALLOW_FILENAME_ARGUMENTS */
/* Invoke the command specified by an execute file. */
fsysdep_execute (qsys
, zuser
, pazargs
, zfullcmd
, zinput
, zoutput
,
fshell
, iseq
, pzerror
, pftemp
)
const struct uuconf_system
*qsys
;
char abxqtdir
[sizeof XQTDIR
+ 4];
aidescs
[0] = open ((char *) zinput
, O_RDONLY
| O_NOCTTY
, 0);
ulog (LOG_ERROR
, "open (%s): %s", zinput
, strerror (errno
));
else if (fcntl (aidescs
[0], F_SETFD
,
fcntl (aidescs
[0], F_GETFD
, 0) | FD_CLOEXEC
) < 0)
ulog (LOG_ERROR
, "fcntl (FD_CLOEXEC): %s", strerror (errno
));
if (! ferr
&& zoutput
!= NULL
)
aidescs
[1] = creat ((char *) zoutput
, IPRIVATE_FILE_MODE
);
ulog (LOG_ERROR
, "creat (%s): %s", zoutput
, strerror (errno
));
else if (fcntl (aidescs
[1], F_SETFD
,
fcntl (aidescs
[1], F_GETFD
, 0) | FD_CLOEXEC
) < 0)
ulog (LOG_ERROR
, "fcntl (FD_CLOEXEC): %s", strerror (errno
));
*pzerror
= zstemp_file (qsys
);
aidescs
[2] = creat (*pzerror
, IPRIVATE_FILE_MODE
);
if (! fsysdep_make_dirs (*pzerror
, FALSE
))
aidescs
[2] = creat (*pzerror
, IPRIVATE_FILE_MODE
);
if (! ferr
&& aidescs
[2] < 0)
ulog (LOG_ERROR
, "creat (%s): %s", *pzerror
, strerror (errno
));
&& fcntl (aidescs
[2], F_SETFD
,
fcntl (aidescs
[2], F_GETFD
, 0) | FD_CLOEXEC
) < 0)
ulog (LOG_ERROR
, "fcntl (FD_CLOEXEC): %s", strerror (errno
));
sprintf (abxqtdir
, "%s%04d", XQTDIR
, iseq
);
if (aidescs
[0] != SPAWN_NULL
)
(void) close (aidescs
[0]);
if (aidescs
[1] != SPAWN_NULL
)
(void) close (aidescs
[1]);
if (aidescs
[2] != SPAWN_NULL
)
(void) close (aidescs
[2]);
if (qsys
->uuconf_pzpath
== NULL
)
for (pz
= qsys
->uuconf_pzpath
; *pz
!= NULL
; pz
++)
for (pz
= qsys
->uuconf_pzpath
; *pz
!= NULL
; pz
++)
/* Pass zchdir as zxqtdir, fnosigs as TRUE, fshell as TRUE if we
aren't already using the shell. */
ipid
= ixsspawn (pazargs
, aidescs
, FALSE
, FALSE
, zxqtdir
, TRUE
,
! fshell
, zpath
, qsys
->uuconf_zname
, zuser
);
if (aidescs
[0] != SPAWN_NULL
)
(void) close (aidescs
[0]);
if (aidescs
[1] != SPAWN_NULL
)
(void) close (aidescs
[1]);
if (aidescs
[2] != SPAWN_NULL
)
(void) close (aidescs
[2]);
ulog (LOG_ERROR
, "ixsspawn: %s", strerror (ierr
));
istat
= ixswait ((unsigned long) ipid
, "Execution");
if (istat
== EX_TEMPFAIL
)
/* Lock a uuxqt process. */
ixsysdep_lock_uuxqt (zcmd
, cmaxuuxqts
)
char ab
[sizeof "LCK.XQT.9999"];
if (cmaxuuxqts
<= 0 || cmaxuuxqts
>= 10000)
for (i
= 0; i
< cmaxuuxqts
; i
++)
sprintf (ab
, "LCK.XQT.%d", i
);
if (fsdo_lock (ab
, TRUE
, (boolean
*) NULL
))
char abcmd
[sizeof "LXQ.123456789"];
sprintf (abcmd
, "LXQ.%.9s", zcmd
);
abcmd
[strcspn (abcmd
, " \t/")] = '\0';
if (! fsdo_lock (abcmd
, TRUE
, (boolean
*) NULL
))
(void) fsdo_unlock (ab
, TRUE
);
/* Unlock a uuxqt process. */
fsysdep_unlock_uuxqt (iseq
, zcmd
, cmaxuuxqts
)
char ab
[sizeof "LCK.XQT.9999"];
sprintf (ab
, "LCK.XQT.%d", iseq
);
if (! fsdo_unlock (ab
, TRUE
))
char abcmd
[sizeof "LXQ.123456789"];
sprintf (abcmd
, "LXQ.%.9s", zcmd
);
abcmd
[strcspn (abcmd
, " \t/")] = '\0';
if (! fsdo_unlock (abcmd
, TRUE
))
/* See whether a particular uuxqt command is locked (this depends on
the implementation of fsdo_lock). */
fsysdep_uuxqt_locked (zcmd
)
char ab
[sizeof "LXQ.123456789"];
sprintf (ab
, "LXQ.%.9s", zcmd
);
return stat (ab
, &s
) == 0;
/* Lock a particular execute file. */
fsysdep_lock_uuxqt_file (zfile
)
z
= strrchr (zcopy
, '/');
fret
= fsdo_lock (zcopy
, TRUE
, (boolean
*) NULL
);
/* Unlock a particular execute file. */
fsysdep_unlock_uuxqt_file (zfile
)
z
= strrchr (zcopy
, '/');
fret
= fsdo_unlock (zcopy
, TRUE
);
/* Lock the execute directory. Since we use a different directory
depending on which LCK.XQT.dddd file we got, there is actually no
need to create a lock file. We do make sure that the directory
fsysdep_lock_uuxqt_dir (iseq
)
char abxqtdir
[sizeof XQTDIR
+ 4];
sprintf (abxqtdir
, "%s%04d", XQTDIR
, iseq
);
if (mkdir (zxqtdir
, S_IRWXU
) < 0
ulog (LOG_ERROR
, "mkdir (%s): %s", zxqtdir
, strerror (errno
));
/* Unlock the execute directory and clear it out. The lock is
actually the LCK.XQT.dddd file, so we don't unlock it, but we do
fsysdep_unlock_uuxqt_dir (iseq
)
char abxqtdir
[sizeof XQTDIR
+ 4];
sprintf (abxqtdir
, "%s%04d", XQTDIR
, iseq
);
qdir
= opendir ((char *) zxqtdir
);
while ((qentry
= readdir (qdir
)) != NULL
)
if (strcmp (qentry
->d_name
, ".") == 0
|| strcmp (qentry
->d_name
, "..") == 0)
z
= zsysdep_in_dir (zxqtdir
, qentry
->d_name
);
if (! fsysdep_directory (z
))
ulog (LOG_ERROR
, "remove (%s): %s", z
,
(void) fsysdep_rmdir (z
);
/* Move files into the execution directory. */
fsysdep_move_uuxqt_files (cfiles
, pzfrom
, pzto
, fto
, iseq
, pzinput
)
const char *const *pzfrom
;
char abxqtdir
[sizeof XQTDIR
+ 4];
sprintf (abxqtdir
, "%s%04d", XQTDIR
, iseq
);
for (i
= 0; i
< cfiles
; i
++)
zfree
= zsysdep_in_dir (zxqtdir
, pzto
[i
]);
if (zinput
!= NULL
&& strcmp (zinput
, zfrom
) == 0)
*pzinput
= zbufcpy (zto
);
(void) chmod (zfrom
, IPRIVATE_FILE_MODE
);
if (rename (zfrom
, zto
) < 0)
/* On some systems the system call rename seems to fail for
arbitrary reasons. To get around this, we always try to
copy the file by hand if the rename failed. */
ulog (LOG_ERROR
, "rename (%s, %s): %s", zfrom
, zto
,
if (! fcopy_file (zfrom
, zto
, FALSE
, FALSE
))
ulog (LOG_ERROR
, "remove (%s): %s", zfrom
,
(void) chmod (zto
, IPUBLIC_FILE_MODE
);
(void) fsysdep_move_uuxqt_files (i
, pzfrom
, pzto
, FALSE
, iseq
,