#include "uucp.h"
#if USE_RCS_ID
const char statsb_rcsid[] = "$Id: statsb.c,v 1.20 2002/03/05 19:10:42 ian Rel $";
#endif
#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
#if HAVE_OPENDIR
#if HAVE_DIRENT_H
#include <dirent.h>
#else
#include <sys/dir.h>
#define dirent direct
#endif
#endif
#if HAVE_TIME_H
#include <time.h>
#endif
#if HAVE_UTIME_H
#include <utime.h>
#endif
static int issettime P((const char *z, time_t inow));
static boolean fskill_or_rejuv P((pointer puuconf, const char *zid,
boolean fkill));
static int
issettime(z, inow)
const char *z;
time_t inow;
{
#if HAVE_UTIME_H
struct utimbuf s;
s.actime = inow;
s.modtime = inow;
return utime ((char *) z, &s);
#else
time_t ai[2];
ai[0] = inow;
ai[1] = inow;
return utime ((char *) z, ai);
#endif
}
boolean
fsysdep_kill_job (puuconf, zid)
pointer puuconf;
const char *zid;
{
return fskill_or_rejuv (puuconf, zid, TRUE);
}
boolean
fsysdep_rejuvenate_job (puuconf, zid)
pointer puuconf;
const char *zid;
{
return fskill_or_rejuv (puuconf, zid, FALSE);
}
static boolean
fskill_or_rejuv (puuconf, zid, fkill)
pointer puuconf;
const char *zid;
boolean fkill;
{
char *zfile;
char *zsys;
char bgrade;
time_t inow = 0;
int iuuconf;
struct uuconf_system ssys;
FILE *e;
boolean fret;
char *zline;
size_t cline;
int isys;
zfile = zsjobid_to_file (zid, &zsys, &bgrade);
if (zfile == NULL)
return FALSE;
if (! fkill)
inow = time ((time_t *) NULL);
iuuconf = uuconf_system_info (puuconf, zsys, &ssys);
if (iuuconf == UUCONF_NOT_FOUND)
{
if (! funknown_system (puuconf, zsys, &ssys))
{
ulog (LOG_ERROR, "%s: Bad job id", zid);
ubuffree (zfile);
ubuffree (zsys);
return FALSE;
}
}
else if (iuuconf != UUCONF_SUCCESS)
{
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
ubuffree (zfile);
ubuffree (zsys);
return FALSE;
}
e = fopen (zfile, "r");
if (e == NULL)
{
if (errno == ENOENT)
ulog (LOG_ERROR, "%s: Job not found", zid);
else
ulog (LOG_ERROR, "fopen (%s): %s", zfile, strerror (errno));
(void) uuconf_system_free (puuconf, &ssys);
ubuffree (zfile);
ubuffree (zsys);
return FALSE;
}
fret = TRUE;
zline = NULL;
cline = 0;
while (getline (&zline, &cline, e) > 0)
{
struct scmd s;
if (! fparse_cmd (zline, &s))
{
ulog (LOG_ERROR, "Bad line in command file %s", zfile);
fret = FALSE;
continue;
}
if (strcmp (s.zuser, zsysdep_login_name ()) != 0
&& ! fsysdep_privileged ())
{
ulog (LOG_ERROR, "%s: Not submitted by you", zid);
xfree ((pointer) zline);
(void) fclose (e);
(void) uuconf_system_free (puuconf, &ssys);
ubuffree (zfile);
ubuffree (zsys);
return FALSE;
}
if (s.bcmd == 'S' || s.bcmd == 'E')
{
char *ztemp;
ztemp = zsfind_file (s.ztemp, ssys.uuconf_zname, bgrade);
if (ztemp == NULL)
fret = FALSE;
else
{
if (fkill)
isys = remove (ztemp);
else
isys = issettime (ztemp, inow);
if (isys != 0 && errno != ENOENT)
{
ulog (LOG_ERROR, "%s (%s): %s",
fkill ? "remove" : "utime", ztemp,
strerror (errno));
fret = FALSE;
}
ubuffree (ztemp);
}
}
}
xfree ((pointer) zline);
(void) fclose (e);
(void) uuconf_system_free (puuconf, &ssys);
ubuffree (zsys);
if (fkill)
isys = remove (zfile);
else
isys = issettime (zfile, inow);
if (isys != 0 && errno != ENOENT)
{
ulog (LOG_ERROR, "%s (%s): %s", fkill ? "remove" : "utime",
zfile, strerror (errno));
fret = FALSE;
}
ubuffree (zfile);
return fret;
}
long
ixsysdep_work_time (qsys, pseq)
const struct uuconf_system *qsys;
pointer pseq;
{
char *zjobid, *zfile;
long iret;
zjobid = zsysdep_jobid (qsys, pseq);
zfile = zsjobid_to_file (zjobid, (char **) NULL, (char *) NULL);
if (zfile == NULL)
return 0;
ubuffree (zjobid);
iret = ixsysdep_file_time (zfile);
ubuffree (zfile);
return iret;
}
long
ixsysdep_file_time (zfile)
const char *zfile;
{
struct stat s;
if (stat ((char *) zfile, &s) < 0)
{
if (errno != ENOENT)
ulog (LOG_ERROR, "stat (%s): %s", zfile, strerror (errno));
return ixsysdep_time ((long *) NULL);
}
return (long) s.st_mtime;
}
boolean
fsysdep_touch_file (zfile)
const char *zfile;
{
if (issettime (zfile, time ((time_t *) NULL)) != 0)
{
ulog (LOG_ERROR, "utime (%s): %s", zfile, strerror (errno));
return FALSE;
}
return TRUE;
}
boolean
fsysdep_all_status_init (phold)
pointer *phold;
{
DIR *qdir;
qdir = opendir ((char *) ".Status");
if (qdir == NULL)
{
ulog (LOG_ERROR, "opendir (.Status): %s", strerror (errno));
return FALSE;
}
*phold = (pointer) qdir;
return TRUE;
}
char *
zsysdep_all_status (phold, pferr, qstat)
pointer phold;
boolean *pferr;
struct sstatus *qstat;
{
DIR *qdir = (DIR *) phold;
struct dirent *qentry;
while (TRUE)
{
errno = 0;
qentry = readdir (qdir);
if (qentry == NULL)
{
if (errno == 0)
*pferr = FALSE;
else
{
ulog (LOG_ERROR, "readdir: %s", strerror (errno));
*pferr = TRUE;
}
return NULL;
}
if (qentry->d_name[0] != '.')
{
struct uuconf_system ssys;
ssys.uuconf_zname = qentry->d_name;
if (fsysdep_get_status (&ssys, qstat, (boolean *) NULL))
return zbufcpy (qentry->d_name);
}
}
}
void
usysdep_all_status_free (phold)
pointer phold;
{
DIR *qdir = (DIR *) phold;
(void) closedir (qdir);
}
boolean
fsysdep_lock_status ()
{
DIR *qdir;
struct dirent *qentry;
int calc;
pid_t *pai;
#if HAVE_QNX_LOCKFILES
nid_t *painid;
#endif
int cgot;
int aidescs[3];
char *zcopy, *ztok;
int cargs, iarg;
char **pazargs;
qdir = opendir ((char *) zSlockdir);
if (qdir == NULL)
{
ulog (LOG_ERROR, "opendir (%s): %s", zSlockdir, strerror (errno));
return FALSE;
}
calc = 0;
pai = NULL;
cgot = 0;
#if HAVE_QNX_LOCKFILES
painid = NULL;
#endif
while ((qentry = readdir (qdir)) != NULL)
{
char *zname;
int o;
#if HAVE_QNX_LOCKFILES
nid_t inid;
char ab[23];
char *zend;
#else
#if HAVE_V2_LOCKFILES
int i;
#else
char ab[12];
#endif
#endif
int cread;
int ierr;
pid_t ipid;
int icheck;
if (strncmp (qentry->d_name, "LCK..", sizeof "LCK.." - 1) != 0)
continue;
zname = zsysdep_in_dir (zSlockdir, qentry->d_name);
o = open ((char *) zname, O_RDONLY | O_NOCTTY, 0);
if (o < 0)
{
if (errno != ENOENT)
ulog (LOG_ERROR, "open (%s): %s", zname, strerror (errno));
ubuffree (zname);
continue;
}
#if HAVE_V2_LOCKFILES
cread = read (o, &i, sizeof i);
#else
cread = read (o, ab, sizeof ab - 1);
#endif
ierr = errno;
(void) close (o);
if (cread < 0)
{
ulog (LOG_ERROR, "read %s: %s", zname, strerror (ierr));
ubuffree (zname);
continue;
}
ubuffree (zname);
#if HAVE_QNX_LOCKFILES
ab[cread] = '\0';
ipid = (pid_t) strtol (ab, &zend, 10);
inid = (nid_t) strtol (zend, (char **) NULL, 10);
#else
#if HAVE_V2_LOCKFILES
ipid = (pid_t) i;
#else
ab[cread] = '\0';
ipid = (pid_t) strtol (ab, (char **) NULL, 10);
#endif
#endif
#if HAVE_QNX_LOCKFILES
printf ("%s: %ld %ld\n", qentry->d_name, (long) inid, (long) ipid);
#else
printf ("%s: %ld\n", qentry->d_name, (long) ipid);
#endif
for (icheck = 0; icheck < cgot; icheck++)
if (pai[icheck] == ipid)
break;
if (icheck < cgot)
continue;
if (cgot >= calc)
{
calc += 10;
pai = (pid_t *) xrealloc ((pointer) pai, calc * sizeof (pid_t));
#if HAVE_QNX_LOCKFILES
painid = (nid_t *) xrealloc ((pointer) painid,
calc * sizeof (nid_t));
#endif
}
pai[cgot] = ipid;
#if HAVE_QNX_LOCKFILES
painid[cgot] = inid;
#endif
++cgot;
}
if (cgot == 0)
return TRUE;
aidescs[0] = SPAWN_NULL;
aidescs[1] = 1;
aidescs[2] = 2;
zcopy = zbufcpy (PS_PROGRAM);
cargs = 0;
for (ztok = strtok (zcopy, " \t");
ztok != NULL;
ztok = strtok ((char *) NULL, " \t"))
++cargs;
pazargs = (char **) xmalloc ((cargs + 1) * sizeof (char *));
memcpy (zcopy, PS_PROGRAM, sizeof PS_PROGRAM);
for (ztok = strtok (zcopy, " \t"), iarg = 0;
ztok != NULL;
ztok = strtok ((char *) NULL, " \t"), ++iarg)
pazargs[iarg] = ztok;
pazargs[iarg] = NULL;
#if ! HAVE_PS_MULTIPLE
{
int i;
char *zlast, *zset;
#if HAVE_QNX_LOCKFILES
char *zpenultimate, *zsetnid;
#endif
zlast = pazargs[cargs - 1];
zset = zbufalc (strlen (zlast) + 20);
#if HAVE_QNX_LOCKFILES
zpenultimate = pazargs[cargs - 2];
zsetnid = zbufalc (strlen (zpenultimate) + 20);
#endif
for (i = 0; i < cgot; i++)
{
pid_t ipid;
sprintf (zset, "%s%ld", zlast, (long) pai[i]);
pazargs[cargs - 1] = zset;
#if HAVE_QNX_LOCKFILES
sprintf (zsetnid, "%s%ld", zpenultimate, (long) painid[i]);
pazargs[cargs - 2] = zsetnid;
#endif
ipid = ixsspawn ((const char **) pazargs, aidescs, FALSE, FALSE,
(const char *) NULL, FALSE, TRUE,
(const char *) NULL, (const char *) NULL,
(const char *) NULL);
if (ipid < 0)
ulog (LOG_ERROR, "ixsspawn: %s", strerror (errno));
else
(void) ixswait ((unsigned long) ipid, PS_PROGRAM);
}
ubuffree (zset);
#if HAVE_QNX_LOCKFILES
ubuffree (zsetnid);
#endif
}
#else
{
char *zlast;
int i;
pid_t ipid;
zlast = zbufalc (strlen (pazargs[cargs - 1]) + cgot * 20 + 1);
strcpy (zlast, pazargs[cargs - 1]);
for (i = 0; i < cgot; i++)
{
char ab[20];
sprintf (ab, "%ld", (long) pai[i]);
strcat (zlast, ab);
if (i + 1 < cgot)
strcat (zlast, ",");
}
pazargs[cargs - 1] = zlast;
ipid = ixsspawn ((const char **) pazargs, aidescs, FALSE, FALSE,
(const char *) NULL, FALSE, TRUE,
(const char *) NULL, (const char *) NULL,
(const char *) NULL);
if (ipid < 0)
ulog (LOG_ERROR, "ixsspawn: %s", strerror (errno));
else
(void) ixswait ((unsigned long) ipid, PS_PROGRAM);
ubuffree (zlast);
}
#endif
ubuffree (zcopy);
xfree ((pointer) pazargs);
return TRUE;
}