1072 lines
24 KiB
C
1072 lines
24 KiB
C
/* uustat.c
|
||
UUCP status program
|
||
|
||
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 AIRS, P.O. Box 520, Waltham, MA 02254.
|
||
|
||
$Log: uustat.c,v $
|
||
Revision 1.1.1.1 1993/03/21 09:45:37 cgd
|
||
initial import of 386bsd-0.1 sources
|
||
|
||
Revision 1.7 1992/03/28 22:54:45 ian
|
||
Allow multiple systems and users or kills and rejuvenates at once
|
||
|
||
Revision 1.6 1992/03/12 19:54:43 ian
|
||
Debugging based on types rather than number
|
||
|
||
Revision 1.5 1992/03/03 21:34:55 ian
|
||
Handle local execution files
|
||
|
||
Revision 1.4 1992/02/27 05:40:54 ian
|
||
T. William Wells: detach from controlling terminal, handle signals safely
|
||
|
||
Revision 1.3 1992/02/24 20:36:27 ian
|
||
Roberto Biancardi: skip spaces after strtok (NULL, "")
|
||
|
||
Revision 1.2 1992/02/23 03:26:51 ian
|
||
Overhaul to use automatic configure shell script
|
||
|
||
Revision 1.1 1992/02/20 04:18:59 ian
|
||
Initial revision
|
||
|
||
*/
|
||
|
||
#include "uucp.h"
|
||
|
||
#if USE_RCS_ID
|
||
char uustat_rcsid[] = "$Id: uustat.c,v 1.1.1.1 1993/03/21 09:45:37 cgd Exp $";
|
||
#endif
|
||
|
||
#include <errno.h>
|
||
|
||
#if HAVE_TIME_H
|
||
#include <time.h>
|
||
#endif
|
||
|
||
#include "system.h"
|
||
#include "sysdep.h"
|
||
#include "getopt.h"
|
||
|
||
/* The uustat program permits various listings and manipulations of
|
||
files in the spool directory. This implementation supports the
|
||
following switches:
|
||
|
||
-a list all jobs
|
||
-kjobid kill job with specified ID
|
||
-m report status for all remote machines
|
||
-ohour report jobs older than specified number of hours
|
||
-p do "ps -flp" on all processes holding lock files (Unix specific)
|
||
-q list number of jobs for all systems
|
||
-rjobid rejuvenate job with specified ID
|
||
-ssystem report on all jobs for specified system
|
||
-uuser report on all jobs for specified user
|
||
-yhour report jobs younger than specified number of hours
|
||
-Ifile set configuration file name
|
||
-xdebug set debugging level */
|
||
|
||
/* The program name. */
|
||
char abProgram[] = "uustat";
|
||
|
||
/* Local functions. */
|
||
|
||
static void ususage P((void));
|
||
static boolean fsworkfiles P((int csystems, char **pazsystems,
|
||
int cusers, char **pazusers,
|
||
long iold, long iyoung));
|
||
static boolean fsworkfiles_system P((const struct ssysteminfo *qsys,
|
||
int cusers, char **pazusers,
|
||
long iold, long iyoung));
|
||
static boolean fsworkfile_show P((const struct ssysteminfo *qsys,
|
||
const struct scmd *qcmd,
|
||
long itime));
|
||
static void usworkfile_header P((const struct ssysteminfo *qsys,
|
||
const struct scmd *qcmd,
|
||
const char *zjobid,
|
||
long itime, boolean ffirst));
|
||
static boolean fsquery P((void));
|
||
static void usunits_show P((long idiff));
|
||
static boolean fsmachines P((void));
|
||
|
||
/* Long getopt options. */
|
||
|
||
static const struct option asLongopts[] = { { NULL, 0, NULL, 0 } };
|
||
|
||
const struct option *_getopt_long_options = asLongopts;
|
||
|
||
int
|
||
main (argc, argv)
|
||
int argc;
|
||
char **argv;
|
||
{
|
||
int iopt;
|
||
/* -a: list all jobs. */
|
||
boolean fall = FALSE;
|
||
/* -k jobid: kill specified job. */
|
||
int ckills = 0;
|
||
char **pazkills = NULL;
|
||
/* -m: report machine status. */
|
||
boolean fmachine = FALSE;
|
||
/* -o hour: report jobs older than given number of hours. */
|
||
int ioldhours = -1;
|
||
/* -p: report status of jobs holding lock files. */
|
||
boolean fps = FALSE;
|
||
/* -q: list number of jobs for each system. */
|
||
boolean fquery = FALSE;
|
||
/* -r jobid: rejuvenate specified job. */
|
||
int crejuvs = 0;
|
||
char **pazrejuvs = NULL;
|
||
/* -s system: list all jobs for specified system. */
|
||
int csystems = 0;
|
||
char **pazsystems = NULL;
|
||
/* -u user: list all jobs for specified user. */
|
||
int cusers = 0;
|
||
char **pazusers = NULL;
|
||
/* -y hour: report jobs younger than given number of hours. */
|
||
int iyounghours = -1;
|
||
/* -I file: set configuration file. */
|
||
const char *zconfig = NULL;
|
||
int ccmds;
|
||
long iold;
|
||
long iyoung;
|
||
char *azoneuser[1];
|
||
boolean fret;
|
||
|
||
while ((iopt = getopt (argc, argv, "aI:k:mo:pqr:s:u:x:y:")) != EOF)
|
||
{
|
||
switch (iopt)
|
||
{
|
||
case 'a':
|
||
/* List all jobs. */
|
||
fall = TRUE;
|
||
break;
|
||
|
||
case 'I':
|
||
/* Set configuration file name. */
|
||
zconfig = optarg;
|
||
break;
|
||
|
||
case 'k':
|
||
/* Kill specified job. */
|
||
++ckills;
|
||
pazkills = (char **) xrealloc ((pointer) pazkills,
|
||
ckills * sizeof (char *));
|
||
pazkills[ckills - 1] = optarg;
|
||
break;
|
||
|
||
case 'm':
|
||
/* Report machine status. */
|
||
fmachine = TRUE;
|
||
break;
|
||
|
||
case 'o':
|
||
/* Report old jobs. */
|
||
ioldhours = atoi (optarg);
|
||
break;
|
||
|
||
case 'p':
|
||
/* Get status of processes holding locks. */
|
||
fps = TRUE;
|
||
break;
|
||
|
||
case 'q':
|
||
/* List number of jobs for each system. */
|
||
fquery = TRUE;
|
||
break;
|
||
|
||
case 'r':
|
||
/* Rejuvenate specified job. */
|
||
++crejuvs;
|
||
pazrejuvs = (char **) xrealloc ((pointer) pazrejuvs,
|
||
crejuvs * sizeof (char *));
|
||
pazrejuvs[crejuvs - 1] = optarg;
|
||
break;
|
||
|
||
case 's':
|
||
/* List jobs for specified system. */
|
||
++csystems;
|
||
pazsystems = (char **) xrealloc ((pointer) pazsystems,
|
||
csystems * sizeof (char *));
|
||
pazsystems[csystems - 1] = optarg;
|
||
break;
|
||
|
||
case 'u':
|
||
/* List jobs for specified user. */
|
||
++cusers;
|
||
pazusers = (char **) xrealloc ((pointer) pazusers,
|
||
cusers * sizeof (char *));
|
||
pazusers[cusers - 1] = optarg;
|
||
break;
|
||
|
||
case 'x':
|
||
#if DEBUG > 1
|
||
/* Set debugging level. */
|
||
iDebug |= idebug_parse (optarg);
|
||
#endif
|
||
break;
|
||
|
||
case 'y':
|
||
/* List jobs younger than given number of hours. */
|
||
iyounghours = atoi (optarg);
|
||
break;
|
||
|
||
case 0:
|
||
/* Long option found and flag set. */
|
||
break;
|
||
|
||
default:
|
||
ususage ();
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (optind != argc)
|
||
ususage ();
|
||
|
||
/* To avoid confusion, most options are only permitted by
|
||
themselves. This restriction might be removed later, but it is
|
||
imposed by most implementations. We do permit any combination of
|
||
-s, -u, -o and -y, and any combination of -k and -r. */
|
||
ccmds = 0;
|
||
if (fall)
|
||
++ccmds;
|
||
if (ckills > 0 || crejuvs > 0)
|
||
++ccmds;
|
||
if (fmachine)
|
||
++ccmds;
|
||
if (fps)
|
||
++ccmds;
|
||
if (fquery)
|
||
++ccmds;
|
||
if (csystems > 0 || cusers > 0
|
||
|| ioldhours != -1 || iyounghours != -1)
|
||
++ccmds;
|
||
|
||
if (ccmds > 1)
|
||
{
|
||
fprintf (stderr, "uustat: Too many options\n");
|
||
ususage ();
|
||
}
|
||
|
||
uread_config (zconfig);
|
||
|
||
usysdep_initialize (FALSE, FALSE);
|
||
|
||
/* If no commands were specified, we list all commands for the given
|
||
user. */
|
||
if (ccmds == 0)
|
||
{
|
||
cusers = 1;
|
||
azoneuser[0] = xstrdup (zsysdep_login_name ());
|
||
pazusers = azoneuser;
|
||
}
|
||
|
||
if (ioldhours == -1)
|
||
iold = (long) -1;
|
||
else
|
||
{
|
||
iold = (isysdep_time ((long *) NULL)
|
||
- (long) ioldhours * (long) 60 * (long) 60);
|
||
if (iold < 0L)
|
||
iold = 0L;
|
||
}
|
||
if (iyounghours == -1)
|
||
iyoung = (long) -1;
|
||
else
|
||
{
|
||
iyoung = (isysdep_time ((long *) NULL)
|
||
- (long) iyounghours * (long) 60 * (long) 60);
|
||
if (iyoung < 0L)
|
||
iyoung = 0L;
|
||
}
|
||
|
||
if (fall
|
||
|| ioldhours != -1
|
||
|| csystems > 0
|
||
|| cusers > 0
|
||
|| iyounghours != -1)
|
||
fret = fsworkfiles (csystems, pazsystems, cusers, pazusers, iold,
|
||
iyoung);
|
||
else if (fquery)
|
||
fret = fsquery ();
|
||
else if (fmachine)
|
||
fret = fsmachines ();
|
||
else if (ckills > 0 || crejuvs > 0)
|
||
{
|
||
int i;
|
||
|
||
fret = TRUE;
|
||
for (i = 0; i < ckills; i++)
|
||
if (! fsysdep_kill_job (pazkills[i]))
|
||
fret = FALSE;
|
||
|
||
for (i = 0; i < crejuvs; i++)
|
||
if (! fsysdep_rejuvenate_job (pazrejuvs[i]))
|
||
fret = FALSE;
|
||
}
|
||
else if (fps)
|
||
fret = fsysdep_lock_status ();
|
||
else
|
||
{
|
||
#if DEBUG > 0
|
||
ulog (LOG_FATAL, "Can't happen");
|
||
#endif
|
||
fret = FALSE;
|
||
}
|
||
|
||
ulog_close ();
|
||
|
||
usysdep_exit (fret);
|
||
|
||
/* Avoid errors about not returning a value. */
|
||
return 0;
|
||
}
|
||
|
||
/* Print a usage message and die. */
|
||
|
||
static void
|
||
ususage ()
|
||
{
|
||
fprintf (stderr,
|
||
"Taylor UUCP version %s, copyright (C) 1991, 1992 Ian Lance Taylor\n",
|
||
abVersion);
|
||
fprintf (stderr,
|
||
"Usage: uustat [-ampq] [-kr job] [-oy hours] [-s system] [-u user]\n");
|
||
fprintf (stderr,
|
||
" -a: list all UUCP jobs\n");
|
||
fprintf (stderr,
|
||
" -k job: kill specified UUCP job\n");
|
||
fprintf (stderr,
|
||
" -m: report status for all remote machines\n");
|
||
fprintf (stderr,
|
||
" -o hours: list all jobs older than given number of hours\n");
|
||
fprintf (stderr,
|
||
" -p: show status of all processes holding UUCP locks\n");
|
||
fprintf (stderr,
|
||
" -q: list number of jobs for each system\n");
|
||
fprintf (stderr,
|
||
" -r job: rejuvenate specified UUCP job\n");
|
||
fprintf (stderr,
|
||
" -s system: list all jobs for specified system\n");
|
||
fprintf (stderr,
|
||
" -u user: list all jobs for specified user\n");
|
||
fprintf (stderr,
|
||
" -y hours: list all jobs younger than given number of hours\n");
|
||
fprintf (stderr,
|
||
" -x debug: Set debugging level (0 for none, 9 is max)\n");
|
||
#if HAVE_TAYLOR_CONFIG
|
||
fprintf (stderr,
|
||
" -I file: Set configuration file to use (default %s%s)\n",
|
||
NEWCONFIGLIB, CONFIGFILE);
|
||
#endif /* HAVE_TAYLOR_CONFIG */
|
||
exit (EXIT_FAILURE);
|
||
}
|
||
|
||
/* Handle various possible requests to look at work files. */
|
||
|
||
static boolean
|
||
fsworkfiles (csystems, pazsystems, cusers, pazusers, iold, iyoung)
|
||
int csystems;
|
||
char **pazsystems;
|
||
int cusers;
|
||
char **pazusers;
|
||
long iold;
|
||
long iyoung;
|
||
{
|
||
boolean fret;
|
||
int i;
|
||
|
||
fret = TRUE;
|
||
|
||
if (csystems > 0)
|
||
{
|
||
struct ssysteminfo ssys;
|
||
|
||
for (i = 0; i < csystems; i++)
|
||
{
|
||
if (! fread_system_info (pazsystems[i], &ssys))
|
||
{
|
||
ulog (LOG_ERROR, "%s: unknown system", pazsystems[i]);
|
||
fret = FALSE;
|
||
continue;
|
||
}
|
||
|
||
if (! fsworkfiles_system (&ssys, cusers, pazusers, iold, iyoung))
|
||
fret = FALSE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int cs;
|
||
struct ssysteminfo *pas;
|
||
|
||
uread_all_system_info (&cs, &pas);
|
||
|
||
for (i = 0; i < cs; i++)
|
||
if (! fsworkfiles_system (&pas[i], cusers, pazusers, iold, iyoung))
|
||
fret = FALSE;
|
||
}
|
||
|
||
return fret;
|
||
}
|
||
|
||
/* Look at the work files for a particular system. */
|
||
|
||
static boolean
|
||
fsworkfiles_system (qsys, cusers, pazusers, iold, iyoung)
|
||
const struct ssysteminfo *qsys;
|
||
int cusers;
|
||
char **pazusers;
|
||
long iold;
|
||
long iyoung;
|
||
{
|
||
boolean fret;
|
||
|
||
if (! fsysdep_get_work_init (qsys, BGRADE_LOW))
|
||
return FALSE;
|
||
|
||
while (TRUE)
|
||
{
|
||
struct scmd s;
|
||
long itime;
|
||
|
||
if (! fsysdep_get_work (qsys, BGRADE_LOW, &s))
|
||
{
|
||
usysdep_get_work_free (qsys);
|
||
return FALSE;
|
||
}
|
||
if (s.bcmd == 'H')
|
||
break;
|
||
|
||
if (cusers > 0)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < cusers; i++)
|
||
if (strcmp (pazusers[i], s.zuser) == 0)
|
||
break;
|
||
if (i >= cusers)
|
||
continue;
|
||
}
|
||
|
||
itime = isysdep_work_time (qsys, s.pseq);
|
||
|
||
if (iold != (long) -1 && itime > iold)
|
||
continue;
|
||
|
||
if (iyoung != (long) -1 && itime < iyoung)
|
||
continue;
|
||
|
||
if (! fsworkfile_show (qsys, &s, itime))
|
||
{
|
||
usysdep_get_work_free (qsys);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
fret = fsworkfile_show (qsys, (const struct scmd *) NULL, 0L);
|
||
|
||
usysdep_get_work_free (qsys);
|
||
|
||
return fret;
|
||
}
|
||
|
||
/* Show a single workfile. This is actually called once for each line
|
||
in the workfile, so we accumulate the lines and show them all at
|
||
once. This lets us show an execution in a useful fashion. */
|
||
|
||
struct scmdlist
|
||
{
|
||
struct scmdlist *qnext;
|
||
struct scmd s;
|
||
long itime;
|
||
};
|
||
|
||
static boolean
|
||
fsworkfile_show (qsys, qcmd, itime)
|
||
const struct ssysteminfo *qsys;
|
||
const struct scmd *qcmd;
|
||
long itime;
|
||
{
|
||
static struct scmdlist *qlist;
|
||
static const char *zlistid;
|
||
const char *zid;
|
||
|
||
if (qcmd == NULL)
|
||
zid = NULL;
|
||
else
|
||
{
|
||
zid = zsysdep_jobid (qsys, qcmd->pseq);
|
||
if (zid == NULL)
|
||
return FALSE;
|
||
}
|
||
|
||
/* If this is the same jobid as the list, put it on the end. */
|
||
|
||
if (qcmd != NULL
|
||
&& qlist != NULL
|
||
&& strcmp (zlistid, zid) == 0)
|
||
{
|
||
struct scmdlist *qnew, **pq;
|
||
|
||
qnew = (struct scmdlist *) xmalloc (sizeof (struct scmdlist));
|
||
qnew->qnext = NULL;
|
||
qnew->s = *qcmd;
|
||
qnew->itime = itime;
|
||
for (pq = &qlist; *pq != NULL; pq = &(*pq)->qnext)
|
||
;
|
||
*pq = qnew;
|
||
return TRUE;
|
||
}
|
||
|
||
if (qcmd != NULL)
|
||
zid = xstrdup (zid);
|
||
|
||
/* Here we have found a different job ID, so we print the scmd
|
||
structures that we have accumulated. We look for the special
|
||
case of an execution (one of the destination files begins with
|
||
X.). We could be more clever about other situations as well. */
|
||
|
||
if (qlist != NULL)
|
||
{
|
||
struct scmdlist *qlook;
|
||
|
||
for (qlook = qlist; qlook != NULL; qlook = qlook->qnext)
|
||
if (qlook->s.bcmd == 'S'
|
||
&& qlook->s.zto[0] == 'X'
|
||
&& qlook->s.zto[1] == '.'
|
||
&& fspool_file (qlook->s.zfrom))
|
||
break;
|
||
|
||
if (qlook == NULL)
|
||
{
|
||
/* Show all the lines in a regular work file. */
|
||
|
||
for (qlook = qlist; qlook != NULL; qlook = qlook->qnext)
|
||
{
|
||
const char *zfile;
|
||
|
||
usworkfile_header (qsys, &qlook->s, zlistid, qlook->itime,
|
||
qlook == qlist);
|
||
|
||
switch (qlook->s.bcmd)
|
||
{
|
||
case 'S':
|
||
if (strchr (qlook->s.zoptions, 'C') != NULL
|
||
|| fspool_file (qlook->s.zfrom))
|
||
zfile = zsysdep_spool_file_name (qsys, qlook->s.ztemp);
|
||
else
|
||
zfile = zsysdep_real_file_name (qsys, qlook->s.zfrom,
|
||
(const char *) NULL);
|
||
printf ("Sending %s (%ld bytes) to %s", qlook->s.zfrom,
|
||
zfile == NULL ? 0L : csysdep_size (zfile),
|
||
qlook->s.zto);
|
||
break;
|
||
case 'R':
|
||
printf ("Requesting %s to %s", qlook->s.zfrom,
|
||
qlook->s.zto);
|
||
break;
|
||
case 'X':
|
||
printf ("Requesting %s to %s", qlook->s.zfrom,
|
||
qlook->s.zto);
|
||
break;
|
||
#if DEBUG > 0
|
||
default:
|
||
printf ("Bad line %d", qlook->s.bcmd);
|
||
break;
|
||
#endif
|
||
}
|
||
|
||
printf ("\n");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
const char *zxqt;
|
||
FILE *e;
|
||
long csize;
|
||
struct scmdlist *qsize;
|
||
char *zline;
|
||
|
||
/* Show the command for an execution file. */
|
||
zxqt = zsysdep_spool_file_name (qsys, qlook->s.zfrom);
|
||
if (zxqt == NULL)
|
||
return FALSE;
|
||
|
||
e = fopen (zxqt, "r");
|
||
if (e == NULL)
|
||
{
|
||
ulog (LOG_ERROR, "fopen (%s): %s", zxqt, strerror (errno));
|
||
return FALSE;
|
||
}
|
||
|
||
csize = 0L;
|
||
for (qsize = qlist; qsize != NULL; qsize = qsize->qnext)
|
||
{
|
||
if (qsize->s.bcmd == 'S')
|
||
{
|
||
const char *zfile;
|
||
|
||
if (strchr (qsize->s.zoptions, 'C') != NULL
|
||
|| fspool_file (qsize->s.zfrom))
|
||
zfile = zsysdep_spool_file_name (qsys, qsize->s.ztemp);
|
||
else
|
||
zfile = zsysdep_real_file_name (qsys, qsize->s.zfrom,
|
||
(const char *) NULL);
|
||
if (zfile != NULL)
|
||
csize += csysdep_size (zfile);
|
||
}
|
||
}
|
||
|
||
usworkfile_header (qsys, &qlook->s, zlistid, qlook->itime,
|
||
TRUE);
|
||
|
||
while ((zline = zfgets (e, FALSE)) != NULL)
|
||
{
|
||
char *ztok;
|
||
|
||
ztok = strtok (zline, " \t");
|
||
if (ztok != NULL
|
||
&& strcmp (ztok, "C") == 0)
|
||
{
|
||
char *zcmd;
|
||
int clen;
|
||
|
||
zcmd = strtok ((char *) NULL, "");
|
||
zcmd += strspn (zcmd, " \t");
|
||
clen = strlen (zcmd);
|
||
if (zcmd[clen - 1] == '\n')
|
||
zcmd[clen - 1] = '\0';
|
||
printf ("Executing %s", zcmd);
|
||
xfree ((pointer) zline);
|
||
break;
|
||
}
|
||
xfree ((pointer) zline);
|
||
}
|
||
|
||
if (zline == NULL)
|
||
printf ("Unrecognized execution");
|
||
|
||
printf (" (sending %ld bytes)\n", csize);
|
||
|
||
(void) fclose (e);
|
||
}
|
||
|
||
/* Free up the list of entries. */
|
||
qlook = qlist;
|
||
while (qlook != NULL)
|
||
{
|
||
struct scmdlist *qnext;
|
||
|
||
qnext = qlook->qnext;
|
||
xfree ((pointer) qlook);
|
||
qlook = qnext;
|
||
}
|
||
|
||
xfree ((pointer) zlistid);
|
||
|
||
qlist = NULL;
|
||
zlistid = NULL;
|
||
}
|
||
|
||
/* Start a new list with the entry we just got. */
|
||
|
||
if (qcmd != NULL)
|
||
{
|
||
qlist = (struct scmdlist *) xmalloc (sizeof (struct scmdlist));
|
||
qlist->qnext = NULL;
|
||
qlist->s = *qcmd;
|
||
qlist->itime = itime;
|
||
zlistid = zid;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/* Show the header of the line describing a workfile. */
|
||
|
||
static void
|
||
usworkfile_header (qsys, qcmd, zjobid, itime, ffirst)
|
||
const struct ssysteminfo *qsys;
|
||
const struct scmd *qcmd;
|
||
const char *zjobid;
|
||
long itime;
|
||
boolean ffirst;
|
||
{
|
||
const char *zshowid;
|
||
struct tm stime;
|
||
|
||
if (ffirst)
|
||
zshowid = zjobid;
|
||
else
|
||
zshowid = "-";
|
||
|
||
printf ("%.14s %s %s ", zshowid, qsys->zname, qcmd->zuser);
|
||
|
||
usysdep_localtime (itime, &stime);
|
||
printf ("%04d-%02d-%02d %02d:%02d:%02d ",
|
||
stime.tm_year + 1900, stime.tm_mon + 1,
|
||
stime.tm_mday, stime.tm_hour,
|
||
stime.tm_min, stime.tm_sec);
|
||
}
|
||
|
||
/* Handle the -q option. For each remote system this lists the number
|
||
of jobs queued, the number of executions queued, and the current
|
||
call status. We get the executions all at once, because they are
|
||
not accessed by system. They could be, but it is possible to have
|
||
executions pending for an unknown system, so special handling would
|
||
still be required. */
|
||
|
||
struct sxqtlist
|
||
{
|
||
struct sxqtlist *qnext;
|
||
char *zsystem;
|
||
int cxqts;
|
||
long ifirst;
|
||
};
|
||
|
||
/* These local functions need the definition of sxqtlist for the
|
||
prototype. */
|
||
|
||
static boolean fsquery_system P((const struct ssysteminfo *qsys,
|
||
struct sxqtlist **pq,
|
||
long inow));
|
||
static boolean fsquery_show P((const struct ssysteminfo *qsys, int cwork,
|
||
long ifirstwork,
|
||
struct sxqtlist *qxqt,
|
||
long inow));
|
||
|
||
static boolean
|
||
fsquery ()
|
||
{
|
||
struct sxqtlist *qlist;
|
||
const char *zfile;
|
||
const char *zsystem;
|
||
boolean ferr;
|
||
long inow;
|
||
int csystems;
|
||
struct ssysteminfo *pas;
|
||
boolean fret;
|
||
int i;
|
||
|
||
/* Get a count of all the execution files. */
|
||
|
||
if (! fsysdep_get_xqt_init ())
|
||
return FALSE;
|
||
|
||
qlist = NULL;
|
||
while ((zfile = zsysdep_get_xqt (&zsystem, &ferr)) != NULL)
|
||
{
|
||
struct sxqtlist *qlook;
|
||
|
||
for (qlook = qlist; qlook != NULL; qlook = qlook->qnext)
|
||
if (strcmp (zsystem, qlook->zsystem) == 0)
|
||
break;
|
||
|
||
if (qlook != NULL)
|
||
{
|
||
long itime;
|
||
|
||
++qlook->cxqts;
|
||
itime = isysdep_file_time (zfile);
|
||
if (itime < qlook->ifirst)
|
||
qlook->ifirst = itime;
|
||
}
|
||
else
|
||
{
|
||
struct sxqtlist *qnew;
|
||
|
||
qnew = (struct sxqtlist *) xmalloc (sizeof (struct sxqtlist));
|
||
qnew->qnext = qlist;
|
||
qnew->zsystem = xstrdup (zsystem);
|
||
qnew->cxqts = 1;
|
||
qnew->ifirst = isysdep_file_time (zfile);
|
||
qlist = qnew;
|
||
}
|
||
}
|
||
|
||
usysdep_get_xqt_free ();
|
||
|
||
if (ferr)
|
||
return FALSE;
|
||
|
||
inow = isysdep_time ((long *) NULL);
|
||
|
||
/* Get a count of all the work files, and print out the system. */
|
||
|
||
uread_all_system_info (&csystems, &pas);
|
||
|
||
fret = TRUE;
|
||
for (i = 0; i < csystems; i++)
|
||
if (! fsquery_system (&pas[i], &qlist, inow))
|
||
fret = FALSE;
|
||
|
||
/* Check for the local system in the list of execution files. */
|
||
if (qlist != NULL)
|
||
{
|
||
struct sxqtlist **pq;
|
||
|
||
for (pq = &qlist; *pq != NULL; pq = &(*pq)->qnext)
|
||
{
|
||
if (strcmp ((*pq)->zsystem, zLocalname) == 0)
|
||
{
|
||
struct sxqtlist *qfree;
|
||
|
||
if (! fsquery_show (&sLocalsys, 0, 0L, *pq, inow))
|
||
fret = FALSE;
|
||
qfree = *pq;
|
||
*pq = qfree->qnext;
|
||
xfree ((pointer) qfree->zsystem);
|
||
xfree ((pointer) qfree);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Print out information for any unknown systems for which we have
|
||
execution files. */
|
||
|
||
if (qlist != NULL && ! fUnknown_ok)
|
||
{
|
||
ulog (LOG_ERROR, "Executions queued up for unknown systems");
|
||
return FALSE;
|
||
}
|
||
|
||
while (qlist != NULL)
|
||
{
|
||
struct sxqtlist *qnext;
|
||
|
||
sUnknown.zname = qlist->zsystem;
|
||
if (! fsquery_show (&sUnknown, 0, 0L, qlist, inow))
|
||
fret = FALSE;
|
||
qnext = qlist->qnext;
|
||
xfree ((pointer) qlist->zsystem);
|
||
xfree ((pointer) qlist);
|
||
qlist = qnext;
|
||
}
|
||
|
||
return fret;
|
||
}
|
||
|
||
/* Query a single known system. */
|
||
|
||
static boolean
|
||
fsquery_system (qsys, pq, inow)
|
||
const struct ssysteminfo *qsys;
|
||
struct sxqtlist **pq;
|
||
long inow;
|
||
{
|
||
int cwork;
|
||
long ifirstwork;
|
||
boolean fret;
|
||
|
||
if (! fsysdep_get_work_init (qsys, BGRADE_LOW))
|
||
return FALSE;
|
||
|
||
cwork = 0;
|
||
ifirstwork = 0L;
|
||
while (TRUE)
|
||
{
|
||
struct scmd s;
|
||
long itime;
|
||
|
||
if (! fsysdep_get_work (qsys, BGRADE_LOW, &s))
|
||
return FALSE;
|
||
if (s.bcmd == 'H')
|
||
break;
|
||
|
||
++cwork;
|
||
|
||
itime = isysdep_work_time (qsys, s.pseq);
|
||
if (ifirstwork == 0L || ifirstwork > itime)
|
||
ifirstwork = itime;
|
||
}
|
||
|
||
usysdep_get_work_free (qsys);
|
||
|
||
/* Find the execution information, if any. */
|
||
while (*pq != NULL)
|
||
{
|
||
if (strcmp ((*pq)->zsystem, qsys->zname) == 0)
|
||
break;
|
||
pq = &(*pq)->qnext;
|
||
}
|
||
|
||
/* If there are no commands and no executions, don't print any
|
||
information for this system. */
|
||
if (cwork == 0 && *pq == NULL)
|
||
return TRUE;
|
||
|
||
fret = fsquery_show (qsys, cwork, ifirstwork, *pq, inow);
|
||
|
||
if (*pq != NULL)
|
||
{
|
||
struct sxqtlist *qfree;
|
||
|
||
qfree = *pq;
|
||
*pq = qfree->qnext;
|
||
xfree ((pointer) qfree->zsystem);
|
||
xfree ((pointer) qfree);
|
||
}
|
||
|
||
return fret;
|
||
}
|
||
|
||
/* Print out the query information for a single system. We handle the
|
||
local system specially. */
|
||
|
||
static boolean
|
||
fsquery_show (qsys, cwork, ifirstwork, qxqt, inow)
|
||
const struct ssysteminfo *qsys;
|
||
int cwork;
|
||
long ifirstwork;
|
||
struct sxqtlist *qxqt;
|
||
long inow;
|
||
{
|
||
boolean flocal;
|
||
struct sstatus sstat;
|
||
struct tm stime;
|
||
|
||
flocal = strcmp (qsys->zname, zLocalname) == 0;
|
||
|
||
if (! flocal)
|
||
{
|
||
if (! fsysdep_get_status (qsys, &sstat))
|
||
return FALSE;
|
||
}
|
||
|
||
printf ("%s %dC (", qsys->zname, cwork);
|
||
|
||
if (cwork == 0)
|
||
printf ("0 secs");
|
||
else
|
||
usunits_show (inow - ifirstwork);
|
||
|
||
printf (") ");
|
||
|
||
if (qxqt == NULL)
|
||
printf ("0X (0 secs)");
|
||
else
|
||
{
|
||
printf ("%dX (", qxqt->cxqts);
|
||
usunits_show (inow - qxqt->ifirst);
|
||
printf (")");
|
||
}
|
||
|
||
if (flocal)
|
||
{
|
||
printf ("\n");
|
||
return TRUE;
|
||
}
|
||
|
||
usysdep_localtime (sstat.ilast, &stime);
|
||
|
||
printf (" %04d-%02d-%02d %02d:%02d:%02d ",
|
||
stime.tm_year + 1900, stime.tm_mon + 1,
|
||
stime.tm_mday, stime.tm_hour,
|
||
stime.tm_min, stime.tm_sec);
|
||
|
||
printf ("%s\n", azStatus[(int) sstat.ttype]);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/* Print a time difference in the largest applicable units. */
|
||
|
||
static void
|
||
usunits_show (idiff)
|
||
long idiff;
|
||
{
|
||
const char *zunit;
|
||
long iunits;
|
||
|
||
if (idiff > (long) 24 * (long) 60 * (long) 60)
|
||
{
|
||
iunits = idiff / ((long) 24 * (long) 60 * (long) 60);
|
||
zunit = "day";
|
||
}
|
||
else if (idiff > (long) 60 * 60)
|
||
{
|
||
iunits = idiff / (long) (60 * 60);
|
||
zunit = "hour";
|
||
}
|
||
else if (idiff > (long) 60)
|
||
{
|
||
iunits = idiff / (long) 60;
|
||
zunit = "min";
|
||
}
|
||
else
|
||
{
|
||
iunits = idiff;
|
||
zunit = "sec";
|
||
}
|
||
|
||
printf ("%ld %s%s", iunits, zunit, iunits == 1 ? "" : "s");
|
||
}
|
||
|
||
/* Give a list of all status entries for all machines that we have
|
||
status entries for. We need to get a list of status entries in a
|
||
system dependent fashion, since we may have status for unknown
|
||
systems. */
|
||
|
||
static boolean
|
||
fsmachines ()
|
||
{
|
||
pointer phold;
|
||
const char *zsystem;
|
||
boolean ferr;
|
||
struct sstatus sstat;
|
||
|
||
if (! fsysdep_all_status_init (&phold))
|
||
return FALSE;
|
||
|
||
while ((zsystem = zsysdep_all_status (phold, &ferr, &sstat)) != NULL)
|
||
{
|
||
struct tm stime;
|
||
|
||
usysdep_localtime (sstat.ilast, &stime);
|
||
printf ("%-14s %04d-%02d-%02d %02d:%02d:%02d %s", zsystem,
|
||
stime.tm_year + 1900, stime.tm_mon + 1,
|
||
stime.tm_mday, stime.tm_hour,
|
||
stime.tm_min, stime.tm_sec,
|
||
azStatus[(int) sstat.ttype]);
|
||
if (sstat.ttype != STATUS_TALKING
|
||
&& sstat.cwait > 0)
|
||
{
|
||
printf (" (%d %s", sstat.cretries,
|
||
sstat.cretries == 1 ? "try" : "tries");
|
||
if (sstat.ilast + sstat.cwait > isysdep_time ((long *) NULL))
|
||
{
|
||
usysdep_localtime (sstat.ilast + sstat.cwait, &stime);
|
||
printf (", next %04d-%02d-%02d %02d:%02d:%02d",
|
||
stime.tm_year + 1900, stime.tm_mon + 1,
|
||
stime.tm_mday, stime.tm_hour,
|
||
stime.tm_min, stime.tm_sec);
|
||
}
|
||
printf (")");
|
||
}
|
||
printf ("\n");
|
||
}
|
||
|
||
usysdep_all_status_free (phold);
|
||
|
||
return ! ferr;
|
||
}
|