home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / uucp-1.04 / unix / statsb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-13  |  12.0 KB  |  573 lines

  1. /* statsb.c
  2.    System dependent routines for uustat.
  3.  
  4.    Copyright (C) 1992 Ian Lance Taylor
  5.  
  6.    This file is part of the Taylor UUCP package.
  7.  
  8.    This program is free software; you can redistribute it and/or
  9.    modify it under the terms of the GNU General Public License as
  10.    published by the Free Software Foundation; either version 2 of the
  11.    License, or (at your option) any later version.
  12.  
  13.    This program is distributed in the hope that it will be useful, but
  14.    WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.    General Public License for more details.
  17.  
  18.    You should have received a copy of the GNU General Public License
  19.    along with this program; if not, write to the Free Software
  20.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22.    The author of the program may be contacted at ian@airs.com or
  23.    c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
  24.    */
  25.  
  26. #include "uucp.h"
  27.  
  28. #if USE_RCS_ID
  29. const char statsb_rcsid[] = "$Id: statsb.c,v 1.10 1992/11/14 16:14:07 ian Rel $";
  30. #endif
  31.  
  32. #include "uudefs.h"
  33. #include "uuconf.h"
  34. #include "sysdep.h"
  35. #include "system.h"
  36.  
  37. #include <errno.h>
  38.  
  39. #if HAVE_FCNTL_H
  40. #include <fcntl.h>
  41. #else
  42. #if HAVE_SYS_FILE_H
  43. #include <sys/file.h>
  44. #endif
  45. #endif
  46.  
  47. #ifndef O_RDONLY
  48. #define O_RDONLY 0
  49. #define O_WRONLY 1
  50. #define O_RDWR 2
  51. #endif
  52.  
  53. #ifndef O_NOCTTY
  54. #define O_NOCTTY 0
  55. #endif
  56.  
  57. #if HAVE_OPENDIR
  58. #if HAVE_DIRENT_H
  59. #include <dirent.h>
  60. #else /* ! HAVE_DIRENT_H */
  61. #include <sys/dir.h>
  62. #define dirent direct
  63. #endif /* ! HAVE_DIRENT_H */
  64. #endif /* HAVE_OPENDIR */
  65.  
  66. #if HAVE_TIME_H
  67. #include <time.h>
  68. #endif
  69.  
  70. #if HAVE_UTIME_H
  71. #include <utime.h>
  72. #endif
  73.  
  74. /* Local functions.  */
  75.  
  76. static int ussettime P((const char *z, time_t inow));
  77. static boolean fskill_or_rejuv P((pointer puuconf, const char *zid,
  78.                   boolean fkill));
  79.  
  80. /* See whether the user is permitted to kill arbitrary jobs.  This is
  81.    true only for root and uucp.  We check for uucp by seeing if the
  82.    real user ID and the effective user ID are the same; this works
  83.    because we should be suid to uucp, so our effective user ID will
  84.    always be uucp while our real user ID will be whoever ran the
  85.    program.  */
  86.  
  87. boolean
  88. fsysdep_privileged ()
  89. {
  90.   uid_t iuid;
  91.  
  92.   iuid = getuid ();
  93.   return iuid == 0 || iuid == geteuid ();
  94. }
  95.  
  96. /* Set file access time to the present.  On many systems this could be
  97.    done by passing NULL to utime, but on some that doesn't work.  This
  98.    routine is not time critical, so we never rely on NULL.  */
  99.  
  100. static int
  101. ussettime(z, inow)
  102.      const char *z;
  103.      time_t inow;
  104. {
  105. #if HAVE_UTIME_H
  106.   struct utimbuf s;
  107.  
  108.   s.actime = inow;
  109.   s.modtime = inow;
  110.   return utime ((char *) z, &s);
  111. #else
  112.   time_t ai[2];
  113.  
  114.   ai[0] = inow;
  115.   ai[1] = inow;
  116.   return utime ((char *) z, ai);
  117. #endif
  118. }
  119.  
  120. /* Kill a job, given the jobid.  */
  121.  
  122. boolean
  123. fsysdep_kill_job (puuconf, zid)
  124.      pointer puuconf;
  125.      const char *zid;
  126. {
  127.   return fskill_or_rejuv (puuconf, zid, TRUE);
  128. }
  129.  
  130. /* Rejuvenate a job, given the jobid.  */
  131.  
  132. boolean
  133. fsysdep_rejuvenate_job (puuconf, zid)
  134.      pointer puuconf;
  135.      const char *zid;
  136. {
  137.   return fskill_or_rejuv (puuconf, zid, FALSE);
  138. }
  139.  
  140. /* Kill or rejuvenate a job, given the jobid.  */
  141.  
  142. static boolean
  143. fskill_or_rejuv (puuconf, zid, fkill)
  144.      pointer puuconf;
  145.      const char *zid;
  146.      boolean fkill;
  147. {
  148.   char *zfile;
  149.   char *zsys;
  150.   char bgrade;
  151.   time_t inow = 0;
  152.   int iuuconf;
  153.   struct uuconf_system ssys;
  154.   FILE *e;
  155.   boolean fret;
  156.   char *zline;
  157.   size_t cline;
  158.   int isys;
  159.  
  160.   zfile = zsjobid_to_file (zid, &zsys, &bgrade);
  161.   if (zfile == NULL)
  162.     return FALSE;
  163.  
  164.   if (! fkill)
  165.     inow = time ((time_t *) NULL);
  166.  
  167.   iuuconf = uuconf_system_info (puuconf, zsys, &ssys);
  168.   if (iuuconf == UUCONF_NOT_FOUND)
  169.     {
  170.       if (! funknown_system (puuconf, zsys, &ssys))
  171.     {
  172.       ulog (LOG_ERROR, "%s: Bad job id", zid);
  173.       ubuffree (zfile);
  174.       ubuffree (zsys);
  175.       return FALSE;
  176.     }
  177.     }
  178.   else if (iuuconf != UUCONF_SUCCESS)
  179.     {
  180.       ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
  181.       ubuffree (zfile);
  182.       ubuffree (zsys);
  183.       return FALSE;
  184.     }
  185.  
  186.   e = fopen (zfile, "r");
  187.   if (e == NULL)
  188.     {
  189.       if (errno == ENOENT)
  190.     ulog (LOG_ERROR, "%s: Job not found", zid);
  191.       else
  192.     ulog (LOG_ERROR, "fopen (%s): %s", zfile, strerror (errno));
  193.       (void) uuconf_system_free (puuconf, &ssys);
  194.       ubuffree (zfile);
  195.       ubuffree (zsys);
  196.       return FALSE;
  197.     }
  198.  
  199.   /* Now we have to read through the file to identify any temporary
  200.      files.  */
  201.   fret = TRUE;
  202.   zline = NULL;
  203.   cline = 0;
  204.   while (getline (&zline, &cline, e) > 0)
  205.     {
  206.       struct scmd s;
  207.  
  208.       if (! fparse_cmd (zline, &s))
  209.     {
  210.       ulog (LOG_ERROR, "Bad line in command file %s", zfile);
  211.       fret = FALSE;
  212.       continue;
  213.     }
  214.  
  215.       /* You are only permitted to delete a job if you submitted it or
  216.      if you are root or uucp.  */
  217.       if (strcmp (s.zuser, zsysdep_login_name ()) != 0
  218.       && ! fsysdep_privileged ())
  219.     {
  220.       ulog (LOG_ERROR, "%s: Not submitted by you", zid);
  221.       xfree ((pointer) zline);
  222.       (void) fclose (e);
  223.       (void) uuconf_system_free (puuconf, &ssys);
  224.       ubuffree (zfile);
  225.       ubuffree (zsys);
  226.       return FALSE;
  227.     }
  228.  
  229.       if (s.bcmd == 'S' || s.bcmd == 'E')
  230.     {
  231.       char *ztemp;
  232.  
  233.       ztemp = zsfind_file (s.ztemp, ssys.uuconf_zname, bgrade);
  234.       if (ztemp == NULL)
  235.         fret = FALSE;
  236.       else
  237.         {
  238.           if (fkill)
  239.         isys = remove (ztemp);
  240.           else
  241.         isys = ussettime (ztemp, inow);
  242.  
  243.           if (isys != 0 && errno != ENOENT)
  244.         {
  245.           ulog (LOG_ERROR, "%s (%s): %s",
  246.             fkill ? "remove" : "utime", ztemp,
  247.             strerror (errno));
  248.           fret = FALSE;
  249.         }
  250.  
  251.           ubuffree (ztemp);
  252.         }
  253.     }
  254.     }
  255.  
  256.   xfree ((pointer) zline);
  257.   (void) fclose (e);
  258.   (void) uuconf_system_free (puuconf, &ssys);
  259.   ubuffree (zsys);
  260.  
  261.   if (fkill)
  262.     isys = remove (zfile);
  263.   else
  264.     isys = ussettime (zfile, inow);
  265.  
  266.   if (isys != 0 && errno != ENOENT)
  267.     {
  268.       ulog (LOG_ERROR, "%s (%s): %s", fkill ? "remove" : "utime",
  269.         zfile, strerror (errno));
  270.       fret = FALSE;
  271.     }
  272.  
  273.   ubuffree (zfile);
  274.  
  275.   return fret;
  276. }
  277.  
  278. /* Get the time a work job was queued.  */
  279.  
  280. long
  281. ixsysdep_work_time (qsys, pseq)
  282.      const struct uuconf_system *qsys;
  283.      pointer pseq;
  284. {
  285.   char *zjobid, *zfile;
  286.   long iret;
  287.  
  288.   zjobid = zsysdep_jobid (qsys, pseq);
  289.   zfile = zsjobid_to_file (zjobid, (char **) NULL, (char *) NULL);
  290.   if (zfile == NULL)
  291.     return 0;
  292.   ubuffree (zjobid);
  293.   iret = ixsysdep_file_time (zfile);
  294.   ubuffree (zfile);
  295.   return iret;
  296. }
  297.  
  298. /* Get the time a file was created (actually, the time it was last
  299.    modified).  */
  300.  
  301. long
  302. ixsysdep_file_time (zfile)
  303.      const char *zfile;
  304. {
  305.   struct stat s;
  306.  
  307.   if (stat ((char *) zfile, &s) < 0)
  308.     {
  309.       if (errno != ENOENT)
  310.     ulog (LOG_ERROR, "stat (%s): %s", zfile, strerror (errno));
  311.       return ixsysdep_time ((long *) NULL);
  312.     }
  313.  
  314.   return (long) s.st_mtime;
  315. }
  316.  
  317. /* Start getting the status files.  */
  318.  
  319. boolean
  320. fsysdep_all_status_init (phold)
  321.      pointer *phold;
  322. {
  323.   DIR *qdir;
  324.  
  325.   qdir = opendir ((char *) ".Status");
  326.   if (qdir == NULL)
  327.     {
  328.       ulog (LOG_ERROR, "opendir (.Status): %s", strerror (errno));
  329.       return FALSE;
  330.     }
  331.  
  332.   *phold = (pointer) qdir;
  333.   return TRUE;
  334. }
  335.  
  336. /* Get the next status file.  */
  337.  
  338. char *
  339. zsysdep_all_status (phold, pferr, qstat)
  340.      pointer phold;
  341.      boolean *pferr;
  342.      struct sstatus *qstat;
  343. {
  344.   DIR *qdir = (DIR *) phold;
  345.   struct dirent *qentry;
  346.  
  347.   while (TRUE)
  348.     {
  349.       errno = 0;
  350.       qentry = readdir (qdir);
  351.       if (qentry == NULL)
  352.     {
  353.       if (errno == 0)
  354.         *pferr = FALSE;
  355.       else
  356.         {
  357.           ulog (LOG_ERROR, "readdir: %s", strerror (errno));
  358.           *pferr = TRUE;
  359.         }
  360.       return NULL;
  361.     }
  362.  
  363.       if (qentry->d_name[0] != '.')
  364.     {
  365.       struct uuconf_system ssys;
  366.  
  367.       /* Hack seriously; fsysdep_get_status only looks at the
  368.          zname element of the qsys argument, so if we fake that we
  369.          can read the status file.  This should really be done
  370.          differently.  */
  371.       ssys.uuconf_zname = qentry->d_name;
  372.       if (fsysdep_get_status (&ssys, qstat, (boolean *) NULL))
  373.         return zbufcpy (qentry->d_name);
  374.  
  375.       /* If fsysdep_get_status fails, it will output an error
  376.          message.  We just continue with the next entry, so that
  377.          most of the status files will be displayed.  */
  378.     }
  379.     }
  380. }
  381.  
  382. /* Finish getting the status file.  */
  383.  
  384. void
  385. usysdep_all_status_free (phold)
  386.      pointer phold;
  387. {
  388.   DIR *qdir = (DIR *) phold;
  389.  
  390.   (void) closedir (qdir);
  391. }
  392.  
  393. /* Get the status of all processes holding lock files.  We do this by
  394.    invoking ps after we've figured out the process entries to use.  */
  395.  
  396. boolean
  397. fsysdep_lock_status ()
  398. {
  399.   DIR *qdir;
  400.   struct dirent *qentry;
  401.   int calc;
  402.   int *pai;
  403.   int cgot;
  404.   int aidescs[3];
  405.   char *zcopy, *ztok;
  406.   int cargs, iarg;
  407.   char **pazargs;
  408.  
  409.   qdir = opendir ((char *) zSlockdir);
  410.   if (qdir == NULL)
  411.     {
  412.       ulog (LOG_ERROR, "opendir (%s): %s", zSlockdir, strerror (errno));
  413.       return FALSE;
  414.     }
  415.  
  416.   /* We look for entries that start with "LCK.." and ignore everything
  417.      else.  This won't find all possible lock files, but it should
  418.      find all the locks on terminals and systems.  */
  419.  
  420.   calc = 0;
  421.   pai = NULL;
  422.   cgot = 0;
  423.   while ((qentry = readdir (qdir)) != NULL)
  424.     {
  425.       char *zname;
  426.       int o;
  427. #if HAVE_V2_LOCKFILES
  428.       int i;
  429. #else
  430.       char ab[12];
  431. #endif
  432.       int cread;
  433.       int ierr;
  434.       int ipid;
  435.  
  436.       if (strncmp (qentry->d_name, "LCK..", sizeof "LCK.." - 1) != 0)
  437.     continue;
  438.  
  439.       zname = zsysdep_in_dir (zSlockdir, qentry->d_name);
  440.       o = open ((char *) zname, O_RDONLY | O_NOCTTY, 0);
  441.       if (o < 0)
  442.     {
  443.       if (errno != ENOENT)
  444.         ulog (LOG_ERROR, "open (%s): %s", zname, strerror (errno));
  445.       ubuffree (zname);
  446.       continue;
  447.     }
  448.  
  449. #if HAVE_V2_LOCKFILES
  450.       cread = read (o, &i, sizeof i);
  451. #else
  452.       cread = read (o, ab, sizeof ab - 1);
  453. #endif
  454.  
  455.       ierr = errno;
  456.       (void) close (o);
  457.  
  458.       if (cread < 0)
  459.     {
  460.       ulog (LOG_ERROR, "read %s: %s", zname, strerror (ierr));
  461.       ubuffree (zname);
  462.       continue;
  463.     }
  464.  
  465.       ubuffree (zname);
  466.  
  467. #if HAVE_V2_LOCKFILES
  468.       ipid = i;
  469. #else
  470.       ab[cread] = '\0';
  471.       ipid = strtol (ab, (char **) NULL, 10);
  472. #endif
  473.  
  474.       printf ("%s: %d\n", qentry->d_name, ipid);
  475.  
  476.       if (cgot >= calc)
  477.     {
  478.       calc += 10;
  479.       pai = (int *) xrealloc ((pointer) pai, calc * sizeof (int));
  480.     }
  481.  
  482.       pai[cgot] = ipid;
  483.       ++cgot;
  484.     }
  485.  
  486.   if (cgot == 0)
  487.     return TRUE;
  488.  
  489.   aidescs[0] = SPAWN_NULL;
  490.   aidescs[1] = 1;
  491.   aidescs[2] = 2;
  492.  
  493.   /* Parse PS_PROGRAM into an array of arguments.  */
  494.   zcopy = zbufcpy (PS_PROGRAM);
  495.  
  496.   cargs = 0;
  497.   for (ztok = strtok (zcopy, " \t");
  498.        ztok != NULL;
  499.        ztok = strtok ((char *) NULL, " \t"))
  500.     ++cargs;
  501.  
  502.   pazargs = (char **) xmalloc ((cargs + 1) * sizeof (char *));
  503.  
  504.   memcpy (zcopy, PS_PROGRAM, sizeof PS_PROGRAM);
  505.   for (ztok = strtok (zcopy, " \t"), iarg = 0;
  506.        ztok != NULL;
  507.        ztok = strtok ((char *) NULL, " \t"), ++iarg)
  508.     pazargs[iarg] = ztok;
  509.   pazargs[iarg] = NULL;
  510.  
  511. #if ! HAVE_PS_MULTIPLE
  512.   /* We have to invoke ps multiple times.  */
  513.   {
  514.     int i;
  515.     char *zlast, *zset;
  516.  
  517.     zlast = pazargs[cargs - 1];
  518.     zset = zbufalc (strlen (zlast) + 20);
  519.     for (i = 0; i < cgot; i++)
  520.       {
  521.     pid_t ipid;
  522.  
  523.     sprintf (zset, "%s%d", zlast, pai[i]);
  524.     pazargs[cargs - 1] = zset;
  525.  
  526.     ipid = ixsspawn ((const char **) pazargs, aidescs, FALSE, FALSE,
  527.              (const char *) NULL, FALSE, TRUE,
  528.              (const char *) NULL, (const char *) NULL,
  529.              (const char *) NULL);
  530.     if (ipid < 0)
  531.       ulog (LOG_ERROR, "ixsspawn: %s", strerror (errno));
  532.     else
  533.       (void) ixswait ((unsigned long) ipid, PS_PROGRAM);
  534.       }
  535.     ubuffree (zset);
  536.   }
  537. #else
  538.   {
  539.     char *zlast;
  540.     int i;
  541.     pid_t ipid;
  542.  
  543.     zlast = zbufalc (strlen (pazargs[cargs - 1]) + cgot * 20 + 1);
  544.     strcpy (zlast, pazargs[cargs - 1]);
  545.     for (i = 0; i < cgot; i++)
  546.       {
  547.     char ab[20];
  548.  
  549.     sprintf (ab, "%d", pai[i]);
  550.     strcat (zlast, ab);
  551.     if (i + 1 < cgot)
  552.       strcat (zlast, ",");
  553.       }
  554.     pazargs[cargs - 1] = zlast;
  555.  
  556.     ipid = ixsspawn ((const char **) pazargs, aidescs, FALSE, FALSE,
  557.              (const char *) NULL, FALSE, TRUE,
  558.              (const char *) NULL, (const char *) NULL,
  559.              (const char *) NULL);
  560.     if (ipid < 0)
  561.       ulog (LOG_ERROR, "ixsspawn: %s", strerror (errno));
  562.     else
  563.       (void) ixswait ((unsigned long) ipid, PS_PROGRAM);
  564.     ubuffree (zlast);
  565.   }
  566. #endif    
  567.  
  568.   ubuffree (zcopy);
  569.   xfree ((pointer) pazargs);
  570.  
  571.   return TRUE;
  572. }
  573.