#include "uucp.h"
#include "uudefs.h"
#include "uuconf.h"
#include "sysdep.h"
#include "system.h"
#include <errno.h>
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#endif
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#if ! HAVE_BROKEN_SETLKW
#ifdef F_SETLKW
#ifdef O_CREAT
#define USE_POSIX_LOCKS 1
#endif
#endif
#endif
#ifndef USE_POSIX_LOCKS
#define USE_POSIX_LOCKS 0
#endif
#ifndef lseek
extern off_t lseek ();
#endif
#define ZCHARS \
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
static boolean fscmd_seq P((const char *zsystem, char *zseq));
static char *zsfile_name P((int btype, const char *zsystem,
const char *zlocalname, int bgrade,
boolean fxqt, char *ztname, char *zdname,
char *zxname));
static boolean
fscmd_seq (zsystem, zseq)
const char *zsystem;
char *zseq;
{
int cdelay;
char *zfree;
const char *zfile;
int o;
boolean flockfile;
int i;
boolean fret;
cdelay = 5;
#if ! USE_POSIX_LOCKS
{
boolean ferr;
while (! fsdo_lock ("LCK..SEQ", TRUE, &ferr))
{
if (ferr || FGOT_SIGNAL ())
return FALSE;
sleep (cdelay);
if (cdelay < 60)
++cdelay;
}
}
#endif
zfree = NULL;
#if SPOOLDIR_V2 || SPOOLDIR_BSD42 || SPOOLDIR_BSD43
zfile = "SEQF";
#endif
#if SPOOLDIR_HDB || SPOOLDIR_SVR4
zfree = zsysdep_in_dir (".Sequence", zsystem);
zfile = zfree;
#endif
#if SPOOLDIR_ULTRIX
if (! fsultrix_has_spool (zsystem))
zfile = "sys/DEFAULT/.SEQF";
else
{
zfree = zsappend3 ("sys", zsystem, ".SEQF");
zfile = zfree;
}
#endif
#if SPOOLDIR_TAYLOR
zfree = zsysdep_in_dir (zsystem, "SEQF");
zfile = zfree;
#endif
#ifdef O_CREAT
o = open ((char *) zfile, O_RDWR | O_CREAT | O_NOCTTY, IPRIVATE_FILE_MODE);
#else
o = open ((char *) zfile, O_RDWR | O_NOCTTY);
if (o < 0 && errno == ENOENT)
{
o = creat ((char *) zfile, IPRIVATE_FILE_MODE);
if (o >= 0)
{
(void) close (o);
o = open ((char *) zfile, O_RDWR | O_NOCTTY);
}
}
#endif
if (o < 0)
{
if (errno == ENOENT)
{
if (! fsysdep_make_dirs (zfile, FALSE))
{
#if ! USE_POSIX_LOCKS
(void) fsdo_unlock ("LCK..SEQ", TRUE);
#endif
return FALSE;
}
#ifdef O_CREAT
o = open ((char *) zfile,
O_RDWR | O_CREAT | O_NOCTTY,
IPRIVATE_FILE_MODE);
#else
o = creat ((char *) zfile, IPRIVATE_FILE_MODE);
if (o >= 0)
{
(void) close (o);
o = open ((char *) zfile, O_RDWR | O_NOCTTY);
}
#endif
}
if (o < 0)
{
ulog (LOG_ERROR, "open (%s): %s", zfile, strerror (errno));
#if ! USE_POSIX_LOCKS
(void) fsdo_unlock ("LCK..SEQ", TRUE);
#endif
return FALSE;
}
}
#if ! USE_POSIX_LOCKS
flockfile = TRUE;
#else
{
struct flock slock;
flockfile = FALSE;
slock.l_type = F_WRLCK;
slock.l_whence = SEEK_SET;
slock.l_start = 0;
slock.l_len = 0;
while (fcntl (o, F_SETLKW, &slock) == -1)
{
boolean fagain;
if (errno == EINVAL)
{
boolean ferr;
while (! fsdo_lock ("LCK..SEQ", TRUE, &ferr))
{
if (ferr || FGOT_SIGNAL ())
{
(void) close (o);
return FALSE;
}
sleep (cdelay);
if (cdelay < 60)
++cdelay;
}
flockfile = TRUE;
break;
}
fagain = FALSE;
if (errno == ENOMEM)
fagain = TRUE;
#ifdef ENOLCK
if (errno == ENOLCK)
fagain = TRUE;
#endif
#ifdef ENOSPC
if (errno == ENOSPC)
fagain = TRUE;
#endif
if (fagain)
{
sleep (cdelay);
if (cdelay < 60)
++cdelay;
continue;
}
ulog (LOG_ERROR, "Locking %s: %s", zfile, strerror (errno));
(void) close (o);
return FALSE;
}
}
#endif
if (read (o, zseq, CSEQLEN) != CSEQLEN)
strcpy (zseq, "0000");
zseq[CSEQLEN] = '\0';
#if SPOOLDIR_V2 || SPOOLDIR_BSD42 || SPOOLDIR_BSD43 || SPOOLDIR_HDB || SPOOLDIR_SVR4
i = (int) strtol (zseq, (char **) NULL, 16);
++i;
if (i > 0xffff)
i = 0;
sprintf (zseq, "%04x", (unsigned int) i);
#endif
#if SPOOLDIR_ULTRIX || SPOOLDIR_TAYLOR
for (i = CSEQLEN - 1; i >= 0; i--)
{
const char *zdig;
zdig = strchr (ZCHARS, zseq[i]);
if (zdig == NULL || zdig[0] == '\0' || zdig[1] == '\0')
zseq[i] = '0';
else
{
zseq[i] = zdig[1];
break;
}
}
#endif
fret = TRUE;
if (lseek (o, (off_t) 0, SEEK_SET) < 0
|| write (o, zseq, CSEQLEN) != CSEQLEN
|| close (o) < 0)
{
ulog (LOG_ERROR, "lseek or write or close %s: %s",
zfile, strerror (errno));
(void) close (o);
fret = FALSE;
}
if (flockfile)
(void) fsdo_unlock ("LCK..SEQ", TRUE);
ubuffree (zfree);
return fret;
}
static char *
zsfile_name (btype, zsystem, zlocalname, bgrade, fxqt, ztname, zdname, zxname)
int btype;
const char *zsystem;
const char *zlocalname;
int bgrade;
boolean fxqt;
char *ztname;
char *zdname;
char *zxname;
{
char abseq[CSEQLEN + 1];
char absimple[11 + CSEQLEN];
char *zname;
if (zlocalname == NULL)
zlocalname = zSlocalname;
while (TRUE)
{
if (! fscmd_seq (zsystem, abseq))
return NULL;
if (btype == 'C')
{
#if ! SPOOLDIR_TAYLOR
sprintf (absimple, "C.%.7s%c%s", zsystem, bgrade, abseq);
#else
sprintf (absimple, "C.%c%s", bgrade, abseq);
#endif
}
else if (btype == 'D')
{
#if SPOOLDIR_SVR4
sprintf (absimple, "D.%.7s%c%s", zsystem, bgrade, abseq);
#else
#if ! SPOOLDIR_TAYLOR
sprintf (absimple, "D.%.7s%c%s", zlocalname, bgrade, abseq);
#else
if (fxqt)
sprintf (absimple, "D.X%s", abseq);
else
sprintf (absimple, "D.%s", abseq);
#endif
#endif
}
#if DEBUG > 0
else
ulog (LOG_FATAL, "zsfile_name: Can't happen");
#endif
zname = zsfind_file (absimple, zsystem, bgrade);
if (zname == NULL)
return NULL;
if (! fsysdep_file_exists (zname))
break;
ubuffree (zname);
}
if (ztname != NULL)
strcpy (ztname, absimple);
if (zdname != NULL)
sprintf (zdname, "D.%.7s%c%s", zlocalname, bgrade, abseq);
if (zxname != NULL)
sprintf (zxname, "X.%.7s%c%s", zlocalname, bgrade, abseq);
return zname;
}
char *
zsysdep_data_file_name (qsys, zlocalname, bgrade, fxqt, ztname, zdname,
zxname)
const struct uuconf_system *qsys;
const char *zlocalname;
int bgrade;
boolean fxqt;
char *ztname;
char *zdname;
char *zxname;
{
return zsfile_name ('D', qsys->uuconf_zname, zlocalname, bgrade, fxqt,
ztname, zdname, zxname);
}
#if SPOOLDIR_TAYLOR
static void usput62 P((long i, char *, int c));
static void
usput62 (i, z, c)
long i;
char *z;
int c;
{
for (--c; c >= 0; --c)
{
int d;
d = i % 62;
i /= 62;
if (d < 26)
z[c] = 'A' + d;
else if (d < 52)
z[c] = 'a' + d - 26;
else
z[c] = '0' + d - 52;
}
}
#endif
char *
zscmd_file (qsys, bgrade)
const struct uuconf_system *qsys;
int bgrade;
{
#if ! SPOOLDIR_TAYLOR
return zsfile_name ('C', qsys->uuconf_zname, (const char *) NULL,
bgrade, FALSE, (char *) NULL, (char *) NULL,
(char *) NULL);
#else
char *zname;
long isecs, imicros;
pid_t ipid;
isecs = ixsysdep_time (&imicros);
ipid = getpid ();
isecs %= (long) 24 * (long) 60 * (long) 60;
imicros %= 1000000;
imicros /= 5;
while (TRUE)
{
char ab[15];
ab[0] = 'C';
ab[1] = '.';
ab[2] = bgrade;
usput62 (isecs, ab + 3, 3);
usput62 (imicros, ab + 6, 3);
usput62 ((long) ipid, ab + 9, 5);
ab[14] = '\0';
zname = zsfind_file (ab, qsys->uuconf_zname, bgrade);
if (zname == NULL)
return NULL;
if (! fsysdep_file_exists (zname))
break;
ubuffree (zname);
if (imicros == 0)
{
imicros = (long) 62 * (long) 62 * (long) 62;
if (isecs == 0)
isecs = (long) 62 * (long) 62 * (long) 62;
--isecs;
}
--imicros;
}
return zname;
#endif
}
char *
zsysdep_xqt_file_name ()
{
char abseq[CSEQLEN + 1];
char absx[11 + CSEQLEN];
char *zname;
while (TRUE)
{
if (! fscmd_seq (zSlocalname, abseq))
return NULL;
sprintf (absx, "X.%.7sX%s", zSlocalname, abseq);
zname = zsfind_file (absx, zSlocalname, -1);
if (zname == NULL)
return NULL;
if (! fsysdep_file_exists (zname))
break;
ubuffree (zname);
}
return zname;
}