home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / uucp / Uucp.framework / unix.subproj / statsb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-09  |  13.7 KB  |  635 lines

  1. /* statsb.c
  2.    System dependent routines for uustat.
  3.  
  4.    Copyright (C) 1992, 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  21.  
  22.    The author of the program may be contacted at ian@airs.com or
  23.    c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
  24.    */
  25.  
  26. #include "uucp.h"
  27.  
  28. #if USE_RCS_ID
  29. const char statsb_rcsid[] = "$Id: statsb.c,v 1.19 1995/06/21 19:20:39 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 issettime P((const char *z, time_t inow));
  77. static boolean fskill_or_rejuv P((pointer puuconf, const char *zid,
  78.                   boolean fkill));
  79.  
  80. /* Set file access time to the present.  On many systems this could be
  81.    done by passing NULL to utime, but on some that doesn't work.  This
  82.    routine is not time critical, so we never rely on NULL.  */
  83.  
  84. static int
  85. issettime(z, inow)
  86.      const char *z;
  87.      time_t inow;
  88. {
  89. #if HAVE_UTIME_H
  90.   struct utimbuf s;
  91.  
  92.   s.actime = inow;
  93.   s.modtime = inow;
  94.   return utime ((char *) z, &s);
  95. #else
  96.   time_t ai[2];
  97.  
  98.   ai[0] = inow;
  99.   ai[1] = inow;
  100.   return utime ((char *) z, ai);
  101. #endif
  102. }
  103.  
  104. /* Kill a job, given the jobid.  */
  105.  
  106. boolean
  107. fsysdep_kill_job (puuconf, zid)
  108.      pointer puuconf;
  109.      const char *zid;
  110. {
  111.   return fskill_or_rejuv (puuconf, zid, TRUE);
  112. }
  113.  
  114. /* Rejuvenate a job, given the jobid.  */
  115.  
  116. boolean
  117. fsysdep_rejuvenate_job (puuconf, zid)
  118.      pointer puuconf;
  119.      const char *zid;
  120. {
  121.   return fskill_or_rejuv (puuconf, zid, FALSE);
  122. }
  123.  
  124. /* Kill or rejuvenate a job, given the jobid.  */
  125.  
  126. static boolean
  127. fskill_or_rejuv (puuconf, zid, fkill)
  128.      pointer puuconf;
  129.      const char *zid;
  130.      boolean fkill;
  131. {
  132.   char *zfile;
  133.   char *zsys;
  134.   char bgrade;
  135.   time_t inow = 0;
  136.   int iuuconf;
  137.   struct uuconf_system ssys;
  138.   FILE *e;
  139.   boolean fret;
  140.   char *zline;
  141.   size_t cline;
  142.   int isys;
  143.  
  144.   zfile = zsjobid_to_file (zid, &zsys, &bgrade);
  145.   if (zfile == NULL)
  146.     return FALSE;
  147.  
  148.   if (! fkill)
  149.     inow = time ((time_t *) NULL);
  150.  
  151.   iuuconf = uuconf_system_info (puuconf, zsys, &ssys);
  152.   if (iuuconf == UUCONF_NOT_FOUND)
  153.     {
  154.       if (! funknown_system (puuconf, zsys, &ssys))
  155.     {
  156.       ulog (LOG_ERROR, "%s: Bad job id", zid);
  157.       ubuffree (zfile);
  158.       ubuffree (zsys);
  159.       return FALSE;
  160.     }
  161.     }
  162.   else if (iuuconf != UUCONF_SUCCESS)
  163.     {
  164.       ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
  165.       ubuffree (zfile);
  166.       ubuffree (zsys);
  167.       return FALSE;
  168.     }
  169.  
  170.   e = fopen (zfile, "r");
  171.   if (e == NULL)
  172.     {
  173.       if (errno == ENOENT)
  174.     ulog (LOG_ERROR, "%s: Job not found", zid);
  175.       else
  176.     ulog (LOG_ERROR, "fopen (%s): %s", zfile, strerror (errno));
  177.       (void) uuconf_system_free (puuconf, &ssys);
  178.       ubuffree (zfile);
  179.       ubuffree (zsys);
  180.       return FALSE;
  181.     }
  182.  
  183.   /* Now we have to read through the file to identify any temporary
  184.      files.  */
  185.   fret = TRUE;
  186.   zline = NULL;
  187.   cline = 0;
  188.   while (getline (&zline, &cline, e) > 0)
  189.     {
  190.       struct scmd s;
  191.  
  192.       if (! fparse_cmd (zline, &s))
  193.     {
  194.       ulog (LOG_ERROR, "Bad line in command file %s", zfile);
  195.       fret = FALSE;
  196.       continue;
  197.     }
  198.  
  199.       /* You are only permitted to delete a job if you submitted it or
  200.      if you are root or uucp.  */
  201.       if (strcmp (s.zuser, zsysdep_login_name ()) != 0
  202.       && ! fsysdep_privileged ())
  203.     {
  204.       ulog (LOG_ERROR, "%s: Not submitted by you", zid);
  205.       xfree ((pointer) zline);
  206.       (void) fclose (e);
  207.       (void) uuconf_system_free (puuconf, &ssys);
  208.       ubuffree (zfile);
  209.       ubuffree (zsys);
  210.       return FALSE;
  211.     }
  212.  
  213.       if (s.bcmd == 'S' || s.bcmd == 'E')
  214.     {
  215.       char *ztemp;
  216.  
  217.       ztemp = zsfind_file (s.ztemp, ssys.uuconf_zname, bgrade);
  218.       if (ztemp == NULL)
  219.         fret = FALSE;
  220.       else
  221.         {
  222.           if (fkill)
  223.         isys = remove (ztemp);
  224.           else
  225.         isys = issettime (ztemp, inow);
  226.  
  227.           if (isys != 0 && errno != ENOENT)
  228.         {
  229.           ulog (LOG_ERROR, "%s (%s): %s",
  230.             fkill ? "remove" : "utime", ztemp,
  231.             strerror (errno));
  232.           fret = FALSE;
  233.         }
  234.  
  235.           ubuffree (ztemp);
  236.         }
  237.     }
  238.     }
  239.  
  240.   xfree ((pointer) zline);
  241.   (void) fclose (e);
  242.   (void) uuconf_system_free (puuconf, &ssys);
  243.   ubuffree (zsys);
  244.  
  245.   if (fkill)
  246.     isys = remove (zfile);
  247.   else
  248.     isys = issettime (zfile, inow);
  249.  
  250.   if (isys != 0 && errno != ENOENT)
  251.     {
  252.       ulog (LOG_ERROR, "%s (%s): %s", fkill ? "remove" : "utime",
  253.         zfile, strerror (errno));
  254.       fret = FALSE;
  255.     }
  256.  
  257.   ubuffree (zfile);
  258.  
  259.   return fret;
  260. }
  261.  
  262. /* Get the time a work job was queued.  */
  263.  
  264. long
  265. ixsysdep_work_time (qsys, pseq)
  266.      const struct uuconf_system *qsys;
  267.      pointer pseq;
  268. {
  269.   char *zjobid, *zfile;
  270.   long iret;
  271.  
  272.   zjobid = zsysdep_jobid (qsys, pseq);
  273.   zfile = zsjobid_to_file (zjobid, (char **) NULL, (char *) NULL);
  274.   if (zfile == NULL)
  275.     return 0;
  276.   ubuffree (zjobid);
  277.   iret = ixsysdep_file_time (zfile);
  278.   ubuffree (zfile);
  279.   return iret;
  280. }
  281.  
  282. /* Get the time a file was created (actually, the time it was last
  283.    modified).  */
  284.  
  285. long
  286. ixsysdep_file_time (zfile)
  287.      const char *zfile;
  288. {
  289.   struct stat s;
  290.  
  291.   if (stat ((char *) zfile, &s) < 0)
  292.     {
  293.       if (errno != ENOENT)
  294.     ulog (LOG_ERROR, "stat (%s): %s", zfile, strerror (errno));
  295.       return ixsysdep_time ((long *) NULL);
  296.     }
  297.  
  298.   return (long) s.st_mtime;
  299. }
  300.  
  301. /* Set the time of a file to the current time.  */
  302.  
  303. boolean
  304. fsysdep_touch_file (zfile)
  305.      const char *zfile;
  306. {
  307.   if (issettime (zfile, time ((time_t *) NULL)) != 0)
  308.     {
  309.       ulog (LOG_ERROR, "utime (%s): %s", zfile, strerror (errno));
  310.       return FALSE;
  311.     }
  312.  
  313.   return TRUE;
  314. }
  315.  
  316. /* Start getting the status files.  */
  317.  
  318. boolean
  319. fsysdep_all_status_init (phold)
  320.      pointer *phold;
  321. {
  322.   DIR *qdir;
  323.  
  324.   qdir = opendir ((char *) ".Status");
  325.   if (qdir == NULL)
  326.     {
  327.       ulog (LOG_ERROR, "opendir (.Status): %s", strerror (errno));
  328.       return FALSE;
  329.     }
  330.  
  331.   *phold = (pointer) qdir;
  332.   return TRUE;
  333. }
  334.  
  335. /* Get the next status file.  */
  336.  
  337. char *
  338. zsysdep_all_status (phold, pferr, qstat)
  339.      pointer phold;
  340.      boolean *pferr;
  341.      struct sstatus *qstat;
  342. {
  343.   DIR *qdir = (DIR *) phold;
  344.   struct dirent *qentry;
  345.  
  346.   while (TRUE)
  347.     {
  348.       errno = 0;
  349.       qentry = readdir (qdir);
  350.       if (qentry == NULL)
  351.     {
  352.       if (errno == 0)
  353.         *pferr = FALSE;
  354.       else
  355.         {
  356.           ulog (LOG_ERROR, "readdir: %s", strerror (errno));
  357.           *pferr = TRUE;
  358.         }
  359.       return NULL;
  360.     }
  361.  
  362.       if (qentry->d_name[0] != '.')
  363.     {
  364.       struct uuconf_system ssys;
  365.  
  366.       /* Hack seriously; fsysdep_get_status only looks at the
  367.          zname element of the qsys argument, so if we fake that we
  368.          can read the status file.  This should really be done
  369.          differently.  */
  370.       ssys.uuconf_zname = qentry->d_name;
  371.       if (fsysdep_get_status (&ssys, qstat, (boolean *) NULL))
  372.         return zbufcpy (qentry->d_name);
  373.  
  374.       /* If fsysdep_get_status fails, it will output an error
  375.          message.  We just continue with the next entry, so that
  376.          most of the status files will be displayed.  */
  377.     }
  378.     }
  379. }
  380.  
  381. /* Finish getting the status file.  */
  382.  
  383. void
  384. usysdep_all_status_free (phold)
  385.      pointer phold;
  386. {
  387.   DIR *qdir = (DIR *) phold;
  388.  
  389.   (void) closedir (qdir);
  390. }
  391.  
  392. /* Get the status of all processes holding lock files.  We do this by
  393.    invoking ps after we've figured out the process entries to use.  */
  394.  
  395. boolean
  396. fsysdep_lock_status ()
  397. {
  398.   DIR *qdir;
  399.   struct dirent *qentry;
  400.   int calc;
  401.   pid_t *pai;
  402. #if HAVE_QNX_LOCKFILES
  403.   nid_t *painid;
  404. #endif
  405.   int cgot;
  406.   int aidescs[3];
  407.   char *zcopy, *ztok;
  408.   int cargs, iarg;
  409.   char **pazargs;
  410.  
  411.   qdir = opendir ((char *) zSlockdir);
  412.   if (qdir == NULL)
  413.     {
  414.       ulog (LOG_ERROR, "opendir (%s): %s", zSlockdir, strerror (errno));
  415.       return FALSE;
  416.     }
  417.  
  418.   /* We look for entries that start with "LCK.." and ignore everything
  419.      else.  This won't find all possible lock files, but it should
  420.      find all the locks on terminals and systems.  */
  421.  
  422.   calc = 0;
  423.   pai = NULL;
  424.   cgot = 0;
  425. #if HAVE_QNX_LOCKFILES
  426.   painid = NULL;
  427. #endif
  428.   while ((qentry = readdir (qdir)) != NULL)
  429.     {
  430.       char *zname;
  431.       int o;
  432. #if HAVE_QNX_LOCKFILES
  433.       nid_t inid;
  434.       char ab[23];
  435.       char *zend;
  436. #else
  437. #if HAVE_V2_LOCKFILES
  438.       int i;
  439. #else
  440.       char ab[12];
  441. #endif
  442. #endif
  443.       int cread;
  444.       int ierr;
  445.       pid_t ipid;
  446.       int icheck;
  447.  
  448.       if (strncmp (qentry->d_name, "LCK..", sizeof "LCK.." - 1) != 0)
  449.     continue;
  450.  
  451.       zname = zsysdep_in_dir (zSlockdir, qentry->d_name);
  452.       o = open ((char *) zname, O_RDONLY | O_NOCTTY, 0);
  453.       if (o < 0)
  454.     {
  455.       if (errno != ENOENT)
  456.         ulog (LOG_ERROR, "open (%s): %s", zname, strerror (errno));
  457.       ubuffree (zname);
  458.       continue;
  459.     }
  460.  
  461. #if HAVE_V2_LOCKFILES
  462.       cread = read (o, &i, sizeof i);
  463. #else
  464.       cread = read (o, ab, sizeof ab - 1);
  465. #endif
  466.  
  467.       ierr = errno;
  468.       (void) close (o);
  469.  
  470.       if (cread < 0)
  471.     {
  472.       ulog (LOG_ERROR, "read %s: %s", zname, strerror (ierr));
  473.       ubuffree (zname);
  474.       continue;
  475.     }
  476.  
  477.       ubuffree (zname);
  478.  
  479. #if HAVE_QNX_LOCKFILES
  480.       ab[cread] = '\0';
  481.       ipid = (pid_t) strtol (ab, &zend, 10);
  482.       inid = (nid_t) strtol (zend, (char **) NULL, 10);
  483. #else
  484. #if HAVE_V2_LOCKFILES
  485.       ipid = (pid_t) i;
  486. #else
  487.       ab[cread] = '\0';
  488.       ipid = (pid_t) strtol (ab, (char **) NULL, 10);
  489. #endif
  490. #endif
  491.  
  492. #if HAVE_QNX_LOCKFILES
  493.       printf ("%s: %ld %ld\n", qentry->d_name, (long) inid, (long) ipid);
  494. #else
  495.       printf ("%s: %ld\n", qentry->d_name, (long) ipid);
  496. #endif
  497.  
  498.       for (icheck = 0; icheck < cgot; icheck++)
  499.     if (pai[icheck] == ipid)
  500.       break;
  501.       if (icheck < cgot)
  502.     continue;
  503.  
  504.       if (cgot >= calc)
  505.     {
  506.       calc += 10;
  507.       pai = (pid_t *) xrealloc ((pointer) pai, calc * sizeof (pid_t));
  508. #if HAVE_QNX_LOCKFILES
  509.       painid = (nid_t *) xrealloc ((pointer) painid,
  510.                        calc * sizeof (nid_t));
  511. #endif
  512.     }
  513.  
  514.       pai[cgot] = ipid;
  515. #if HAVE_QNX_LOCKFILES
  516.       painid[cgot] = inid;
  517. #endif
  518.       ++cgot;
  519.     }
  520.  
  521.   if (cgot == 0)
  522.     return TRUE;
  523.  
  524.   aidescs[0] = SPAWN_NULL;
  525.   aidescs[1] = 1;
  526.   aidescs[2] = 2;
  527.  
  528.   /* Parse PS_PROGRAM into an array of arguments.  */
  529.   zcopy = zbufcpy (PS_PROGRAM);
  530.  
  531.   cargs = 0;
  532.   for (ztok = strtok (zcopy, " \t");
  533.        ztok != NULL;
  534.        ztok = strtok ((char *) NULL, " \t"))
  535.     ++cargs;
  536.  
  537.   pazargs = (char **) xmalloc ((cargs + 1) * sizeof (char *));
  538.  
  539.   memcpy (zcopy, PS_PROGRAM, sizeof PS_PROGRAM);
  540.   for (ztok = strtok (zcopy, " \t"), iarg = 0;
  541.        ztok != NULL;
  542.        ztok = strtok ((char *) NULL, " \t"), ++iarg)
  543.     pazargs[iarg] = ztok;
  544.   pazargs[iarg] = NULL;
  545.  
  546. #if ! HAVE_PS_MULTIPLE
  547.   /* We have to invoke ps multiple times.  */
  548.   {
  549.     int i;
  550.     char *zlast, *zset;
  551. #if HAVE_QNX_LOCKFILES
  552.     char *zpenultimate, *zsetnid;
  553. #endif /* HAVE_QNX_LOCKFILES */
  554.  
  555.     zlast = pazargs[cargs - 1];
  556.     zset = zbufalc (strlen (zlast) + 20);
  557.  
  558. #if HAVE_QNX_LOCKFILES
  559.     /* We assume in this case that PS_PROGRAM ends with " -n -p".
  560.        Thus, the last argument is "-p" and the second-to-last
  561.        (penultimate) argument is "-n".  We modify them to read "-n###"
  562.        and "-p###" where "###" is the node ID and the process ID,
  563.        respectively.  This seems like quite a roundabout way of doing
  564.        things.  Why don't we just leave the " -n -p" part out of
  565.        PS_PROGRAM and construct the "-n###" and "-p###" arguments here
  566.        from scratch?  Because that would not fit as well with how the
  567.        code works for the other systems and would require larger
  568.        changes. */
  569.     zpenultimate = pazargs[cargs - 2];
  570.     zsetnid = zbufalc (strlen (zpenultimate) + 20);
  571. #endif
  572.  
  573.     for (i = 0; i < cgot; i++)
  574.       {
  575.     pid_t ipid;
  576.  
  577.     sprintf (zset, "%s%ld", zlast, (long) pai[i]);
  578.     pazargs[cargs - 1] = zset;
  579.  
  580. #if HAVE_QNX_LOCKFILES
  581.         sprintf (zsetnid, "%s%ld", zpenultimate, (long) painid[i]);
  582.         pazargs[cargs - 2] = zsetnid;
  583. #endif
  584.  
  585.     ipid = ixsspawn ((const char **) pazargs, aidescs, FALSE, FALSE,
  586.              (const char *) NULL, FALSE, TRUE,
  587.              (const char *) NULL, (const char *) NULL,
  588.              (const char *) NULL);
  589.     if (ipid < 0)
  590.       ulog (LOG_ERROR, "ixsspawn: %s", strerror (errno));
  591.     else
  592.       (void) ixswait ((unsigned long) ipid, PS_PROGRAM);
  593.       }
  594.     ubuffree (zset);
  595. #if HAVE_QNX_LOCKFILES
  596.     ubuffree (zsetnid);
  597. #endif
  598.   }
  599. #else
  600.   {
  601.     char *zlast;
  602.     int i;
  603.     pid_t ipid;
  604.  
  605.     zlast = zbufalc (strlen (pazargs[cargs - 1]) + cgot * 20 + 1);
  606.     strcpy (zlast, pazargs[cargs - 1]);
  607.     for (i = 0; i < cgot; i++)
  608.       {
  609.     char ab[20];
  610.  
  611.     sprintf (ab, "%ld", (long) pai[i]);
  612.     strcat (zlast, ab);
  613.     if (i + 1 < cgot)
  614.       strcat (zlast, ",");
  615.       }
  616.     pazargs[cargs - 1] = zlast;
  617.  
  618.     ipid = ixsspawn ((const char **) pazargs, aidescs, FALSE, FALSE,
  619.              (const char *) NULL, FALSE, TRUE,
  620.              (const char *) NULL, (const char *) NULL,
  621.              (const char *) NULL);
  622.     if (ipid < 0)
  623.       ulog (LOG_ERROR, "ixsspawn: %s", strerror (errno));
  624.     else
  625.       (void) ixswait ((unsigned long) ipid, PS_PROGRAM);
  626.     ubuffree (zlast);
  627.   }
  628. #endif
  629.  
  630.   ubuffree (zcopy);
  631.   xfree ((pointer) pazargs);
  632.  
  633.   return TRUE;
  634. }
  635.