#include "uucp.h"
#if USE_RCS_ID
const char work_rcsid[] = "$Id: work.c,v 1.24 2002/03/05 19:10:42 ian Rel $";
#endif
#include "uudefs.h"
#include "uuconf.h"
#include "system.h"
#include "sysdep.h"
#include <ctype.h>
#include <errno.h>
#if HAVE_OPENDIR
#if HAVE_DIRENT_H
#include <dirent.h>
#else
#include <sys/dir.h>
#define dirent direct
#endif
#endif
static char *zswork_directory P((const char *zsystem));
static boolean fswork_file P((const char *zsystem, const char *zfile,
char *pbgrade));
static int iswork_cmp P((constpointer pkey, constpointer pdatum));
struct ssfilename
{
char *zfile;
char bgrade;
char bdummy;
};
#define CFILELINES (10)
struct ssline
{
char *zline;
struct ssfile *qfile;
char *ztemp;
};
struct ssfile
{
char *zfile;
char bgrade;
char bdummy;
int clines;
int cdid;
struct ssline aslines[CFILELINES];
};
static struct ssfilename *asSwork_files;
static size_t cSwork_files;
static size_t iSwork_file;
static struct ssfile *qSwork_file;
static char *
zswork_directory (zsystem)
const char *zsystem;
{
#if SPOOLDIR_V2
return zbufcpy (".");
#endif
#if SPOOLDIR_BSD42 || SPOOLDIR_BSD43
return zbufcpy ("C.");
#endif
#if SPOOLDIR_HDB || SPOOLDIR_SVR4
return zbufcpy (zsystem);
#endif
#if SPOOLDIR_ULTRIX
return zsappend3 ("sys",
(fsultrix_has_spool (zsystem)
? zsystem
: "DEFAULT"),
"C.");
#endif
#if SPOOLDIR_TAYLOR
return zsysdep_in_dir (zsystem, "C.");
#endif
}
static boolean
fswork_file (zsystem, zfile, pbgrade)
const char *zsystem ATTRIBUTE_UNUSED;
const char *zfile;
char *pbgrade;
{
#if SPOOLDIR_V2 || SPOOLDIR_BSD42 || SPOOLDIR_BSD43 || SPOOLDIR_ULTRIX
int cfilesys, csys;
if (zfile[0] != 'C' || zfile[1] != '.')
return FALSE;
csys = strlen (zsystem);
cfilesys = strlen (zfile) - 7;
if (csys != cfilesys
&& (csys < 6 || (cfilesys != 6 && cfilesys != 7)))
return FALSE;
*pbgrade = zfile[cfilesys + 2];
return strncmp (zfile + 2, zsystem, cfilesys) == 0;
#endif
#if SPOOLDIR_HDB || SPOOLDIR_SVR4
int clen;
if (zfile[0] != 'C' || zfile[1] != '.')
return FALSE;
clen = strlen (zfile);
if (clen < 7)
return FALSE;
#if ! SPOOLDIR_SVR4
*pbgrade = zfile[clen - 5];
#endif
return TRUE;
#endif
#if SPOOLDIR_TAYLOR
*pbgrade = zfile[2];
return (zfile[0] == 'C'
&& zfile[1] == '.'
&& zfile[2] != '\0');
#endif
}
static int
iswork_cmp (pkey, pdatum)
constpointer pkey;
constpointer pdatum;
{
const struct ssfilename *qkey = (const struct ssfilename *) pkey;
const struct ssfilename *qdatum = (const struct ssfilename *) pdatum;
return strcmp (qkey->zfile, qdatum->zfile);
}
boolean
fsysdep_has_work (qsys)
const struct uuconf_system *qsys;
{
char *zdir;
DIR *qdir;
struct dirent *qentry;
#if SPOOLDIR_SVR4
DIR *qgdir;
struct dirent *qgentry;
#endif
zdir = zswork_directory (qsys->uuconf_zname);
if (zdir == NULL)
return FALSE;
qdir = opendir ((char *) zdir);
if (qdir == NULL)
{
ubuffree (zdir);
return FALSE;
}
#if SPOOLDIR_SVR4
qgdir = qdir;
while ((qgentry = readdir (qgdir)) != NULL)
{
char *zsub;
if (qgentry->d_name[0] == '.'
|| qgentry->d_name[1] != '\0')
continue;
zsub = zsysdep_in_dir (zdir, qgentry->d_name);
qdir = opendir (zsub);
ubuffree (zsub);
if (qdir == NULL)
continue;
#endif
while ((qentry = readdir (qdir)) != NULL)
{
char bgrade;
if (fswork_file (qsys->uuconf_zname, qentry->d_name, &bgrade))
{
closedir (qdir);
#if SPOOLDIR_SVR4
closedir (qgdir);
#endif
ubuffree (zdir);
return TRUE;
}
}
#if SPOOLDIR_SVR4
closedir (qdir);
}
qdir = qgdir;
#endif
closedir (qdir);
ubuffree (zdir);
return FALSE;
}
#define CWORKFILES (10)
boolean
fsysdep_get_work_init (qsys, bgrade, cmax)
const struct uuconf_system *qsys;
int bgrade;
unsigned int cmax;
{
char *zdir;
DIR *qdir;
struct dirent *qentry;
size_t chad;
size_t callocated;
#if SPOOLDIR_SVR4
DIR *qgdir;
struct dirent *qgentry;
#endif
zdir = zswork_directory (qsys->uuconf_zname);
if (zdir == NULL)
return FALSE;
qdir = opendir (zdir);
if (qdir == NULL)
{
boolean fret;
if (errno == ENOENT)
fret = TRUE;
else
{
ulog (LOG_ERROR, "opendir (%s): %s", zdir, strerror (errno));
fret = FALSE;
}
ubuffree (zdir);
return fret;
}
chad = cSwork_files;
callocated = cSwork_files;
if (chad > 0)
qsort ((pointer) asSwork_files, chad, sizeof (struct ssfilename),
iswork_cmp);
#if SPOOLDIR_SVR4
qgdir = qdir;
while ((qgentry = readdir (qgdir)) != NULL)
{
char *zsub;
if (qgentry->d_name[0] == '.'
|| qgentry->d_name[1] != '\0'
|| UUCONF_GRADE_CMP (bgrade, qgentry->d_name[0]) < 0)
continue;
zsub = zsysdep_in_dir (zdir, qgentry->d_name);
qdir = opendir (zsub);
if (qdir == NULL)
{
if (errno != ENOTDIR && errno != ENOENT)
{
ulog (LOG_ERROR, "opendir (%s): %s", zsub,
strerror (errno));
ubuffree (zsub);
return FALSE;
}
ubuffree (zsub);
continue;
}
ubuffree (zsub);
#endif
while ((qentry = readdir (qdir)) != NULL)
{
char bfilegrade;
char *zname;
struct ssfilename slook;
#if ! SPOOLDIR_SVR4
zname = zbufcpy (qentry->d_name);
#else
zname = zsysdep_in_dir (qgentry->d_name, qentry->d_name);
bfilegrade = qgentry->d_name[0];
#endif
slook.zfile = zname;
if (! fswork_file (qsys->uuconf_zname, qentry->d_name,
&bfilegrade)
|| UUCONF_GRADE_CMP (bgrade, bfilegrade) < 0
|| (asSwork_files != NULL
&& bsearch ((pointer) &slook,
(pointer) asSwork_files,
chad, sizeof (struct ssfilename),
iswork_cmp) != NULL))
ubuffree (zname);
else
{
DEBUG_MESSAGE1 (DEBUG_SPOOLDIR,
"fsysdep_get_work_init: Found %s",
zname);
if (cSwork_files >= callocated)
{
callocated += CWORKFILES;
asSwork_files =
((struct ssfilename *)
xrealloc ((pointer) asSwork_files,
(callocated * sizeof (struct ssfilename))));
}
asSwork_files[cSwork_files].zfile = zname;
asSwork_files[cSwork_files].bgrade = bfilegrade;
++cSwork_files;
if (cmax != 0 && cSwork_files - chad > cmax)
break;
}
}
#if SPOOLDIR_SVR4
closedir (qdir);
if (cmax != 0 && cSwork_files - chad > cmax)
break;
}
qdir = qgdir;
#endif
closedir (qdir);
ubuffree (zdir);
if (cSwork_files > iSwork_file)
qsort ((pointer) (asSwork_files + iSwork_file),
cSwork_files - iSwork_file,
sizeof (struct ssfilename), iswork_cmp);
return TRUE;
}
boolean
fsysdep_get_work (qsys, bgrade, cmax, qcmd)
const struct uuconf_system *qsys;
int bgrade ATTRIBUTE_UNUSED;
unsigned int cmax ATTRIBUTE_UNUSED;
struct scmd *qcmd;
{
char *zdir;
if (qSwork_file != NULL && qSwork_file->cdid >= qSwork_file->clines)
qSwork_file = NULL;
if (asSwork_files == NULL)
{
qcmd->bcmd = 'H';
return TRUE;
}
zdir = NULL;
while (TRUE)
{
while (qSwork_file == NULL)
{
FILE *e;
struct ssfile *qfile;
int iline, callocated;
char *zline;
size_t cline;
char *zname;
char bfilegrade;
do
{
if (iSwork_file >= cSwork_files)
{
qcmd->bcmd = 'H';
ubuffree (zdir);
return TRUE;
}
if (zdir == NULL)
{
zdir = zswork_directory (qsys->uuconf_zname);
if (zdir == NULL)
return FALSE;
}
zname = zsysdep_in_dir (zdir, asSwork_files[iSwork_file].zfile);
bfilegrade = asSwork_files[iSwork_file].bgrade;
++iSwork_file;
e = fopen (zname, "r");
if (e == NULL)
{
ulog (LOG_ERROR, "fopen (%s): %s", zname,
strerror (errno));
ubuffree (zname);
}
}
while (e == NULL);
qfile = (struct ssfile *) xmalloc (sizeof (struct ssfile));
callocated = CFILELINES;
iline = 0;
zline = NULL;
cline = 0;
while (getline (&zline, &cline, e) > 0)
{
if (iline >= callocated)
{
qfile =
((struct ssfile *)
xrealloc ((pointer) qfile,
(sizeof (struct ssfile) +
(callocated * sizeof (struct ssline)))));
callocated += CFILELINES;
}
qfile->aslines[iline].zline = zbufcpy (zline);
qfile->aslines[iline].qfile = NULL;
qfile->aslines[iline].ztemp = NULL;
iline++;
}
xfree ((pointer) zline);
if (fclose (e) != 0)
ulog (LOG_ERROR, "fclose: %s", strerror (errno));
if (iline == 0)
{
qfile->aslines[0].zline = zbufcpy ("P");
qfile->aslines[0].qfile = NULL;
qfile->aslines[0].ztemp = NULL;
iline = 1;
}
qfile->zfile = zname;
qfile->bgrade = bfilegrade;
qfile->clines = iline;
qfile->cdid = 0;
qSwork_file = qfile;
}
while (TRUE)
{
int iline;
if (qSwork_file->cdid >= qSwork_file->clines)
{
qSwork_file = NULL;
break;
}
iline = qSwork_file->cdid;
++qSwork_file->cdid;
if (! fparse_cmd (qSwork_file->aslines[iline].zline, qcmd))
{
ulog (LOG_ERROR, "Bad line in command file %s",
qSwork_file->zfile);
ubuffree (qSwork_file->aslines[iline].zline);
qSwork_file->aslines[iline].zline = NULL;
continue;
}
qcmd->bgrade = qSwork_file->bgrade;
qSwork_file->aslines[iline].qfile = qSwork_file;
qcmd->pseq = (pointer) (&qSwork_file->aslines[iline]);
if (qcmd->bcmd == 'S' || qcmd->bcmd == 'E')
{
char *zreal;
zreal = zsysdep_spool_file_name (qsys, qcmd->ztemp,
qcmd->pseq);
if (zreal == NULL)
{
ubuffree (qSwork_file->aslines[iline].zline);
qSwork_file->aslines[iline].zline = NULL;
ubuffree (zdir);
return FALSE;
}
qSwork_file->aslines[iline].ztemp = zreal;
}
ubuffree (zdir);
return TRUE;
}
}
}
boolean
fsysdep_did_work (pseq)
pointer pseq;
{
struct ssfile *qfile;
struct ssline *qline;
int i;
qline = (struct ssline *) pseq;
ubuffree (qline->zline);
qline->zline = NULL;
qfile = qline->qfile;
qline->qfile = NULL;
if (qline->ztemp != NULL)
{
(void) remove (qline->ztemp);
ubuffree (qline->ztemp);
qline->ztemp = NULL;
}
if (qfile->cdid < qfile->clines)
return TRUE;
for (i = 0; i < qfile->clines; i++)
if (qfile->aslines[i].qfile != NULL)
return TRUE;
if (remove (qfile->zfile) != 0)
{
ulog (LOG_ERROR, "remove (%s): %s", qfile->zfile,
strerror (errno));
return FALSE;
}
ubuffree (qfile->zfile);
xfree ((pointer) qfile);
if (qfile == qSwork_file)
qSwork_file = NULL;
return TRUE;
}
void
usysdep_get_work_free (qsys)
const struct uuconf_system *qsys ATTRIBUTE_UNUSED;
{
if (asSwork_files != NULL)
{
size_t i;
for (i = 0; i < cSwork_files; i++)
ubuffree ((pointer) asSwork_files[i].zfile);
xfree ((pointer) asSwork_files);
asSwork_files = NULL;
cSwork_files = 0;
iSwork_file = 0;
}
if (qSwork_file != NULL)
{
int i;
ubuffree (qSwork_file->zfile);
for (i = 0; i < qSwork_file->cdid; i++)
{
ubuffree (qSwork_file->aslines[i].zline);
ubuffree (qSwork_file->aslines[i].ztemp);
}
for (i = qSwork_file->cdid; i < qSwork_file->clines; i++)
ubuffree (qSwork_file->aslines[i].zline);
xfree ((pointer) qSwork_file);
qSwork_file = NULL;
}
}
const char *
zsysdep_save_temp_file (pseq)
pointer pseq;
{
struct ssline *qline = (struct ssline *) pseq;
char *zto, *zslash;
size_t cwant;
static char *zbuf;
static size_t cbuf;
if (! fsysdep_file_exists (qline->ztemp))
return NULL;
zslash = strrchr (qline->ztemp, '/');
if (zslash == NULL)
zslash = qline->ztemp;
else
++zslash;
zto = zbufalc (sizeof PRESERVEDIR + sizeof "/" + strlen (zslash));
sprintf (zto, "%s/%s", PRESERVEDIR, zslash);
if (! fsysdep_move_file (qline->ztemp, zto, TRUE, FALSE, FALSE,
(const char *) NULL))
{
ubuffree (zto);
return "Could not move file to preservation directory";
}
cwant = sizeof "File saved as\n\t/" + strlen (zSspooldir) + strlen (zto);
if (cwant > cbuf)
{
ubuffree (zbuf);
zbuf = zbufalc (cwant);
cbuf = cwant;
}
sprintf (zbuf, "File saved as\n\t%s/%s", zSspooldir, zto);
ubuffree (zto);
return zbuf;
}
char *
zsysdep_jobid (qsys, pseq)
const struct uuconf_system *qsys;
pointer pseq;
{
return zsfile_to_jobid (qsys, ((struct ssline *) pseq)->qfile->zfile,
bsgrade (pseq));
}
int
bsgrade (pseq)
pointer pseq;
{
const char *zfile;
char bgrade;
if (pseq == NULL)
return -1;
zfile = ((struct ssline *) pseq)->qfile->zfile;
#if SPOOLDIR_TAYLOR
bgrade = *(strrchr (zfile, '/') + 3);
#else
#if ! SPOOLDIR_SVR4
bgrade = zfile[strlen (zfile) - CSEQLEN - 1];
#else
bgrade = *(strchr (zfile, '/') + 1);
#endif
#endif
return bgrade;
}