diff options
Diffstat (limited to 'gnu/libexec/uucp/libunix/statsb.c')
| -rw-r--r-- | gnu/libexec/uucp/libunix/statsb.c | 572 |
1 files changed, 572 insertions, 0 deletions
diff --git a/gnu/libexec/uucp/libunix/statsb.c b/gnu/libexec/uucp/libunix/statsb.c new file mode 100644 index 000000000000..aa17f9e9df07 --- /dev/null +++ b/gnu/libexec/uucp/libunix/statsb.c @@ -0,0 +1,572 @@ +/* statsb.c + System dependent routines for uustat. + + Copyright (C) 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 Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#include "uucp.h" + +#if USE_RCS_ID +const char statsb_rcsid[] = "$Id: statsb.c,v 1.1 1993/08/05 18:24:34 conklin Exp $"; +#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 /* ! HAVE_DIRENT_H */ +#include <sys/dir.h> +#define dirent direct +#endif /* ! HAVE_DIRENT_H */ +#endif /* HAVE_OPENDIR */ + +#if HAVE_TIME_H +#include <time.h> +#endif + +#if HAVE_UTIME_H +#include <utime.h> +#endif + +/* Local functions. */ + +static int ussettime P((const char *z, time_t inow)); +static boolean fskill_or_rejuv P((pointer puuconf, const char *zid, + boolean fkill)); + +/* See whether the user is permitted to kill arbitrary jobs. This is + true only for root and uucp. We check for uucp by seeing if the + real user ID and the effective user ID are the same; this works + because we should be suid to uucp, so our effective user ID will + always be uucp while our real user ID will be whoever ran the + program. */ + +boolean +fsysdep_privileged () +{ + uid_t iuid; + + iuid = getuid (); + return iuid == 0 || iuid == geteuid (); +} + +/* Set file access time to the present. On many systems this could be + done by passing NULL to utime, but on some that doesn't work. This + routine is not time critical, so we never rely on NULL. */ + +static int +ussettime(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 +} + +/* Kill a job, given the jobid. */ + +boolean +fsysdep_kill_job (puuconf, zid) + pointer puuconf; + const char *zid; +{ + return fskill_or_rejuv (puuconf, zid, TRUE); +} + +/* Rejuvenate a job, given the jobid. */ + +boolean +fsysdep_rejuvenate_job (puuconf, zid) + pointer puuconf; + const char *zid; +{ + return fskill_or_rejuv (puuconf, zid, FALSE); +} + +/* Kill or rejuvenate a job, given the jobid. */ + +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; + } + + /* Now we have to read through the file to identify any temporary + files. */ + 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; + } + + /* You are only permitted to delete a job if you submitted it or + if you are root or uucp. */ + 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 = ussettime (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 = ussettime (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; +} + +/* Get the time a work job was queued. */ + +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; +} + +/* Get the time a file was created (actually, the time it was last + modified). */ + +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; +} + +/* Start getting the status files. */ + +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; +} + +/* Get the next status file. */ + +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; + + /* Hack seriously; fsysdep_get_status only looks at the + zname element of the qsys argument, so if we fake that we + can read the status file. This should really be done + differently. */ + ssys.uuconf_zname = qentry->d_name; + if (fsysdep_get_status (&ssys, qstat, (boolean *) NULL)) + return zbufcpy (qentry->d_name); + + /* If fsysdep_get_status fails, it will output an error + message. We just continue with the next entry, so that + most of the status files will be displayed. */ + } + } +} + +/* Finish getting the status file. */ + +void +usysdep_all_status_free (phold) + pointer phold; +{ + DIR *qdir = (DIR *) phold; + + (void) closedir (qdir); +} + +/* Get the status of all processes holding lock files. We do this by + invoking ps after we've figured out the process entries to use. */ + +boolean +fsysdep_lock_status () +{ + DIR *qdir; + struct dirent *qentry; + int calc; + int *pai; + 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; + } + + /* We look for entries that start with "LCK.." and ignore everything + else. This won't find all possible lock files, but it should + find all the locks on terminals and systems. */ + + calc = 0; + pai = NULL; + cgot = 0; + while ((qentry = readdir (qdir)) != NULL) + { + char *zname; + int o; +#if HAVE_V2_LOCKFILES + int i; +#else + char ab[12]; +#endif + int cread; + int ierr; + int ipid; + + 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_V2_LOCKFILES + ipid = i; +#else + ab[cread] = '\0'; + ipid = strtol (ab, (char **) NULL, 10); +#endif + + printf ("%s: %d\n", qentry->d_name, ipid); + + if (cgot >= calc) + { + calc += 10; + pai = (int *) xrealloc ((pointer) pai, calc * sizeof (int)); + } + + pai[cgot] = ipid; + ++cgot; + } + + if (cgot == 0) + return TRUE; + + aidescs[0] = SPAWN_NULL; + aidescs[1] = 1; + aidescs[2] = 2; + + /* Parse PS_PROGRAM into an array of arguments. */ + 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 + /* We have to invoke ps multiple times. */ + { + int i; + char *zlast, *zset; + + zlast = pazargs[cargs - 1]; + zset = zbufalc (strlen (zlast) + 20); + for (i = 0; i < cgot; i++) + { + pid_t ipid; + + sprintf (zset, "%s%d", zlast, pai[i]); + pazargs[cargs - 1] = zset; + + 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); + } +#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, "%d", 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; +} |
