1/* uustat.c 2 UUCP status program 3 4 Copyright (C) 1991, 1992, 1993, 1994, 1995, 2002 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. 23 */ 24 25#include "uucp.h" 26 27#if USE_RCS_ID 28const char uustat_rcsid[] = "$Id: uustat.c,v 1.61 2002/03/05 19:10:42 ian Rel $"; 29#endif 30 31#include <ctype.h> 32#include <errno.h> 33 34#if TM_IN_SYS_TIME 35#include <sys/time.h> 36#else 37#include <time.h> 38#endif 39 40#include "getopt.h" 41 42#include "uudefs.h" 43#include "uuconf.h" 44#include "system.h" 45 46/* The uustat program permits various listings and manipulations of 47 files in the spool directory. This implementation supports the 48 following switches: 49 50 -a list all jobs 51 -Blines number of lines of standard input to mail 52 -ccommand list only executions of specified command 53 -Ccommand list only jobs other than executions of specified command 54 -e list execute jobs rather than command requests 55 -i ask user whether to kill each listed job 56 -Ifile set configuration file name 57 -kjobid kill job with specified ID 58 -K kill each listed job 59 -m report status for all remote machines 60 -M mail uucp about each job killed with -K 61 -N mail requestor about each job killed with -K 62 -ohour report jobs older than specified number of hours 63 -p do "ps -flp" on all processes holding lock files (Unix specific) 64 -q list number of jobs for all systems 65 -Q don't list jobs, just do -K processing 66 -rjobid rejuvenate job with specified ID 67 -ssystem report on all jobs for specified system 68 -Ssystem report on all jobs other than for specified system 69 -uuser report on all jobs for specified user 70 -Uuser report on all jobs other than for specified user 71 -Wcomment comment to include in mail messages 72 -xdebug set debugging level 73 -yhour report jobs younger than specified number of hours */ 74 75/* What to do with a job that matches the selection criteria; these 76 values may be or'red together. */ 77#define JOB_SHOW (01) 78#define JOB_INQUIRE (02) 79#define JOB_KILL (04) 80#define JOB_REJUVENATE (010) 81#define JOB_MAIL (020) 82#define JOB_NOTIFY (040) 83 84/* This structure is used to accumulate all the lines in a single 85 command file, so that they can all be displayed at once and so that 86 executions can be displayed reasonably. */ 87 88struct scmdlist 89{ 90 struct scmdlist *qnext; 91 struct scmd s; 92 long itime; 93}; 94 95/* Local functions. */ 96 97static void ususage P((void)); 98static void ushelp P((void)); 99static boolean fsxqt_file_read P((pointer puuconf, FILE *)); 100static void usxqt_file_free P((void)); 101static int isxqt_cmd P((pointer puuconf, int argc, char **argv, pointer pvar, 102 pointer pinfo)); 103static int isxqt_file P((pointer puuconf, int argc, char **argv, pointer pvar, 104 pointer pinfo)); 105static int isxqt_user P((pointer puuconf, int argc, char **argv, pointer pvar, 106 pointer pinfo)); 107static boolean fsworkfiles P((pointer puuconf, int icmd, int csystems, 108 char **pazsystems, boolean fnotsystems, 109 int cusers, char **pazusers, 110 boolean fnotusers, long iold, long iyoung, 111 int ccommands, char **pazcommands, 112 boolean fnotcommands, const char *zcomment, 113 int cstdin)); 114static boolean fsworkfiles_system P((pointer puuconf,int icmd, 115 const struct uuconf_system *qsys, 116 int cusers, char **pazusers, 117 boolean fnotusers, long iold, 118 long iyoung, int ccommands, 119 char **pazcommands, 120 boolean fnotcommands, 121 const char *zcomment, int cstdin)); 122static boolean fsworkfile_show P((pointer puuconf, int icmd, 123 const struct uuconf_system *qsys, 124 const struct scmd *qcmd, 125 long itime, int ccommands, 126 char **pazcommands, boolean fnotcommands, 127 const char *zcomment, int cstdin)); 128static void usworkfile_header P((const struct uuconf_system *qsys, 129 const struct scmd *qcmd, 130 const char *zjobid, 131 long itime, boolean ffirst)); 132static boolean fsexecutions P((pointer puuconf, int icmd, int csystems, 133 char **pazsystems, boolean fnotsystems, 134 int cusers, char **pazusers, 135 boolean fnotusers, long iold, long iyoung, 136 int ccommands, char **pazcommands, 137 boolean fnotcommands, const char *zcomment, 138 int cstdin)); 139static boolean fsnotify P((pointer puuconf, int icmd, const char *zcomment, 140 int cstdin, boolean fkilled, const char *zcmd, 141 struct scmdlist *qcmd, const char *zid, 142 long itime, const char *zuser, 143 const struct uuconf_system *qsys, 144 const char *zstdin, pointer pstdinseq, 145 const char *zrequestor)); 146static boolean fsquery P((pointer puuconf, int csystems, 147 char **pazsystems, boolean fnotsystems, 148 long iold, long iyoung)); 149static int csunits_show P((long idiff)); 150static boolean fsmachines P((void)); 151 152/* Long getopt options. */ 153static const struct option asSlongopts[] = 154{ 155 { "all", no_argument, NULL, 'a' }, 156 { "mail-lines", required_argument, NULL, 'B' }, 157 { "command", required_argument, NULL, 'c' }, 158 { "not-command", required_argument, NULL, 'C' }, 159 { "executions", no_argument, NULL, 'e' }, 160 { "prompt", no_argument, NULL, 'i' }, 161 { "kill", required_argument, NULL, 'k' }, 162 { "kill-all", no_argument, NULL, 'K' }, 163 { "status", no_argument, NULL, 'm' }, 164 { "mail", no_argument, NULL, 'M' }, 165 { "notify", no_argument, NULL, 'N' }, 166 { "older-than", required_argument, NULL, 'o' }, 167 { "ps", no_argument, NULL, 'p' }, 168 { "list", no_argument, NULL, 'q' }, 169 { "no-list", no_argument, NULL, 'Q' }, 170 { "rejuvenate", required_argument, NULL, 'r' }, 171 { "rejuvenate-all", no_argument, NULL, 'R' }, 172 { "system", required_argument, NULL, 's' }, 173 { "not-system", required_argument, NULL, 'S' }, 174 { "user", required_argument, NULL, 'u' }, 175 { "not-user", required_argument, NULL, 'U' }, 176 { "comment", required_argument, NULL, 'W' }, 177 { "younger-than", required_argument, NULL, 'y' }, 178 { "config", required_argument, NULL, 'I' }, 179 { "debug", required_argument, NULL, 'x' }, 180 { "version", no_argument, NULL, 'v' }, 181 { "help", no_argument, NULL, 1 }, 182 { NULL, 0, NULL, 0 } 183}; 184 185int 186main (argc, argv) 187 int argc; 188 char **argv; 189{ 190 /* -a: list all jobs. */ 191 boolean fall = FALSE; 192 /* -B lines: number of lines of standard input to mail. */ 193 int cstdin = 100; 194 /* -c,-C command: list only specified command. */ 195 int ccommands = 0; 196 char **pazcommands = NULL; 197 boolean fnotcommands = FALSE; 198 /* -e: list execute jobs. */ 199 boolean fexecute = FALSE; 200 /* -k jobid: kill specified job. */ 201 int ckills = 0; 202 char **pazkills = NULL; 203 /* -m: report machine status. */ 204 boolean fmachine = FALSE; 205 /* -o hour: report jobs older than given number of hours. */ 206 int ioldhours = -1; 207 /* -p: report status of jobs holding lock files. */ 208 boolean fps = FALSE; 209 /* -q: list number of jobs for each system. */ 210 boolean fquery = FALSE; 211 /* -r jobid: rejuvenate specified job. */ 212 int crejuvs = 0; 213 char **pazrejuvs = NULL; 214 /* -s,-S system: list all jobs for specified system. */ 215 int csystems = 0; 216 char **pazsystems = NULL; 217 boolean fnotsystems = FALSE; 218 /* -u,-U user: list all jobs for specified user. */ 219 int cusers = 0; 220 char **pazusers = NULL; 221 boolean fnotusers = FALSE; 222 /* -W comment: comment to include in mail messages. */ 223 const char *zcomment = NULL; 224 /* -y hour: report jobs younger than given number of hours. */ 225 int iyounghours = -1; 226 /* -I file: set configuration file. */ 227 const char *zconfig = NULL; 228 /* -Q, -i, -K, -M, -N: what to do with each job. */ 229 int icmd = JOB_SHOW; 230 int ccmds; 231 int iopt; 232 pointer puuconf; 233 int iuuconf; 234 long iold; 235 long iyoung; 236 const char *azoneuser[1]; 237 boolean fret; 238 239 if (argc < 1) 240 { 241 zProgram = "uustat"; 242 ususage (); 243 } 244 245 zProgram = argv[0]; 246 247 while ((iopt = getopt_long (argc, argv, 248 "aB:c:C:eiI:k:KmMNo:pqQr:Rs:S:u:U:vW:x:y:", 249 asSlongopts, (int *) NULL)) != EOF) 250 { 251 switch (iopt) 252 { 253 case 'a': 254 /* List all jobs. */ 255 fall = TRUE; 256 break; 257 258 case 'B': 259 /* Number of lines of standard input to mail. */ 260 cstdin = (int) strtol (optarg, (char **) NULL, 10); 261 break; 262 263 case 'C': 264 /* List jobs for other than specified command. */ 265 fnotcommands = TRUE; 266 /* Fall through. */ 267 case 'c': 268 /* List specified command. */ 269 ++ccommands; 270 pazcommands = (char **) xrealloc ((pointer) pazcommands, 271 ccommands * sizeof (char *)); 272 pazcommands[ccommands - 1] = optarg; 273 break; 274 275 case 'e': 276 /* List execute jobs. */ 277 fexecute = TRUE; 278 break; 279 280 case 'i': 281 /* Prompt the user whether to kill each job. */ 282 icmd |= JOB_INQUIRE; 283 break; 284 285 case 'I': 286 /* Set configuration file name. */ 287 if (fsysdep_other_config (optarg)) 288 zconfig = optarg; 289 break; 290 291 case 'k': 292 /* Kill specified job. */ 293 ++ckills; 294 pazkills = (char **) xrealloc ((pointer) pazkills, 295 ckills * sizeof (char *)); 296 pazkills[ckills - 1] = optarg; 297 break; 298 299 case 'K': 300 /* Kill each listed job. */ 301 icmd |= JOB_KILL; 302 break; 303 304 case 'm': 305 /* Report machine status. */ 306 fmachine = TRUE; 307 break; 308 309 case 'M': 310 /* Mail to uucp action taken on each job. */ 311 icmd |= JOB_MAIL; 312 break; 313 314 case 'N': 315 /* Mail to requestor action taken on each job. */ 316 icmd |= JOB_NOTIFY; 317 break; 318 319 case 'o': 320 /* Report old jobs. */ 321 ioldhours = (int) strtol (optarg, (char **) NULL, 10); 322 break; 323 324 case 'p': 325 /* Get status of processes holding locks. */ 326 fps = TRUE; 327 break; 328 329 case 'q': 330 /* List number of jobs for each system. */ 331 fquery = TRUE; 332 break; 333 334 case 'Q': 335 /* Don't list jobs, just do -K processing. */ 336 icmd &=~ JOB_SHOW; 337 break; 338 339 case 'r': 340 /* Rejuvenate specified job. */ 341 ++crejuvs; 342 pazrejuvs = (char **) xrealloc ((pointer) pazrejuvs, 343 crejuvs * sizeof (char *)); 344 pazrejuvs[crejuvs - 1] = optarg; 345 break; 346 347 case 'R': 348 /* Rejuvenate each listed job. */ 349 icmd |= JOB_REJUVENATE; 350 break; 351 352 case 'S': 353 /* List jobs for other than specified system. */ 354 fnotsystems = TRUE; 355 /* Fall through. */ 356 case 's': 357 /* List jobs for specified system. */ 358 ++csystems; 359 pazsystems = (char **) xrealloc ((pointer) pazsystems, 360 csystems * sizeof (char *)); 361 pazsystems[csystems - 1] = optarg; 362 break; 363 364 case 'U': 365 /* List jobs for other than specified user. */ 366 fnotusers = TRUE; 367 /* Fall through. */ 368 case 'u': 369 /* List jobs for specified user. */ 370 ++cusers; 371 pazusers = (char **) xrealloc ((pointer) pazusers, 372 cusers * sizeof (char *)); 373 pazusers[cusers - 1] = optarg; 374 break; 375 376 case 'W': 377 /* Comment to include in mail messages. */ 378 zcomment = optarg; 379 break; 380 381 case 'x': 382#if DEBUG > 1 383 /* Set debugging level. */ 384 iDebug |= idebug_parse (optarg); 385#endif 386 break; 387 388 case 'y': 389 /* List jobs younger than given number of hours. */ 390 iyounghours = (int) strtol (optarg, (char **) NULL, 10); 391 break; 392 393 case 'v': 394 /* Print version and exit. */ 395 printf ("uustat (Taylor UUCP) %s\n", VERSION); 396 printf ("Copyright (C) 1991, 92, 93, 94, 1995, 2002 Ian Lance Taylor\n"); 397 printf ("This program is free software; you may redistribute it under the terms of\n"); 398 printf ("the GNU General Public LIcense. This program has ABSOLUTELY NO WARRANTY.\n"); 399 exit (EXIT_SUCCESS); 400 /*NOTREACHED*/ 401 402 case 1: 403 /* --help. */ 404 ushelp (); 405 exit (EXIT_SUCCESS); 406 /*NOTREACHED*/ 407 408 case 0: 409 /* Long option found and flag set. */ 410 break; 411 412 default: 413 ususage (); 414 /*NOTREACHED*/ 415 } 416 } 417 418 if (optind != argc) 419 ususage (); 420 421 /* To avoid confusion, most options are only permitted by 422 themselves. This restriction might be removed later, but it is 423 imposed by most implementations. We do permit any combination of 424 -c, -s, -u, -o and -y, and any combination of -k and -r. */ 425 ccmds = 0; 426 if (fall) 427 ++ccmds; 428 if (ckills > 0 || crejuvs > 0) 429 ++ccmds; 430 if (fmachine) 431 ++ccmds; 432 if (fps) 433 ++ccmds; 434 if (fexecute || fquery || csystems > 0 || cusers > 0 || ioldhours != -1 435 || iyounghours != -1 || ccommands > 0) 436 ++ccmds; 437 if (fexecute && fquery) 438 ++ccmds; 439 440 if (ccmds > 1) 441 { 442 fprintf (stderr, "%s: too many options\n", zProgram); 443 ususage (); 444 } 445 446 if ((icmd & JOB_KILL) != 0 447 && (icmd & JOB_REJUVENATE) != 0) 448 { 449 fprintf (stderr, "%s: can not both rejuvenate and kill jobs\n", 450 zProgram); 451 ususage (); 452 } 453 454 iuuconf = uuconf_init (&puuconf, (const char *) NULL, zconfig); 455 if (iuuconf != UUCONF_SUCCESS) 456 ulog_uuconf (LOG_FATAL, puuconf, iuuconf); 457 458#if DEBUG > 1 459 { 460 const char *zdebug; 461 462 iuuconf = uuconf_debuglevel (puuconf, &zdebug); 463 if (iuuconf != UUCONF_SUCCESS) 464 ulog_uuconf (LOG_FATAL, puuconf, iuuconf); 465 if (zdebug != NULL) 466 iDebug |= idebug_parse (zdebug); 467 } 468#endif 469 470 usysdep_initialize (puuconf, INIT_SUID); 471 472 /* If no commands were specified, we list all commands for the given 473 user. */ 474 if (ccmds == 0) 475 { 476 cusers = 1; 477 azoneuser[0] = zsysdep_login_name (); 478 pazusers = (char **) azoneuser; 479 } 480 481 /* Canonicalize the system names. */ 482 if (csystems > 0) 483 { 484 int i; 485 486 for (i = 0; i < csystems; i++) 487 { 488 struct uuconf_system ssys; 489 490 iuuconf = uuconf_system_info (puuconf, pazsystems[i], &ssys); 491 if (iuuconf != UUCONF_SUCCESS) 492 { 493 if (iuuconf == UUCONF_NOT_FOUND) 494 ulog (LOG_FATAL, "%s: System not found", pazsystems[i]); 495 else 496 ulog_uuconf (LOG_FATAL, puuconf, iuuconf); 497 } 498 if (strcmp (pazsystems[i], ssys.uuconf_zname) != 0) 499 pazsystems[i] = zbufcpy (ssys.uuconf_zname); 500 (void) uuconf_system_free (puuconf, &ssys); 501 } 502 } 503 504 if (ioldhours == -1) 505 iold = (long) -1; 506 else 507 { 508 iold = (ixsysdep_time ((long *) NULL) 509 - (long) ioldhours * (long) 60 * (long) 60); 510 if (iold < 0L) 511 iold = 0L; 512 } 513 if (iyounghours == -1) 514 iyoung = (long) -1; 515 else 516 { 517 iyoung = (ixsysdep_time ((long *) NULL) 518 - (long) iyounghours * (long) 60 * (long) 60); 519 if (iyoung < 0L) 520 iyoung = 0L; 521 } 522 523 if (! fexecute 524 && ! fquery 525 && (fall 526 || csystems > 0 527 || cusers > 0 528 || ioldhours != -1 529 || iyounghours != -1 530 || ccommands > 0)) 531 fret = fsworkfiles (puuconf, icmd, csystems, pazsystems, fnotsystems, 532 cusers, pazusers, fnotusers, iold, iyoung, 533 ccommands, pazcommands, fnotcommands, zcomment, 534 cstdin); 535 else if (fexecute) 536 fret = fsexecutions (puuconf, icmd, csystems, pazsystems, fnotsystems, 537 cusers, pazusers, fnotusers, iold, iyoung, 538 ccommands, pazcommands, fnotcommands, zcomment, 539 cstdin); 540 else if (icmd != JOB_SHOW) 541 { 542 ulog (LOG_ERROR, 543 "-i, -K, -M, -N, -Q, -R not supported with -k, -m, -p, -q, -r"); 544 ususage (); 545 fret = FALSE; 546 } 547 else if (fquery) 548 { 549 if (cusers > 0 || ccommands > 0) 550 { 551 ulog (LOG_ERROR, "-u, -c not supported with -q"); 552 ususage (); 553 fret = FALSE; 554 } 555 else 556 fret = fsquery (puuconf, csystems, pazsystems, fnotsystems, 557 iold, iyoung); 558 } 559 else if (fmachine) 560 fret = fsmachines (); 561 else if (ckills > 0 || crejuvs > 0) 562 { 563 int i; 564 565 fret = TRUE; 566 for (i = 0; i < ckills; i++) 567 if (! fsysdep_kill_job (puuconf, pazkills[i])) 568 fret = FALSE; 569 570 for (i = 0; i < crejuvs; i++) 571 if (! fsysdep_rejuvenate_job (puuconf, pazrejuvs[i])) 572 fret = FALSE; 573 } 574 else if (fps) 575 fret = fsysdep_lock_status (); 576 else 577 { 578#if DEBUG > 0 579 ulog (LOG_FATAL, "Can't happen"); 580#endif 581 fret = FALSE; 582 } 583 584 ulog_close (); 585 586 usysdep_exit (fret); 587 588 /* Avoid errors about not returning a value. */ 589 return 0; 590} 591 592/* Print a usage message and die. */ 593 594static void 595ususage () 596{ 597 fprintf (stderr, "Usage: %s [options]\n", zProgram); 598 fprintf (stderr, "Use %s --help for help\n", zProgram); 599 exit (EXIT_FAILURE); 600} 601 602/* Print a help message. */ 603 604static void 605ushelp () 606{ 607 printf ("Taylor UUCP %s, copyright (C) 1991, 92, 93, 94, 1995, 2002 Ian Lance Taylor\n", 608 VERSION); 609 printf ("Usage: %s [options]\n", zProgram); 610 printf (" -a,--all: list all UUCP jobs\n"); 611 printf (" -B,--mail-lines num: number of lines to return in -M or -N mail message\n"); 612 printf (" -c,--command command: list requests for named command\n"); 613 printf (" -C,--not-command command: list requests for other than named command\n"); 614 printf (" -e,--executions: list queued executions rather than job requests\n"); 615 printf (" -i,--prompt: prompt for whether to kill each listed job\n"); 616 printf (" -k,--kill job: kill specified UUCP job\n"); 617 printf (" -K,--kill-all: kill each listed job\n"); 618 printf (" -m,--status: report status for all remote machines\n"); 619 printf (" -M,--mail: mail report on each listed job to UUCP administrator\n"); 620 printf (" -N,--notify: mail report on each listed job to requestor\n"); 621 printf (" -o,--older-than hours: list all jobs older than given number of hours\n"); 622 printf (" -p,--ps: show status of all processes holding UUCP locks\n"); 623 printf (" -q,--list: list number of jobs for each system\n"); 624 printf (" -Q,--no-list: don't list jobs, just take actions (-i, -K, -M, -N)\n"); 625 printf (" -r,--rejuvenate job: rejuvenate specified UUCP job\n"); 626 printf (" -R,--rejuvenate-all: rejuvenate each listed job\n"); 627 printf (" -s,--system system: list all jobs for specified system\n"); 628 printf (" -S,--not-system system: list all jobs for other than specified system\n"); 629 printf (" -u,--user user: list all jobs for specified user\n"); 630 printf (" -U,--not-user user: list all jobs for other than specified user\n"); 631 printf (" -W,--comment comment: comment to include in mail messages\n"); 632 printf (" -y,--younger-than hours: list all jobs younger than given number of hours\n"); 633 printf (" -x,--debug debug: Set debugging level\n"); 634#if HAVE_TAYLOR_CONFIG 635 printf (" -I,--config file: Set configuration file to use\n"); 636#endif /* HAVE_TAYLOR_CONFIG */ 637 printf (" -v,--version: Print version and exit\n"); 638 printf (" --help: Print help and exit\n"); 639 printf ("Report bugs to taylor-uucp@gnu.org\n"); 640} 641 642/* We need to be able to read information from an execution file. */ 643 644/* The user name extracted from an execution file. */ 645static char *zSxqt_user; 646 647/* The system name from an execution file. */ 648static char *zSxqt_system; 649 650/* Address of requesting user (who to send mail to). */ 651static const char *zSxqt_requestor; 652 653/* The command (no arguments) from an execution file. */ 654static char *zSxqt_prog; 655 656/* The full command line from an execution file. */ 657static char *zSxqt_cmd; 658 659/* Number of files associated with an execution file. */ 660static int cSxqt_files; 661 662/* Names of files associated with execution file. */ 663static char **pazSxqt_files; 664 665/* Standard input file name. */ 666static const char *zSxqt_stdin; 667 668/* A command table used to dispatch an execution file. */ 669static const struct uuconf_cmdtab asSxqt_cmds[] = 670{ 671 { "C", UUCONF_CMDTABTYPE_FN | 0, NULL, isxqt_cmd }, 672 { "I", UUCONF_CMDTABTYPE_STRING, (pointer) &zSxqt_stdin, NULL }, 673 { "F", UUCONF_CMDTABTYPE_FN | 0, NULL, isxqt_file }, 674 { "R", UUCONF_CMDTABTYPE_STRING, (pointer) &zSxqt_requestor, NULL }, 675 { "U", UUCONF_CMDTABTYPE_FN | 3, NULL, isxqt_user }, 676 { NULL, 0, NULL, NULL } 677}; 678 679/* Read an execution file, setting the above variables. */ 680 681static boolean 682fsxqt_file_read (puuconf, e) 683 pointer puuconf; 684 FILE *e; 685{ 686 int iuuconf; 687 boolean fret; 688 689 zSxqt_user = NULL; 690 zSxqt_system = NULL; 691 zSxqt_stdin = NULL; 692 zSxqt_requestor = NULL; 693 zSxqt_prog = NULL; 694 zSxqt_cmd = NULL; 695 cSxqt_files = 0; 696 pazSxqt_files = NULL; 697 698 iuuconf = uuconf_cmd_file (puuconf, e, asSxqt_cmds, (pointer) NULL, 699 (uuconf_cmdtabfn) NULL, 700 UUCONF_CMDTABFLAG_CASE, (pointer) NULL); 701 if (iuuconf == UUCONF_SUCCESS) 702 fret = TRUE; 703 else 704 { 705 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 706 fret = FALSE; 707 } 708 709 if (zSxqt_user == NULL) 710 zSxqt_user = zbufcpy ("*unknown*"); 711 if (zSxqt_system == NULL) 712 zSxqt_system = zbufcpy ("*unknown*"); 713 if (zSxqt_prog == NULL) 714 { 715 zSxqt_prog = zbufcpy ("*none*"); 716 zSxqt_cmd = zbufcpy ("*none*"); 717 } 718 719 return fret; 720} 721 722/* Free up the information read from an execution file. */ 723 724static void 725usxqt_file_free () 726{ 727 int i; 728 729 ubuffree (zSxqt_user); 730 zSxqt_user = NULL; 731 ubuffree (zSxqt_system); 732 zSxqt_system = NULL; 733 ubuffree (zSxqt_prog); 734 zSxqt_prog = NULL; 735 ubuffree (zSxqt_cmd); 736 zSxqt_cmd = NULL; 737 for (i = 0; i < cSxqt_files; i++) 738 ubuffree (pazSxqt_files[i]); 739 cSxqt_files = 0; 740 xfree ((pointer) pazSxqt_files); 741 pazSxqt_files = NULL; 742 zSxqt_stdin = NULL; 743 zSxqt_requestor = NULL; 744} 745 746/* Get the command from an execution file. */ 747 748/*ARGSUSED*/ 749static int 750isxqt_cmd (puuconf, argc, argv, pvar, pinfo) 751 pointer puuconf ATTRIBUTE_UNUSED; 752 int argc; 753 char **argv; 754 pointer pvar ATTRIBUTE_UNUSED; 755 pointer pinfo ATTRIBUTE_UNUSED; 756{ 757 size_t clen; 758 int i; 759 760 if (argc <= 1) 761 return UUCONF_CMDTABRET_CONTINUE; 762 763 zSxqt_prog = zbufcpy (argv[1]); 764 765 clen = 0; 766 for (i = 1; i < argc; i++) 767 clen += strlen (argv[i]) + 1; 768 769 zSxqt_cmd = zbufalc (clen); 770 zSxqt_cmd[0] = '\0'; 771 for (i = 1; i < argc - 1; i++) 772 { 773 strcat (zSxqt_cmd, argv[i]); 774 strcat (zSxqt_cmd, " "); 775 } 776 strcat (zSxqt_cmd, argv[i]); 777 778 return UUCONF_CMDTABRET_CONTINUE; 779} 780 781/* Get the associated files from an execution file. */ 782 783/*ARGSUSED*/ 784static int 785isxqt_file (puuconf, argc, argv, pvar, pinfo) 786 pointer puuconf ATTRIBUTE_UNUSED; 787 int argc; 788 char **argv; 789 pointer pvar ATTRIBUTE_UNUSED; 790 pointer pinfo ATTRIBUTE_UNUSED; 791{ 792 if (argc != 2 && argc != 3) 793 return UUCONF_CMDTABRET_CONTINUE; 794 795 /* If this file is not in the spool directory, just ignore it. */ 796 if (! fspool_file (argv[1])) 797 return UUCONF_CMDTABRET_CONTINUE; 798 799 ++cSxqt_files; 800 pazSxqt_files = (char **) xrealloc ((pointer) pazSxqt_files, 801 cSxqt_files * sizeof (char *)); 802 803 pazSxqt_files[cSxqt_files - 1] = zbufcpy (argv[1]); 804 805 return UUCONF_CMDTABRET_CONTINUE; 806} 807 808/* Get the requesting user and system from an execution file. */ 809 810/*ARGSUSED*/ 811static int 812isxqt_user (puuconf, argc, argv, pvar, pinfo) 813 pointer puuconf ATTRIBUTE_UNUSED; 814 int argc ATTRIBUTE_UNUSED; 815 char **argv; 816 pointer pvar ATTRIBUTE_UNUSED; 817 pointer pinfo ATTRIBUTE_UNUSED; 818{ 819 zSxqt_user = zbufcpy (argv[1]); 820 zSxqt_system = zbufcpy (argv[2]); 821 return UUCONF_CMDTABRET_CONTINUE; 822} 823 824/* Handle various possible requests to look at work files. */ 825 826static boolean 827fsworkfiles (puuconf, icmd, csystems, pazsystems, fnotsystems, cusers, 828 pazusers, fnotusers, iold, iyoung, ccommands, pazcommands, 829 fnotcommands, zcomment, cstdin) 830 pointer puuconf; 831 int icmd; 832 int csystems; 833 char **pazsystems; 834 boolean fnotsystems; 835 int cusers; 836 char **pazusers; 837 boolean fnotusers; 838 long iold; 839 long iyoung; 840 int ccommands; 841 char **pazcommands; 842 boolean fnotcommands; 843 const char *zcomment; 844 int cstdin; 845{ 846 boolean fret; 847 int i; 848 int iuuconf; 849 struct uuconf_system ssys; 850 851 fret = TRUE; 852 853 if (csystems > 0 && ! fnotsystems) 854 { 855 for (i = 0; i < csystems; i++) 856 { 857 iuuconf = uuconf_system_info (puuconf, pazsystems[i], &ssys); 858 if (iuuconf != UUCONF_SUCCESS) 859 { 860 if (iuuconf == UUCONF_NOT_FOUND) 861 ulog (LOG_ERROR, "%s: System not found", pazsystems[i]); 862 else 863 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 864 fret = FALSE; 865 continue; 866 } 867 868 if (! fsworkfiles_system (puuconf, icmd, &ssys, cusers, pazusers, 869 fnotusers, iold, iyoung, ccommands, 870 pazcommands, fnotcommands, zcomment, 871 cstdin)) 872 fret = FALSE; 873 874 (void) uuconf_system_free (puuconf, &ssys); 875 } 876 } 877 else 878 { 879 char **pznames, **pz; 880 881 iuuconf = uuconf_system_names (puuconf, &pznames, 0); 882 if (iuuconf != UUCONF_SUCCESS) 883 { 884 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 885 return FALSE; 886 } 887 888 for (pz = pznames; *pz != NULL; pz++) 889 { 890 if (csystems > 0) 891 { 892 for (i = 0; i < csystems; i++) 893 if (strcmp (*pz, pazsystems[i]) == 0) 894 break; 895 if (i < csystems) 896 continue; 897 } 898 899 iuuconf = uuconf_system_info (puuconf, *pz, &ssys); 900 if (iuuconf != UUCONF_SUCCESS) 901 { 902 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 903 fret = FALSE; 904 continue; 905 } 906 907 if (! fsworkfiles_system (puuconf, icmd, &ssys, cusers, pazusers, 908 fnotusers, iold, iyoung, ccommands, 909 pazcommands, fnotcommands, zcomment, 910 cstdin)) 911 fret = FALSE; 912 913 (void) uuconf_system_free (puuconf, &ssys); 914 xfree ((pointer) *pz); 915 } 916 xfree ((pointer) pznames); 917 } 918 919 return fret; 920} 921 922/* Look at the work files for a particular system. */ 923 924static boolean 925fsworkfiles_system (puuconf, icmd, qsys, cusers, pazusers, fnotusers, iold, 926 iyoung, ccommands, pazcommands, fnotcommands, zcomment, 927 cstdin) 928 pointer puuconf; 929 int icmd; 930 const struct uuconf_system *qsys; 931 int cusers; 932 char **pazusers; 933 boolean fnotusers; 934 long iold; 935 long iyoung; 936 int ccommands; 937 char **pazcommands; 938 boolean fnotcommands; 939 const char *zcomment; 940 int cstdin; 941{ 942 boolean fret; 943 944 if (! fsysdep_get_work_init (qsys, UUCONF_GRADE_LOW, 0)) 945 return FALSE; 946 947 while (TRUE) 948 { 949 struct scmd s; 950 long itime; 951 952 if (! fsysdep_get_work (qsys, UUCONF_GRADE_LOW, 0, &s)) 953 { 954 usysdep_get_work_free (qsys); 955 return FALSE; 956 } 957 if (s.bcmd == 'H') 958 break; 959 960 if (cusers > 0) 961 { 962 boolean fmatch; 963 int i; 964 965 fmatch = fnotusers; 966 for (i = 0; i < cusers; i++) 967 { 968 if (s.zuser != NULL 969 && strcmp (pazusers[i], s.zuser) == 0) 970 { 971 fmatch = ! fmatch; 972 break; 973 } 974 } 975 if (! fmatch) 976 continue; 977 } 978 979 itime = ixsysdep_work_time (qsys, s.pseq); 980 981 if (iold != (long) -1 && itime > iold) 982 continue; 983 984 if (iyoung != (long) -1 && itime < iyoung) 985 continue; 986 987 if (! fsworkfile_show (puuconf, icmd, qsys, &s, itime, ccommands, 988 pazcommands, fnotcommands, zcomment, cstdin)) 989 { 990 usysdep_get_work_free (qsys); 991 return FALSE; 992 } 993 } 994 995 fret = fsworkfile_show (puuconf, icmd, qsys, (const struct scmd *) NULL, 996 0L, ccommands, pazcommands, fnotcommands, zcomment, 997 cstdin); 998 999 usysdep_get_work_free (qsys); 1000 1001 return fret; 1002} 1003 1004/* Show a single workfile. This is actually called once for each line 1005 in the workfile, so we accumulate the lines and show them all at 1006 once. This lets us show an execution in a useful fashion. */ 1007 1008static boolean 1009fsworkfile_show (puuconf, icmd, qsys, qcmd, itime, ccommands, pazcommands, 1010 fnotcommands, zcomment, cstdin) 1011 pointer puuconf; 1012 int icmd; 1013 const struct uuconf_system *qsys; 1014 const struct scmd *qcmd; 1015 long itime; 1016 int ccommands; 1017 char **pazcommands; 1018 boolean fnotcommands; 1019 const char *zcomment; 1020 int cstdin; 1021{ 1022 static struct scmdlist *qlist; 1023 static char *zlistid; 1024 char *zid; 1025 1026 if (qcmd == NULL) 1027 zid = NULL; 1028 else 1029 { 1030 zid = zsysdep_jobid (qsys, qcmd->pseq); 1031 if (zid == NULL) 1032 return FALSE; 1033 } 1034 1035 /* If this is the same jobid as the list, put it on the end. */ 1036 1037 if (qcmd != NULL 1038 && qlist != NULL 1039 && strcmp (zlistid, zid) == 0) 1040 { 1041 struct scmdlist *qnew, **pq; 1042 1043 ubuffree (zid); 1044 qnew = (struct scmdlist *) xmalloc (sizeof (struct scmdlist)); 1045 qnew->qnext = NULL; 1046 qnew->s = *qcmd; 1047 qnew->itime = itime; 1048 for (pq = &qlist; *pq != NULL; pq = &(*pq)->qnext) 1049 ; 1050 *pq = qnew; 1051 return TRUE; 1052 } 1053 1054 /* Here we have found a different job ID, so we print the scmd 1055 structures that we have accumulated. We look for the special 1056 case of an execution (an E command, or one of the destination 1057 files begins with X.). We could be more clever about other 1058 situations as well. */ 1059 if (qlist != NULL) 1060 { 1061 boolean fmatch; 1062 const char *zprog, *zcmd, *zrequestor, *zstdin; 1063 char *zfree; 1064 struct scmdlist *qxqt; 1065 FILE *exqt = NULL; 1066 struct scmdlist *qfree; 1067 1068 fmatch = FALSE; 1069 zprog = zcmd = zrequestor = zstdin = NULL; 1070 zfree = NULL; 1071 1072 for (qxqt = qlist; qxqt != NULL; qxqt = qxqt->qnext) 1073 { 1074 if (qxqt->s.bcmd == 'E') 1075 break; 1076 if (qxqt->s.bcmd == 'S' 1077 && qxqt->s.zto[0] == 'X' 1078 && qxqt->s.zto[1] == '.' 1079 && fspool_file (qxqt->s.zfrom)) 1080 { 1081 char *zxqt; 1082 1083 /* Open the file now, so that, if it does not exist, we 1084 can still report sensibly (the qxqt == NULL case) on 1085 any other files that may exist. */ 1086 1087 zxqt = zsysdep_spool_file_name (qsys, qxqt->s.zfrom, 1088 qxqt->s.pseq); 1089 if (zxqt == NULL) 1090 return FALSE; 1091 1092 exqt = fopen (zxqt, "r"); 1093 1094 ubuffree (zxqt); 1095 1096 if (exqt != NULL) 1097 break; 1098 } 1099 } 1100 1101 if (qxqt == NULL) 1102 { 1103 if (ccommands == 0 1104 || (fnotcommands 1105 && strcmp (pazcommands[0], "ALL") == 0)) 1106 { 1107 /* Show all the lines in a regular work file. */ 1108 fmatch = TRUE; 1109 1110 if ((icmd & JOB_SHOW) != 0) 1111 { 1112 struct scmdlist *qshow; 1113 1114 for (qshow = qlist; qshow != NULL; qshow = qshow->qnext) 1115 { 1116 char *zfile; 1117 long cbytes; 1118 1119 usworkfile_header (qsys, &qshow->s, zlistid, 1120 qshow->itime, qshow == qlist); 1121 1122 switch (qshow->s.bcmd) 1123 { 1124 case 'S': 1125 if (strchr (qshow->s.zoptions, 'C') != NULL 1126 || fspool_file (qshow->s.zfrom)) 1127 zfile = zsysdep_spool_file_name (qsys, 1128 qshow->s.ztemp, 1129 qshow->s.pseq); 1130 else 1131 zfile = zbufcpy (qshow->s.zfrom); 1132 if (zfile == NULL) 1133 cbytes = -1; 1134 else 1135 cbytes = csysdep_size (zfile); 1136 if (cbytes >= 0) 1137 printf ("Sending %s (%ld bytes) to %s", 1138 qshow->s.zfrom, cbytes, qshow->s.zto); 1139 ubuffree (zfile); 1140 break; 1141 case 'R': 1142 printf ("Requesting %s to %s", qshow->s.zfrom, 1143 qshow->s.zto); 1144 break; 1145 case 'X': 1146 printf ("Requesting %s to %s", qshow->s.zfrom, 1147 qshow->s.zto); 1148 break; 1149 case 'P': 1150 printf ("(poll file)"); 1151 break; 1152#if DEBUG > 0 1153 default: 1154 printf ("Bad line %d", qshow->s.bcmd); 1155 break; 1156#endif 1157 } 1158 1159 printf ("\n"); 1160 } 1161 } 1162 } 1163 } 1164 else 1165 { 1166 long csize; 1167 struct scmdlist *qsize; 1168 1169 /* Show the command for an execution file. */ 1170 if (qxqt->s.bcmd == 'E') 1171 { 1172 zfree = zbufcpy (qxqt->s.zcmd); 1173 zfree[strcspn (zfree, " \t")] = '\0'; 1174 zprog = zfree; 1175 zcmd = qxqt->s.zcmd; 1176 if (strchr (qxqt->s.zoptions, 'R') != NULL) 1177 zrequestor = qxqt->s.znotify; 1178 } 1179 else 1180 { 1181 if (! fsxqt_file_read (puuconf, exqt)) 1182 { 1183 (void) fclose (exqt); 1184 return FALSE; 1185 } 1186 1187 (void) fclose (exqt); 1188 1189 zprog = zSxqt_prog; 1190 zcmd = zSxqt_cmd; 1191 zrequestor = zSxqt_requestor; 1192 } 1193 1194 csize = 0L; 1195 for (qsize = qlist; qsize != NULL; qsize = qsize->qnext) 1196 { 1197 if (qsize->s.bcmd == 'S' || qsize->s.bcmd == 'E') 1198 { 1199 char *zfile; 1200 1201 if (strchr (qsize->s.zoptions, 'C') != NULL 1202 || fspool_file (qsize->s.zfrom)) 1203 zfile = zsysdep_spool_file_name (qsys, qsize->s.ztemp, 1204 qsize->s.pseq); 1205 else 1206 zfile = zbufcpy (qsize->s.zfrom); 1207 if (zfile != NULL) 1208 { 1209 long cbytes; 1210 1211 cbytes = csysdep_size (zfile); 1212 if (cbytes > 0) 1213 csize += cbytes; 1214 ubuffree (zfile); 1215 } 1216 } 1217 } 1218 1219 if (ccommands == 0) 1220 fmatch = TRUE; 1221 else 1222 { 1223 int i; 1224 1225 fmatch = fnotcommands; 1226 for (i = 0; i < ccommands; i++) 1227 { 1228 if (strcmp (pazcommands[i], "ALL") == 0 1229 || strcmp (pazcommands[i], zprog) == 0) 1230 { 1231 fmatch = ! fmatch; 1232 break; 1233 } 1234 } 1235 } 1236 1237 /* To get the name of the standard input file on this system 1238 we have to look through the list of file transfers to 1239 find the right one on the remote system. */ 1240 if (fmatch) 1241 { 1242 struct scmdlist *qstdin; 1243 1244 if (qxqt->s.bcmd == 'E') 1245 qstdin = qxqt; 1246 else if (zSxqt_stdin != NULL) 1247 { 1248 for (qstdin = qlist; 1249 qstdin != NULL; 1250 qstdin = qstdin->qnext) 1251 if (qstdin->s.bcmd == 'S' 1252 && strcmp (qstdin->s.zto, zSxqt_stdin) == 0) 1253 break; 1254 } 1255 else 1256 qstdin = NULL; 1257 1258 if (qstdin != NULL) 1259 { 1260 if (strchr (qstdin->s.zoptions, 'C') != NULL 1261 || fspool_file (qstdin->s.zfrom)) 1262 zstdin = qstdin->s.ztemp; 1263 else 1264 zstdin = qstdin->s.zfrom; 1265 } 1266 } 1267 1268 if (fmatch && (icmd & JOB_SHOW) != 0) 1269 { 1270 usworkfile_header (qsys, &qxqt->s, zlistid, qxqt->itime, 1271 TRUE); 1272 printf ("Executing %s (sending %ld bytes)\n", zcmd, csize); 1273 } 1274 } 1275 1276 if (fmatch) 1277 { 1278 boolean fkill_or_rejuv; 1279 1280 fkill_or_rejuv = FALSE; 1281 if ((icmd & JOB_INQUIRE) != 0) 1282 { 1283 int b; 1284 1285 /* Ask stdin whether this job should be killed. */ 1286 fprintf (stderr, "%s: %s %s? ", 1287 zProgram, 1288 (icmd & JOB_REJUVENATE) != 0 ? "Rejuvenate" : "Kill", 1289 zlistid); 1290 (void) fflush (stderr); 1291 b = getchar (); 1292 fkill_or_rejuv = b == 'y' || b == 'Y'; 1293 while (b != EOF && b != '\n') 1294 b = getchar (); 1295 } 1296 else if ((icmd & JOB_KILL) != 0 1297 || (icmd & JOB_REJUVENATE) != 0) 1298 fkill_or_rejuv = TRUE; 1299 1300 if (fkill_or_rejuv 1301 && (qlist->s.zuser == NULL 1302 || strcmp (zsysdep_login_name (), qlist->s.zuser) != 0) 1303 && ! fsysdep_privileged ()) 1304 ulog (LOG_ERROR, "%s: Not submitted by you", zlistid); 1305 else 1306 { 1307 if ((icmd & (JOB_MAIL | JOB_NOTIFY)) != 0) 1308 { 1309 if (! fsnotify (puuconf, icmd, zcomment, cstdin, 1310 (fkill_or_rejuv && 1311 (icmd & JOB_REJUVENATE) == 0), 1312 zcmd, qlist, zlistid, qlist->itime, 1313 qlist->s.zuser, qsys, zstdin, 1314 qlist->s.pseq, zrequestor)) 1315 return FALSE; 1316 } 1317 1318 if (fkill_or_rejuv) 1319 { 1320 if ((icmd & JOB_REJUVENATE) == 0) 1321 { 1322 if (! fsysdep_kill_job (puuconf, zlistid)) 1323 return FALSE; 1324 } 1325 else 1326 { 1327 if (! fsysdep_rejuvenate_job (puuconf, zlistid)) 1328 return FALSE; 1329 } 1330 } 1331 } 1332 } 1333 1334 if (qxqt != NULL) 1335 { 1336 if (qxqt->s.bcmd == 'E') 1337 ubuffree (zfree); 1338 else 1339 usxqt_file_free (); 1340 } 1341 1342 /* Free up the list of entries. */ 1343 qfree = qlist; 1344 while (qfree != NULL) 1345 { 1346 struct scmdlist *qnext; 1347 1348 qnext = qfree->qnext; 1349 xfree ((pointer) qfree); 1350 qfree = qnext; 1351 } 1352 1353 ubuffree (zlistid); 1354 1355 qlist = NULL; 1356 zlistid = NULL; 1357 } 1358 1359 /* Start a new list with the entry we just got. */ 1360 if (qcmd != NULL) 1361 { 1362 qlist = (struct scmdlist *) xmalloc (sizeof (struct scmdlist)); 1363 qlist->qnext = NULL; 1364 qlist->s = *qcmd; 1365 qlist->itime = itime; 1366 zlistid = zid; 1367 } 1368 1369 return TRUE; 1370} 1371 1372/* Show the header of the line describing a workfile. */ 1373 1374static void 1375usworkfile_header (qsys, qcmd, zjobid, itime, ffirst) 1376 const struct uuconf_system *qsys; 1377 const struct scmd *qcmd; 1378 const char *zjobid; 1379 long itime; 1380 boolean ffirst; 1381{ 1382 const char *zshowid; 1383 struct tm stime; 1384 1385 if (ffirst) 1386 zshowid = zjobid; 1387 else 1388 zshowid = "-"; 1389 1390 printf ("%s %s %s ", zshowid, qsys->uuconf_zname, 1391 qcmd->zuser != NULL ? qcmd->zuser : OWNER); 1392 1393 usysdep_localtime (itime, &stime); 1394 printf ("%02d-%02d %02d:%02d ", 1395 stime.tm_mon + 1, stime.tm_mday, stime.tm_hour, stime.tm_min); 1396} 1397 1398/* List queued executions that have not been processed by uuxqt for 1399 one reason or another. */ 1400 1401static boolean 1402fsexecutions (puuconf, icmd, csystems, pazsystems, fnotsystems, cusers, 1403 pazusers, fnotusers, iold, iyoung, ccommands, pazcommands, 1404 fnotcommands, zcomment, cstdin) 1405 pointer puuconf; 1406 int icmd; 1407 int csystems; 1408 char **pazsystems; 1409 boolean fnotsystems; 1410 int cusers; 1411 char **pazusers; 1412 boolean fnotusers; 1413 long iold; 1414 long iyoung; 1415 int ccommands; 1416 char **pazcommands; 1417 boolean fnotcommands; 1418 const char *zcomment; 1419 int cstdin; 1420{ 1421 const char *zlocalname; 1422 int iuuconf; 1423 char *zfile; 1424 char *zsystem; 1425 boolean ferr; 1426 1427 iuuconf = uuconf_localname (puuconf, &zlocalname); 1428 if (iuuconf == UUCONF_NOT_FOUND) 1429 { 1430 zlocalname = zsysdep_localname (); 1431 if (zlocalname == NULL) 1432 return FALSE; 1433 } 1434 else if (iuuconf != UUCONF_SUCCESS) 1435 { 1436 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 1437 return FALSE; 1438 } 1439 1440 if (! fsysdep_get_xqt_init ((const char *) NULL)) 1441 return FALSE; 1442 1443 while ((zfile = zsysdep_get_xqt ((const char *) NULL, &zsystem, &ferr)) 1444 != NULL) 1445 { 1446 boolean fmatch; 1447 int i; 1448 long itime; 1449 FILE *e; 1450 1451 if (csystems > 0) 1452 { 1453 fmatch = fnotsystems; 1454 for (i = 0; i < csystems; i++) 1455 { 1456 if (strcmp (pazsystems[i], zsystem) == 0) 1457 { 1458 fmatch = ! fmatch; 1459 break; 1460 } 1461 } 1462 if (! fmatch) 1463 { 1464 ubuffree (zfile); 1465 ubuffree (zsystem); 1466 continue; 1467 } 1468 } 1469 1470 itime = ixsysdep_file_time (zfile); 1471 1472 if ((iold != (long) -1 && itime > iold) 1473 || (iyoung != (long) -1 && itime < iyoung)) 1474 { 1475 ubuffree (zfile); 1476 ubuffree (zsystem); 1477 continue; 1478 } 1479 1480 /* We need to read the execution file before we can check the 1481 user name. */ 1482 e = fopen (zfile, "r"); 1483 if (e == NULL) 1484 { 1485 /* Probably uucico just deleted the file. */ 1486 continue; 1487 } 1488 if (! fsxqt_file_read (puuconf, e)) 1489 { 1490 (void) fclose (e); 1491 ubuffree (zfile); 1492 ubuffree (zsystem); 1493 continue; 1494 } 1495 (void) fclose (e); 1496 1497 if (cusers == 0) 1498 fmatch = TRUE; 1499 else 1500 { 1501 fmatch = fnotusers; 1502 for (i = 0; i < cusers; i++) 1503 { 1504 if (strcmp (zSxqt_user, pazusers[i]) == 0 1505 || (zSxqt_requestor != NULL 1506 && strcmp (zSxqt_requestor, pazusers[i]) == 0)) 1507 { 1508 fmatch = ! fmatch; 1509 break; 1510 } 1511 } 1512 } 1513 1514 if (fmatch && ccommands > 0) 1515 { 1516 fmatch = fnotcommands; 1517 for (i = 0; i < ccommands; i++) 1518 { 1519 if (strcmp (pazcommands[i], "ALL") == 0 1520 || strcmp (pazcommands[i], zSxqt_prog) == 0) 1521 { 1522 fmatch = ! fmatch; 1523 break; 1524 } 1525 } 1526 } 1527 1528 if (fmatch) 1529 { 1530 boolean fbad, fkill_or_rejuv; 1531 struct uuconf_system ssys; 1532 1533 fbad = FALSE; 1534 1535 if ((icmd & JOB_SHOW) != 0) 1536 { 1537 struct tm stime; 1538 1539 printf ("%s %s!", zsystem, zSxqt_system); 1540 if (zSxqt_requestor != NULL) 1541 printf ("%s", zSxqt_requestor); 1542 else 1543 printf ("%s", zSxqt_user); 1544 1545 usysdep_localtime (itime, &stime); 1546 printf (" %02d-%02d %02d:%02d ", 1547 stime.tm_mon + 1, stime.tm_mday, stime.tm_hour, 1548 stime.tm_min); 1549 1550 printf ("%s\n", zSxqt_cmd); 1551 } 1552 1553 fkill_or_rejuv = FALSE; 1554 if ((icmd & JOB_INQUIRE) != 0) 1555 { 1556 int b; 1557 1558 /* Ask stdin whether this job should be killed. */ 1559 fprintf (stderr, "%s: %s %s? ", 1560 zProgram, 1561 (icmd & JOB_REJUVENATE) != 0 ? "Rejuvenate" : "Kill", 1562 zSxqt_cmd); 1563 (void) fflush (stderr); 1564 b = getchar (); 1565 fkill_or_rejuv = b == 'y' || b == 'Y'; 1566 while (b != EOF && b != '\n') 1567 b = getchar (); 1568 } 1569 else if ((icmd & JOB_KILL) != 0 1570 || (icmd & JOB_REJUVENATE) != 0) 1571 fkill_or_rejuv = TRUE; 1572 1573 if (fkill_or_rejuv) 1574 { 1575 if ((strcmp (zSxqt_user, zsysdep_login_name ()) != 0 1576 || strcmp (zsystem, zlocalname) != 0) 1577 && ! fsysdep_privileged ()) 1578 { 1579 ulog (LOG_ERROR, "Job not submitted by you\n"); 1580 fbad = TRUE; 1581 } 1582 } 1583 1584 if (! fbad) 1585 { 1586 iuuconf = uuconf_system_info (puuconf, zsystem, &ssys); 1587 if (iuuconf != UUCONF_SUCCESS) 1588 { 1589 if (iuuconf != UUCONF_NOT_FOUND) 1590 { 1591 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 1592 fbad = TRUE; 1593 } 1594 else if (strcmp (zsystem, zlocalname) == 0) 1595 { 1596 iuuconf = uuconf_system_local (puuconf, &ssys); 1597 if (iuuconf != UUCONF_SUCCESS) 1598 { 1599 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 1600 fbad = TRUE; 1601 } 1602 ssys.uuconf_zname = (char *) zlocalname; 1603 } 1604 else if (! funknown_system (puuconf, zsystem, &ssys)) 1605 { 1606 ulog (LOG_ERROR, "Job for unknown system %s", 1607 zsystem); 1608 fbad = TRUE; 1609 } 1610 } 1611 } 1612 1613 if (! fbad && (icmd & (JOB_MAIL | JOB_NOTIFY)) != 0) 1614 { 1615 if (! fsnotify (puuconf, icmd, zcomment, cstdin, 1616 fkill_or_rejuv && (icmd & JOB_REJUVENATE) == 0, 1617 zSxqt_cmd, (struct scmdlist *) NULL, 1618 (const char *) NULL, itime, zSxqt_user, &ssys, 1619 zSxqt_stdin, (pointer) NULL, zSxqt_requestor)) 1620 { 1621 ferr = TRUE; 1622 usxqt_file_free (); 1623 ubuffree (zfile); 1624 ubuffree (zsystem); 1625 break; 1626 } 1627 } 1628 1629 if (! fbad && fkill_or_rejuv) 1630 { 1631 for (i = 0; i < cSxqt_files; i++) 1632 { 1633 char *z; 1634 1635 z = zsysdep_spool_file_name (&ssys, pazSxqt_files[i], 1636 (pointer) NULL); 1637 if (z != NULL) 1638 { 1639 if ((icmd & JOB_REJUVENATE) != 0) 1640 (void) fsysdep_touch_file (z); 1641 else 1642 (void) remove (z); 1643 ubuffree (z); 1644 } 1645 } 1646 if ((icmd & JOB_REJUVENATE) != 0) 1647 (void) fsysdep_touch_file (zfile); 1648 else 1649 { 1650 if (remove (zfile) != 0) 1651 ulog (LOG_ERROR, "remove (%s): %s", zfile, 1652 strerror (errno)); 1653 } 1654 } 1655 1656 if (! fbad) 1657 (void) uuconf_system_free (puuconf, &ssys); 1658 } 1659 1660 usxqt_file_free (); 1661 ubuffree (zfile); 1662 ubuffree (zsystem); 1663 } 1664 1665 usysdep_get_xqt_free ((const char *) NULL); 1666 1667 return ferr; 1668} 1669 1670/* When a job is killed, send mail to the appropriate people. */ 1671 1672static boolean 1673fsnotify (puuconf, icmd, zcomment, cstdin, fkilled, zcmd, qcmd, zid, itime, 1674 zuser, qsys, zstdin, pstdinseq, zrequestor) 1675 pointer puuconf; 1676 int icmd; 1677 const char *zcomment; 1678 int cstdin; 1679 boolean fkilled; 1680 const char *zcmd; 1681 struct scmdlist *qcmd; 1682 const char *zid; 1683 long itime; 1684 const char *zuser; 1685 const struct uuconf_system *qsys; 1686 const char *zstdin; 1687 pointer pstdinseq; 1688 const char *zrequestor; 1689{ 1690 const char **pz; 1691 int cgot; 1692 int i, istdin; 1693 struct tm stime; 1694 char ab[sizeof "1991-12-31 12:00:00"]; 1695 const char *zsubject; 1696 boolean fret; 1697 1698 pz = (const char **) xmalloc (20 * sizeof (const char *)); 1699 cgot = 20; 1700 1701 i = 0; 1702 if (zid == NULL) 1703 pz[i++] = "A UUCP execution request"; 1704 else 1705 { 1706 pz[i++] = "UUCP job\n\t"; 1707 pz[i++] = zid; 1708 pz[i++] = "\nfor system\n\t"; 1709 pz[i++] = qsys->uuconf_zname; 1710 } 1711 pz[i++] = "\nrequested by\n\t"; 1712 pz[i++] = zuser != NULL ? zuser : OWNER; 1713 if (zid == NULL) 1714 { 1715 pz[i++] = "\non system\n\t"; 1716 pz[i++] = qsys->uuconf_zname; 1717 } 1718 pz[i++] = "\n"; 1719 1720 if (fkilled) 1721 pz[i++] = "has been killed.\n"; 1722 1723 if (zcomment != NULL) 1724 { 1725 pz[i++] = zcomment; 1726 pz[i++] = "\n"; 1727 } 1728 1729 pz[i++] = "The job was queued at "; 1730 usysdep_localtime (itime, &stime); 1731 sprintf (ab, "%04d-%02d-%02d %02d:%02d:%02d", 1732 stime.tm_year + 1900, stime.tm_mon + 1, stime.tm_mday, 1733 stime.tm_hour, stime.tm_min, stime.tm_sec); 1734 pz[i++] = ab; 1735 pz[i++] = ".\nIt "; 1736 1737 if (fkilled) 1738 pz[i++] = "was\n"; 1739 else 1740 pz[i++] = "is\n"; 1741 1742 if (zcmd != NULL) 1743 { 1744 pz[i++] = "\t"; 1745 pz[i++] = zcmd; 1746 } 1747 else 1748 { 1749 struct scmdlist *qshow; 1750 1751 for (qshow = qcmd; qshow != NULL; qshow = qshow->qnext) 1752 { 1753 if (i + 10 > cgot) 1754 { 1755 cgot += 20; 1756 pz = (const char **) xrealloc ((pointer) pz, 1757 cgot * sizeof (const char *)); 1758 } 1759 1760 switch (qshow->s.bcmd) 1761 { 1762 case 'S': 1763 pz[i++] = "\tsend "; 1764 break; 1765 default: 1766 case 'R': 1767 case 'X': 1768 pz[i++] = "\trequest "; 1769 break; 1770 case 'P': 1771 pz[i++] = "\tpoll "; 1772 break; 1773#if DEBUG > 0 1774 case 'E': 1775 ulog (LOG_FATAL, "fsnotify: Can't happen"); 1776 break; 1777#endif 1778 } 1779 if (qshow->s.zfrom != NULL && qshow->s.zto != NULL) 1780 { 1781 pz[i++] = qshow->s.zfrom; 1782 pz[i++] = " to "; 1783 pz[i++] = qshow->s.zto; 1784 } 1785 } 1786 } 1787 1788 istdin = i; 1789 if (cstdin > 0 && zstdin != NULL) 1790 { 1791 boolean fspool; 1792 char *zfile; 1793 FILE *e; 1794 1795 fspool = fspool_file (zstdin); 1796 if (fspool) 1797 zfile = zsysdep_spool_file_name (qsys, zstdin, pstdinseq); 1798 else 1799 zfile = zsysdep_local_file (zstdin, qsys->uuconf_zpubdir, 1800 (boolean *) NULL); 1801 1802 if (zfile != NULL 1803 && (fspool 1804 || fin_directory_list (zfile, qsys->uuconf_pzremote_send, 1805 qsys->uuconf_zpubdir, TRUE, TRUE, 1806 (const char *) NULL))) 1807 { 1808 e = fopen (zfile, "r"); 1809 if (e != NULL) 1810 { 1811 int clines, clen; 1812 char *zline; 1813 size_t cline; 1814 1815 pz[i++] = "\n"; 1816 istdin = i; 1817 1818 clines = 0; 1819 1820 zline = NULL; 1821 cline = 0; 1822 while ((clen = getline (&zline, &cline, e)) > 0) 1823 { 1824 if (memchr (zline, '\0', (size_t) clen) != NULL) 1825 { 1826 int ifree; 1827 1828 /* A null character means this is probably a 1829 binary file. */ 1830 for (ifree = istdin; ifree < i; ifree++) 1831 ubuffree ((char *) pz[ifree]); 1832 i = istdin - 1; 1833 break; 1834 } 1835 ++clines; 1836 if (clines > cstdin) 1837 break; 1838 if (i >= cgot) 1839 { 1840 cgot += 20; 1841 pz = (const char **) xrealloc ((pointer) pz, 1842 (cgot 1843 * sizeof (char *))); 1844 } 1845 if (strncmp (zline, "From ", sizeof "From " - 1) != 0) 1846 pz[i++] = zbufcpy (zline); 1847 else 1848 { 1849 char *zalc; 1850 1851 /* Escape "From " at the start of a line. This 1852 should really be the responsibility of the 1853 mail transfer agent. On some systems, 1854 though, the mail transfer agent does not do 1855 it, but user mail programs expect it. We 1856 help them out here, since it doesn't matter 1857 much--we're already truncating the message 1858 anyhow. */ 1859 zalc = zbufalc (strlen (zline) + 2); 1860 zalc[0] = '>'; 1861 strcpy (zalc + 1, zline); 1862 pz[i++] = zalc; 1863 } 1864 } 1865 xfree ((pointer) zline); 1866 (void) fclose (e); 1867 } 1868 } 1869 1870 ubuffree (zfile); 1871 } 1872 1873 if (fkilled) 1874 zsubject = "UUCP job killed"; 1875 else 1876 zsubject = "UUCP notification"; 1877 1878 fret = TRUE; 1879 1880 if ((icmd & JOB_MAIL) != 0) 1881 { 1882 if (! fsysdep_mail (OWNER, zsubject, i, pz)) 1883 fret = FALSE; 1884 } 1885 1886 if ((icmd & JOB_NOTIFY) != 0 1887 && (zrequestor != NULL || zuser != NULL)) 1888 { 1889 const char *zmail; 1890 char *zfree; 1891 1892 if (zrequestor != NULL) 1893 zmail = zrequestor; 1894 else 1895 zmail = zuser; 1896 1897 zfree = NULL; 1898 1899 if (zid == NULL) 1900 { 1901 int iuuconf; 1902 const char *zloc; 1903 1904 /* This is an execution request, which may be from another 1905 system. If it is, we must prepend that system name to 1906 the user name extracted from the X. file. */ 1907 iuuconf = uuconf_localname (puuconf, &zloc); 1908 if (iuuconf == UUCONF_NOT_FOUND) 1909 { 1910 zloc = zsysdep_localname (); 1911 if (zloc == NULL) 1912 return FALSE; 1913 } 1914 else if (iuuconf != UUCONF_SUCCESS) 1915 ulog_uuconf (LOG_FATAL, puuconf, iuuconf); 1916 1917 if (strcmp (qsys->uuconf_zname, zloc) != 0 1918#if HAVE_INTERNET_MAIL 1919 && strchr (zmail, '@') == NULL 1920#endif 1921 ) 1922 { 1923 zfree = zbufalc (strlen (qsys->uuconf_zname) 1924 + strlen (zmail) 1925 + sizeof "!"); 1926 sprintf (zfree, "%s!%s", qsys->uuconf_zname, zmail); 1927 zmail = zfree; 1928 } 1929 } 1930 1931 if (! fsysdep_mail (zmail, zsubject, i, pz)) 1932 fret = FALSE; 1933 1934 ubuffree (zfree); 1935 } 1936 1937 while (istdin < i) 1938 { 1939 ubuffree ((char *) pz[istdin]); 1940 istdin++; 1941 } 1942 1943 xfree ((pointer) pz); 1944 1945 return fret; 1946} 1947 1948/* Handle the -q option. For each remote system this lists the number 1949 of jobs queued, the number of executions queued, and the current 1950 call status. We get the executions all at once, because they are 1951 not accessed by system. They could be, but it is possible to have 1952 executions pending for an unknown system, so special handling would 1953 still be required. */ 1954 1955struct sxqtlist 1956{ 1957 struct sxqtlist *qnext; 1958 char *zsystem; 1959 int cxqts; 1960 long ifirst; 1961}; 1962 1963/* These local functions need the definition of sxqtlist for the 1964 prototype. */ 1965 1966static boolean fsquery_system P((const struct uuconf_system *qsys, 1967 struct sxqtlist **pq, 1968 long inow, const char *zlocalname, 1969 int csystems, char **pazsystems, 1970 boolean fnotsystems, long iold, long iyoung)); 1971static boolean fsquery_show P((const struct uuconf_system *qsys, int cwork, 1972 long ifirstwork, struct sxqtlist *qxqt, 1973 long inow, const char *zlocalname, 1974 int csystems, char **pazsystems, 1975 boolean fnotsystems, long iold, long iyoung)); 1976 1977static boolean 1978fsquery (puuconf, csystems, pazsystems, fnotsystems, iold, iyoung) 1979 pointer puuconf; 1980 int csystems; 1981 char **pazsystems; 1982 boolean fnotsystems; 1983 long iold; 1984 long iyoung; 1985{ 1986 int iuuconf; 1987 const char *zlocalname; 1988 struct sxqtlist *qlist; 1989 char *zfile, *zsystem; 1990 boolean ferr; 1991 long inow; 1992 char **pznames, **pz; 1993 boolean fret; 1994 1995 iuuconf = uuconf_localname (puuconf, &zlocalname); 1996 if (iuuconf == UUCONF_NOT_FOUND) 1997 { 1998 zlocalname = zsysdep_localname (); 1999 if (zlocalname == NULL) 2000 return FALSE; 2001 } 2002 else if (iuuconf != UUCONF_SUCCESS) 2003 { 2004 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 2005 return FALSE; 2006 } 2007 2008 /* Get a count of all the execution files. */ 2009 if (! fsysdep_get_xqt_init ((const char *) NULL)) 2010 return FALSE; 2011 2012 qlist = NULL; 2013 while ((zfile = zsysdep_get_xqt ((const char *) NULL, &zsystem, &ferr)) 2014 != NULL) 2015 { 2016 struct sxqtlist *qlook; 2017 2018 for (qlook = qlist; qlook != NULL; qlook = qlook->qnext) 2019 if (strcmp (zsystem, qlook->zsystem) == 0) 2020 break; 2021 2022 if (qlook != NULL) 2023 { 2024 long itime; 2025 2026 ubuffree (zsystem); 2027 ++qlook->cxqts; 2028 itime = ixsysdep_file_time (zfile); 2029 if (itime < qlook->ifirst) 2030 qlook->ifirst = itime; 2031 } 2032 else 2033 { 2034 struct sxqtlist *qnew; 2035 2036 qnew = (struct sxqtlist *) xmalloc (sizeof (struct sxqtlist)); 2037 qnew->qnext = qlist; 2038 qnew->zsystem = zsystem; 2039 qnew->cxqts = 1; 2040 qnew->ifirst = ixsysdep_file_time (zfile); 2041 qlist = qnew; 2042 } 2043 2044 ubuffree (zfile); 2045 } 2046 2047 usysdep_get_xqt_free ((const char *) NULL); 2048 2049 if (ferr) 2050 return FALSE; 2051 2052 inow = ixsysdep_time ((long *) NULL); 2053 2054 /* Show the information for each system. */ 2055 iuuconf = uuconf_system_names (puuconf, &pznames, 0); 2056 if (iuuconf != UUCONF_SUCCESS) 2057 { 2058 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 2059 return FALSE; 2060 } 2061 2062 fret = TRUE; 2063 2064 for (pz = pznames; *pz != NULL; pz++) 2065 { 2066 struct uuconf_system ssys; 2067 2068 iuuconf = uuconf_system_info (puuconf, *pz, &ssys); 2069 if (iuuconf != UUCONF_SUCCESS) 2070 { 2071 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 2072 fret = FALSE; 2073 continue; 2074 } 2075 2076 if (! fsquery_system (&ssys, &qlist, inow, zlocalname, csystems, 2077 pazsystems, fnotsystems, iold, iyoung)) 2078 fret = FALSE; 2079 2080 (void) uuconf_system_free (puuconf, &ssys); 2081 xfree ((pointer) *pz); 2082 } 2083 2084 /* Check for the local system in the list of execution files. */ 2085 if (qlist != NULL) 2086 { 2087 struct sxqtlist **pq; 2088 2089 for (pq = &qlist; *pq != NULL; pq = &(*pq)->qnext) 2090 { 2091 if (strcmp ((*pq)->zsystem, zlocalname) == 0) 2092 { 2093 struct uuconf_system ssys; 2094 struct sxqtlist *qfree; 2095 2096 iuuconf = uuconf_system_info (puuconf, zlocalname, &ssys); 2097 if (iuuconf != UUCONF_SUCCESS) 2098 { 2099 if (iuuconf != UUCONF_NOT_FOUND) 2100 { 2101 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 2102 fret = FALSE; 2103 break; 2104 } 2105 2106 iuuconf = uuconf_system_local (puuconf, &ssys); 2107 if (iuuconf != UUCONF_SUCCESS) 2108 { 2109 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 2110 fret = FALSE; 2111 break; 2112 } 2113 ssys.uuconf_zname = (char *) zlocalname; 2114 } 2115 2116 if (! fsquery_show (&ssys, 0, 0L, *pq, inow, zlocalname, 2117 csystems, pazsystems, fnotsystems, 2118 iold, iyoung)) 2119 fret = FALSE; 2120 (void) uuconf_system_free (puuconf, &ssys); 2121 qfree = *pq; 2122 *pq = qfree->qnext; 2123 ubuffree (qfree->zsystem); 2124 xfree ((pointer) qfree); 2125 break; 2126 } 2127 } 2128 } 2129 2130 /* Print out information for any unknown systems for which we have 2131 execution files. */ 2132 while (qlist != NULL) 2133 { 2134 struct uuconf_system ssys; 2135 struct sxqtlist *qnext; 2136 2137 if (! funknown_system (puuconf, qlist->zsystem, &ssys)) 2138 { 2139 ulog (LOG_ERROR, "Executions queued up for unknown systems"); 2140 fret = FALSE; 2141 break; 2142 } 2143 2144 if (! fsquery_show (&ssys, 0, 0L, qlist, inow, zlocalname, 2145 csystems, pazsystems, fnotsystems, iold, iyoung)) 2146 fret = FALSE; 2147 (void) uuconf_system_free (puuconf, &ssys); 2148 qnext = qlist->qnext; 2149 ubuffree (qlist->zsystem); 2150 xfree ((pointer) qlist); 2151 qlist = qnext; 2152 } 2153 2154 return fret; 2155} 2156 2157/* Query a single known system. */ 2158 2159static boolean 2160fsquery_system (qsys, pq, inow, zlocalname, csystems, pazsystems, 2161 fnotsystems, iold, iyoung) 2162 const struct uuconf_system *qsys; 2163 struct sxqtlist **pq; 2164 long inow; 2165 const char *zlocalname; 2166 int csystems; 2167 char **pazsystems; 2168 boolean fnotsystems; 2169 long iold; 2170 long iyoung; 2171{ 2172 int cwork; 2173 long ifirstwork; 2174 char *zid; 2175 boolean fret; 2176 2177 if (! fsysdep_get_work_init (qsys, UUCONF_GRADE_LOW, 0)) 2178 return FALSE; 2179 2180 cwork = 0; 2181 ifirstwork = 0L; 2182 zid = NULL; 2183 while (TRUE) 2184 { 2185 struct scmd s; 2186 long itime; 2187 char *zthisid; 2188 2189 if (! fsysdep_get_work (qsys, UUCONF_GRADE_LOW, 0, &s)) 2190 return FALSE; 2191 if (s.bcmd == 'H') 2192 break; 2193 2194 zthisid = zsysdep_jobid (qsys, s.pseq); 2195 if (zid != NULL && strcmp (zid, zthisid) == 0) 2196 ubuffree (zthisid); 2197 else 2198 { 2199 ++cwork; 2200 ubuffree (zid); 2201 zid = zthisid; 2202 } 2203 2204 itime = ixsysdep_work_time (qsys, s.pseq); 2205 if (ifirstwork == 0L || ifirstwork > itime) 2206 ifirstwork = itime; 2207 } 2208 2209 usysdep_get_work_free (qsys); 2210 ubuffree (zid); 2211 2212 /* Find the execution information, if any. */ 2213 while (*pq != NULL) 2214 { 2215 if (strcmp ((*pq)->zsystem, qsys->uuconf_zname) == 0) 2216 break; 2217 pq = &(*pq)->qnext; 2218 } 2219 2220 /* If there are no commands and no executions, don't print any 2221 information for this system. */ 2222 if (cwork == 0 && *pq == NULL) 2223 return TRUE; 2224 2225 fret = fsquery_show (qsys, cwork, ifirstwork, *pq, inow, 2226 zlocalname, csystems, pazsystems, fnotsystems, 2227 iold, iyoung); 2228 2229 if (*pq != NULL) 2230 { 2231 struct sxqtlist *qfree; 2232 2233 qfree = *pq; 2234 *pq = qfree->qnext; 2235 ubuffree (qfree->zsystem); 2236 xfree ((pointer) qfree); 2237 } 2238 2239 return fret; 2240} 2241 2242/* Print out the query information for a single system. We handle the 2243 local system specially. */ 2244 2245static boolean 2246fsquery_show (qsys, cwork, ifirstwork, qxqt, inow, zlocalname, 2247 csystems, pazsystems, fnotsystems, iold, iyoung) 2248 const struct uuconf_system *qsys; 2249 int cwork; 2250 long ifirstwork; 2251 struct sxqtlist *qxqt; 2252 long inow; 2253 const char *zlocalname; 2254 int csystems; 2255 char **pazsystems; 2256 boolean fnotsystems; 2257 long iold; 2258 long iyoung; 2259{ 2260 boolean flocal; 2261 struct sstatus sstat; 2262 boolean fnostatus; 2263 struct tm stime; 2264 int cpad; 2265 2266 /* Make sure this is one of the systems we are printing. */ 2267 if (csystems > 0) 2268 { 2269 boolean fmatch; 2270 int i; 2271 2272 fmatch = fnotsystems; 2273 for (i = 0; i < csystems; i++) 2274 { 2275 if (strcmp (pazsystems[i], qsys->uuconf_zname) == 0) 2276 { 2277 fmatch = ! fmatch; 2278 break; 2279 } 2280 } 2281 if (! fmatch) 2282 return TRUE; 2283 } 2284 2285 /* Make sure the commands are within the time bounds. */ 2286 if ((iold != (long) -1 2287 && (cwork == 0 || ifirstwork > iold) 2288 && (qxqt == NULL || qxqt->ifirst > iold)) 2289 || (iyoung != (long) -1 2290 && (cwork == 0 || ifirstwork < iyoung) 2291 && (qxqt == NULL || qxqt->ifirst < iyoung))) 2292 return TRUE; 2293 2294 flocal = strcmp (qsys->uuconf_zname, zlocalname) == 0; 2295 2296 if (! flocal) 2297 { 2298 if (! fsysdep_get_status (qsys, &sstat, &fnostatus)) 2299 return FALSE; 2300 } 2301 2302 printf ("%-10s %3dC (", qsys->uuconf_zname, cwork); 2303 2304 if (cwork == 0) 2305 { 2306 printf ("0 secs"); 2307 cpad = 3; 2308 } 2309 else 2310 cpad = csunits_show (inow - ifirstwork); 2311 2312 printf (") "); 2313 while (cpad-- != 0) 2314 printf (" "); 2315 2316 if (qxqt == NULL) 2317 printf (" 0X (0 secs) "); 2318 else 2319 { 2320 printf ("%3dX (", qxqt->cxqts); 2321 cpad = csunits_show (inow - qxqt->ifirst); 2322 printf (")"); 2323 while (cpad-- != 0) 2324 printf (" "); 2325 } 2326 2327 if (flocal || fnostatus) 2328 { 2329 printf ("\n"); 2330 if (! flocal) 2331 ubuffree (sstat.zstring); 2332 return TRUE; 2333 } 2334 2335 usysdep_localtime (sstat.ilast, &stime); 2336 2337 printf (" %02d-%02d %02d:%02d ", 2338 stime.tm_mon + 1,stime.tm_mday, stime.tm_hour, stime.tm_min); 2339 2340 if (sstat.zstring == NULL) 2341 printf ("%s\n", azStatus[(int) sstat.ttype]); 2342 else 2343 { 2344 printf ("%s\n", sstat.zstring); 2345 ubuffree (sstat.zstring); 2346 } 2347 2348 return TRUE; 2349} 2350 2351/* Print a time difference in the largest applicable units. */ 2352 2353static int 2354csunits_show (idiff) 2355 long idiff; 2356{ 2357 const char *zunit; 2358 long iunits; 2359 int cpad; 2360 2361 if (idiff > (long) 24 * (long) 60 * (long) 60) 2362 { 2363 iunits = idiff / ((long) 24 * (long) 60 * (long) 60); 2364 zunit = "day"; 2365 cpad = 4; 2366 } 2367 else if (idiff > (long) 60 * 60) 2368 { 2369 iunits = idiff / (long) (60 * 60); 2370 zunit = "hour"; 2371 cpad = 3; 2372 } 2373 else if (idiff > (long) 60) 2374 { 2375 iunits = idiff / (long) 60; 2376 zunit = "min"; 2377 cpad = 4; 2378 } 2379 else 2380 { 2381 iunits = idiff; 2382 zunit = "sec"; 2383 cpad = 4; 2384 } 2385 2386 printf ("%ld %s%s", iunits, zunit, iunits == 1 ? "" : "s"); 2387 2388 if (iunits != 1) 2389 --cpad; 2390 if (iunits > 99) 2391 --cpad; 2392 if (iunits > 9) 2393 --cpad; 2394 return cpad; 2395} 2396 2397/* Give a list of all status entries for all machines that we have 2398 status entries for. We need to get a list of status entries in a 2399 system dependent fashion, since we may have status for unknown 2400 systems. */ 2401 2402static boolean 2403fsmachines () 2404{ 2405 pointer phold; 2406 char *zsystem; 2407 boolean ferr; 2408 struct sstatus sstat; 2409 2410 if (! fsysdep_all_status_init (&phold)) 2411 return FALSE; 2412 2413 while ((zsystem = zsysdep_all_status (phold, &ferr, &sstat)) != NULL) 2414 { 2415 struct tm stime; 2416 2417 usysdep_localtime (sstat.ilast, &stime); 2418 printf ("%-14s %02d-%02d %02d:%02d ", zsystem, 2419 stime.tm_mon + 1, stime.tm_mday, stime.tm_hour, 2420 stime.tm_min); 2421 if (sstat.zstring == NULL) 2422 printf ("%s", azStatus[(int) sstat.ttype]); 2423 else 2424 { 2425 printf ("%s", sstat.zstring); 2426 ubuffree (sstat.zstring); 2427 } 2428 ubuffree (zsystem); 2429 if (sstat.ttype != STATUS_TALKING 2430 && sstat.cwait > 0) 2431 { 2432 printf (" (%d %s", sstat.cretries, 2433 sstat.cretries == 1 ? "try" : "tries"); 2434 if (sstat.ilast + sstat.cwait > ixsysdep_time ((long *) NULL)) 2435 { 2436 usysdep_localtime (sstat.ilast + sstat.cwait, &stime); 2437 printf (", next after %02d-%02d %02d:%02d", 2438 stime.tm_mon + 1, stime.tm_mday, stime.tm_hour, 2439 stime.tm_min); 2440 } 2441 printf (")"); 2442 } 2443 printf ("\n"); 2444 } 2445 2446 usysdep_all_status_free (phold); 2447 2448 return ! ferr; 2449} 2450