|
|
1.1 root 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 [email protected] 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.1 93/07/30 08:03:31 bin Exp Locker: bin $";
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.