428 lines
14 KiB
C
428 lines
14 KiB
C
/* spool.c
|
||
Find a file in the spool directory.
|
||
|
||
Copyright (C) 1991, 1992, 1993 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
||
The author of the program may be contacted at ian@airs.com or
|
||
c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
|
||
*/
|
||
|
||
#include "uucp.h"
|
||
|
||
#if USE_RCS_ID
|
||
const char spool_rcsid[] = "$FreeBSD$";
|
||
#endif
|
||
|
||
#include "uudefs.h"
|
||
#include "sysdep.h"
|
||
#include "system.h"
|
||
|
||
/* There are several types of files that go in the spool directory,
|
||
and they go into various different subdirectories. Whenever the
|
||
system name LOCAL appears below, it means whatever the local system
|
||
name is.
|
||
|
||
Command files
|
||
These contain instructions for uucico indicating what files to transfer
|
||
to and from what systems. Each line of a work file is a command
|
||
beginning with S, R, X, or E.
|
||
#if ! SPOOLDIR_TAYLOR
|
||
They are named C.ssssssgqqqq, where ssssss is the system name to
|
||
transfer to or from, g is the grade and qqqq is the sequence number.
|
||
#if SPOOLDIR_V2
|
||
They are put in the spool directory.
|
||
#elif SPOOLDIR_BSD42 || SPOOLDIR_BSD43
|
||
They are put in the directory "C.".
|
||
#elif SPOOLDIR_HDB
|
||
They are put in a directory named for the system for which they were
|
||
created.
|
||
#elif SPOOLDIR_ULTRIX
|
||
If the directory sys/ssssss exists, they are put in the directory
|
||
sys/ssssss/C; otherwise, they are put in the directory sys/DEFAULT/C.
|
||
#elif SPOOLDIR_SVR4
|
||
They are put in the directory sys/g, where sys is the system name
|
||
and g is the grade.
|
||
#endif
|
||
#else SPOOLDIR_TAYLOR
|
||
They are named C.gqqqq, where g is the grade and qqqq is the
|
||
sequence number, and are placed in the directory ssssss/C. where
|
||
ssssss is the system name to transfer to or from. The sequence
|
||
number for a C. file is actually a long string; it is not based on
|
||
the sequence number file, but is generated via a process which
|
||
attempts to produce a unique string each time it is run.
|
||
#endif
|
||
|
||
Data files
|
||
There are files to be transferred to other systems. Some files to
|
||
be transferred may not be in the spool directory, depending on how
|
||
uucp was invoked. Data files are named in work files, so it is
|
||
never necessary to look at them directly (except to remove old ones);
|
||
it is only necessary to create them. These means that the many
|
||
variations in naming are inconsequential.
|
||
#if ! SPOOLDIR_TAYLOR
|
||
They are named D.ssssssgqqqq where ssssss is a system name (which
|
||
may be LOCAL for locally initiated transfers or a remote system for
|
||
remotely initiated transfers, except that HDB appears to use the
|
||
system the file is being transferred to), g is the grade and qqqq
|
||
is the sequence number. Some systems use a trailing subjob ID
|
||
number, but we currently do not. The grade is not important, and
|
||
some systems do not use it. If the data file is to become an
|
||
execution file on another system the grade (if present) will be
|
||
'X'. Otherwise Ultrix appears to use 'b'; the uux included with
|
||
gnuucp 1.0 appears to use 'S'; SCO does not appear to use a grade,
|
||
although it does use a subjob ID number.
|
||
#if SPOOLDIR_V2
|
||
They are put in the spool directory.
|
||
#elif SPOOLDIR_BSD42
|
||
If the name begins with D.LOCAL, the file is put in the directory
|
||
D.LOCAL. Otherwise the file is put in the directory D..
|
||
#elif SPOOLDIR_BSD43
|
||
If the name begins with D.LOCALX, the file is put in the directory
|
||
D.LOCALX. Otherwise if the name begins with D.LOCAL, the file is
|
||
put in the directory D.LOCAL Otherwise the file is put in the
|
||
directory "D.".
|
||
#elif SPOOLDIR_HDB
|
||
They are put in a directory named for the system for which they
|
||
were created.
|
||
#elif SPOOLDIR_ULTRIX
|
||
Say the file is being transferred to system REMOTE. If the
|
||
directory sys/REMOTE exists, then if the file begins with D.LOCALX
|
||
it is put in sys/REMOTE/D.LOCALX, if the file begins with D.LOCAL
|
||
it is put in sys/REMOTE/D.LOCAL, and otherwise it is put in
|
||
"sys/REMOTE/D.". If the directory sys/REMOTE does not exist, the
|
||
same applies except that DEFAULT is used instead of REMOTE.
|
||
#elif SPOOLDIR_SVR4
|
||
They are put in the directory sys/g, where sys is the system name
|
||
and g is the grade.
|
||
#endif
|
||
#else SPOOLDIR_TAYLOR
|
||
If the file is to become an executable file on another system it is
|
||
named D.Xqqqq, otherwise it is named D.qqqq where in both cases
|
||
qqqq is a sequence number. If the corresponding C. file is in
|
||
directory ssssss/C., a D.X file is placed in ssssss/D.X and a D.
|
||
file is placed in "ssssss/D.".
|
||
#endif
|
||
|
||
Execute files
|
||
These are files that specify programs to be executed. They are
|
||
created by uux, perhaps as run on another system. These names are
|
||
important, because a file transfer done to an execute file name
|
||
causes an execution to occur. The name is X.ssssssgqqqq, where
|
||
ssssss is the requesting system, g is the grade, and qqqq is a
|
||
sequence number.
|
||
#if SPOOLDIR_V2 || SPOOLDIR_BSD42
|
||
These files are placed in the spool directory.
|
||
#elif SPOOLDIR_BSD43
|
||
These files are placed in the directory X..
|
||
#elif SPOOLDIR_HDB || SPOOLDIR_SVR4
|
||
These files are put in a directory named for the system for which
|
||
the files were created.
|
||
#elif SPOOLDIR_ULTRIX
|
||
If there is a spool directory (sys/ssssss) for the requesting
|
||
system, the files are placed in sys/ssssss/X.; otherwise, the files
|
||
are placed in "sys/DEFAULT/X.".
|
||
#elif SPOOLDIR_TAYLOR
|
||
The system name is automatically truncated to seven characters when
|
||
a file is created. The files are placed in the subdirectory X. of
|
||
a directory named for the system for which the files were created.
|
||
#endif
|
||
|
||
Temporary receive files
|
||
These are used when receiving files from another system. They are
|
||
later renamed to the final name. The actual name is unimportant,
|
||
although it generally begins with TM..
|
||
#if SPOOLDIR_V2 || SPOOLDIR_BSD42
|
||
These files are placed in the spool directory.
|
||
#elif SPOOLDIR_BSD43 || SPOOLDIR_ULTRIX || SPOOLDIR_TAYLOR
|
||
These files are placed in the directory .Temp.
|
||
#elif SPOOLDIR_HDB || SPOOLDIR_SVR4
|
||
These files are placed in a directory named for the system for
|
||
which they were created.
|
||
#endif
|
||
|
||
System status files
|
||
These are used to record when the last call was made to the system
|
||
and what the status is. They are used to prevent frequent recalls
|
||
to a system which is not responding. I will not attempt to
|
||
recreate the format of these exactly, since they are not all that
|
||
important. They will be put in the directory .Status, as in HDB,
|
||
and they use the system name as the name of the file.
|
||
|
||
Sequence file
|
||
This is used to generate a unique sequence number. It contains an
|
||
ASCII number.
|
||
#if SPOOLDIR_V2 || SPOOLDIR_BSD42 || SPOOLDIR_BSD43
|
||
The file is named SEQF and is kept in the spool directory.
|
||
#elif SPOOLDIR_HDB || SPOOLDIR_SVR4
|
||
A separate sequence file is kept for each system in the directory
|
||
.Sequence with the name of the system.
|
||
#elif SPOOLDIR_ULTRIX
|
||
Each system with a file sys/ssssss has a sequence file in
|
||
sys/ssssss/.SEQF. Other systems use sys/DEFAULT/.SEQF.
|
||
#else SPOOLDIR_TAYLOR
|
||
A sequence file named SEQF is kept in the directory ssssss for each
|
||
system.
|
||
#endif
|
||
*/
|
||
|
||
/* Given the name of a file as specified in a UUCP command, and the
|
||
system for which this file has been created, return where to find
|
||
it in the spool directory. The file will begin with C. (a command
|
||
file), D. (a data file) or X. (an execution file). Under
|
||
SPOOLDIR_SVR4 we need to know the grade of the file created by the
|
||
local system; this is the bgrade argument, which is -1 for a file
|
||
from a remote system. */
|
||
|
||
/*ARGSUSED*/
|
||
char *
|
||
zsfind_file (zsimple, zsystem, bgrade)
|
||
const char *zsimple;
|
||
const char *zsystem;
|
||
int bgrade;
|
||
{
|
||
/* zsysdep_spool_commands calls this with TMPXXX which we must treat
|
||
as a C. file. */
|
||
if ((zsimple[0] != 'T'
|
||
|| zsimple[1] != 'M'
|
||
|| zsimple[2] != 'P')
|
||
&& ! fspool_file (zsimple))
|
||
{
|
||
ulog (LOG_ERROR, "Unrecognized file name %s", zsimple);
|
||
return NULL;
|
||
}
|
||
|
||
#if ! SPOOLDIR_HDB && ! SPOOLDIR_SVR4 && ! SPOOLDIR_TAYLOR
|
||
if (*zsimple == 'X')
|
||
{
|
||
static char *zbuf;
|
||
static size_t cbuf;
|
||
size_t clen, cwant;
|
||
|
||
/* Files beginning with X. are execute files. It is important
|
||
for security reasons that we know the system which created
|
||
the X. file. This is easy under SPOOLDIR_HDB or
|
||
SPOOLDIR_SVR4 SPOOLDIR_TAYLOR, because the file will be in a
|
||
directory named for the system. Under other schemes, we must
|
||
get the system name from the X. file name. To prevent
|
||
security violations, we set the system name directly here;
|
||
this will cause problems if the maximum file name length is
|
||
too short, but hopefully no problem will occur since any
|
||
System V systems will be using HDB or SVR4 or TAYLOR. */
|
||
clen = strlen (zsimple);
|
||
if (clen < 5)
|
||
{
|
||
ulog (LOG_ERROR, "Bad file name (too short) %s", zsimple);
|
||
return NULL;
|
||
}
|
||
cwant = strlen (zsystem) + 8;
|
||
if (cwant > cbuf)
|
||
{
|
||
zbuf = (char *) xrealloc ((pointer) zbuf, cwant);
|
||
cbuf = cwant;
|
||
}
|
||
sprintf (zbuf, "X.%s%s", zsystem, zsimple + clen - 5);
|
||
zsimple = zbuf;
|
||
}
|
||
#endif /* ! SPOOLDIR_HDB && ! SPOOLDIR_SVR4 && ! SPOOLDIR_TAYLOR */
|
||
|
||
#if SPOOLDIR_V2
|
||
/* V2 never uses subdirectories. */
|
||
return zbufcpy (zsimple);
|
||
#endif /* SPOOLDIR_V2 */
|
||
|
||
#if SPOOLDIR_HDB
|
||
/* HDB always uses the system name as a directory. */
|
||
return zsysdep_in_dir (zsystem, zsimple);
|
||
#endif /* SPOOLDIR_HDB */
|
||
|
||
#if SPOOLDIR_SVR4
|
||
/* SVR4 uses grade directories within the system directory for local
|
||
command and data files. */
|
||
if (bgrade < 0 || *zsimple == 'X')
|
||
return zsysdep_in_dir (zsystem, zsimple);
|
||
else
|
||
{
|
||
char abgrade[2];
|
||
|
||
abgrade[0] = bgrade;
|
||
abgrade[1] = '\0';
|
||
return zsappend3 (zsystem, abgrade, zsimple);
|
||
}
|
||
#endif /* SPOOLDIR_SVR4 */
|
||
|
||
#if ! SPOOLDIR_V2 && ! SPOOLDIR_HDB && ! SPOOLDIR_SVR4
|
||
switch (*zsimple)
|
||
{
|
||
case 'C':
|
||
case 'T':
|
||
#if SPOOLDIR_BSD42 || SPOOLDIR_BSD43
|
||
return zsysdep_in_dir ("C.", zsimple);
|
||
#endif /* SPOOLDIR_BSD42 || SPOOLDIR_BSD43 */
|
||
#if SPOOLDIR_ULTRIX
|
||
if (fsultrix_has_spool (zsystem))
|
||
return zsappend4 ("sys", zsystem, "C.", zsimple);
|
||
else
|
||
return zsappend4 ("sys", "DEFAULT", "C.", zsimple);
|
||
#endif /* SPOOLDIR_ULTRIX */
|
||
#if SPOOLDIR_TAYLOR
|
||
return zsappend3 (zsystem, "C.", zsimple);
|
||
#endif /* SPOOLDIR_TAYLOR */
|
||
|
||
case 'D':
|
||
#if SPOOLDIR_BSD42 || SPOOLDIR_BSD43
|
||
{
|
||
size_t c;
|
||
boolean ftruncated;
|
||
|
||
/* D.LOCAL in D.LOCAL/, others in D./. If BSD43, D.LOCALX in
|
||
D.LOCALX/. */
|
||
ftruncated = TRUE;
|
||
if (strncmp (zsimple + 2, zSlocalname, strlen (zSlocalname)) == 0)
|
||
{
|
||
c = strlen (zSlocalname);
|
||
ftruncated = FALSE;
|
||
}
|
||
else if (strncmp (zsimple + 2, zSlocalname, 7) == 0)
|
||
c = 7;
|
||
else if (strncmp (zsimple + 2, zSlocalname, 6) == 0)
|
||
c = 6;
|
||
else
|
||
c = 0;
|
||
#if SPOOLDIR_BSD43
|
||
if (c > 0 && zsimple[c + 2] == 'X')
|
||
c++;
|
||
#endif /* SPOOLDIR_BSD43 */
|
||
if (c > 0)
|
||
{
|
||
char *zalloc;
|
||
|
||
zalloc = zbufalc (c + 3);
|
||
memcpy (zalloc, zsimple, c + 2);
|
||
zalloc[c + 2] = '\0';
|
||
|
||
/* If we truncated the system name, and there is no existing
|
||
directory with the truncated name, then just use D.. */
|
||
if (! ftruncated || fsysdep_directory (zalloc))
|
||
{
|
||
char *zret;
|
||
|
||
zret = zsysdep_in_dir (zalloc, zsimple);
|
||
ubuffree (zalloc);
|
||
return zret;
|
||
}
|
||
ubuffree (zalloc);
|
||
}
|
||
return zsysdep_in_dir ("D.", zsimple);
|
||
}
|
||
#endif /* SPOOLDIR_BSD42 || SPOOLDIR_BSD43 */
|
||
#if SPOOLDIR_ULTRIX
|
||
{
|
||
size_t c;
|
||
boolean ftruncated;
|
||
char *zfree;
|
||
const char *zdir;
|
||
char *zret;
|
||
|
||
/* D.LOCALX in D.LOCALX/, D.LOCAL in D.LOCAL/, others in D./. */
|
||
ftruncated = TRUE;
|
||
if (strncmp (zsimple + 2, zSlocalname, strlen (zSlocalname)) == 0)
|
||
{
|
||
c = strlen (zSlocalname);
|
||
ftruncated = FALSE;
|
||
}
|
||
else if (strncmp (zsimple + 2, zSlocalname, 7) == 0)
|
||
c = 7;
|
||
else if (strncmp (zsimple + 2, zSlocalname, 6) == 0)
|
||
c = 6;
|
||
else
|
||
c = 0;
|
||
if (c > 0 && zsimple[c + 2] == 'X')
|
||
++c;
|
||
if (c > 0)
|
||
{
|
||
zfree = zbufalc (c + 3);
|
||
memcpy (zfree, zsimple, c + 2);
|
||
zfree[c + 2] = '\0';
|
||
zdir = zfree;
|
||
|
||
/* If we truncated the name, and there is no directory for
|
||
the truncated name, then don't use it. */
|
||
if (ftruncated)
|
||
{
|
||
char *zlook;
|
||
|
||
zlook = zsappend3 ("sys",
|
||
(fsultrix_has_spool (zsystem)
|
||
? zsystem
|
||
: "DEFAULT"),
|
||
zdir);
|
||
if (! fsysdep_directory (zlook))
|
||
zdir = "D.";
|
||
ubuffree (zlook);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
zfree = NULL;
|
||
zdir = "D.";
|
||
}
|
||
|
||
zret = zsappend4 ("sys",
|
||
(fsultrix_has_spool (zsystem)
|
||
? zsystem
|
||
: "DEFAULT"),
|
||
zdir,
|
||
zsimple);
|
||
ubuffree (zfree);
|
||
return zret;
|
||
}
|
||
#endif /* SPOOLDIR_ULTRIX */
|
||
#if SPOOLDIR_TAYLOR
|
||
if (zsimple[2] == 'X')
|
||
return zsappend3 (zsystem, "D.X", zsimple);
|
||
else
|
||
return zsappend3 (zsystem, "D.", zsimple);
|
||
#endif /* SPOOLDIR_TAYLOR */
|
||
|
||
|
||
case 'X':
|
||
#if SPOOLDIR_BSD42
|
||
return zbufcpy (zsimple);
|
||
#endif
|
||
#if SPOOLDIR_BSD43
|
||
return zsysdep_in_dir ("X.", zsimple);
|
||
#endif
|
||
#if SPOOLDIR_ULTRIX
|
||
return zsappend4 ("sys",
|
||
(fsultrix_has_spool (zsystem)
|
||
? zsystem
|
||
: "DEFAULT"),
|
||
"X.",
|
||
zsimple);
|
||
#endif
|
||
#if SPOOLDIR_TAYLOR
|
||
return zsappend3 (zsystem, "X.", zsimple);
|
||
#endif
|
||
}
|
||
|
||
/* This is just to avoid warnings; it will never be executed. */
|
||
return NULL;
|
||
#endif /* ! SPOOLDIR_V2 && ! SPOOLDIR_HDB && ! SPOOLDIR_SVR4 */
|
||
}
|