|
|
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.