GCCluster: qstat.c

File qstat.c, 55.1 KB (added by Pieter Neerincx, 12 years ago)

Patched qstat.c for long job names

Line 
1/*
2*         OpenPBS (Portable Batch System) v2.3 Software License
3*
4* Copyright (c) 1999-2000 Veridian Information Solutions, Inc.
5* All rights reserved.
6*
7* ---------------------------------------------------------------------------
8* For a license to use or redistribute the OpenPBS software under conditions
9* other than those described below, or to purchase support for this software,
10* please contact Veridian Systems, PBS Products Department ("Licensor") at:
11*
12*    www.OpenPBS.org  +1 650 967-4675                  sales@OpenPBS.org
13*                        877 902-4PBS (US toll-free)
14* ---------------------------------------------------------------------------
15*
16* This license covers use of the OpenPBS v2.3 software (the "Software") at
17* your site or location, and, for certain users, redistribution of the
18* Software to other sites and locations.  Use and redistribution of
19* OpenPBS v2.3 in source and binary forms, with or without modification,
20* are permitted provided that all of the following conditions are met.
21* After December 31, 2001, only conditions 3-6 must be met:
22*
23* 3. Any Redistribution of source code must retain the above copyright notice
24*    and the acknowledgment contained in paragraph 6, this list of conditions
25*    and the disclaimer contained in paragraph 7.
26*
27* 4. Any Redistribution in binary form must reproduce the above copyright
28*    notice and the acknowledgment contained in paragraph 6, this list of
29*    conditions and the disclaimer contained in paragraph 7 in the
30*    documentation and/or other materials provided with the distribution.
31*
32* 5. Redistributions in any form must be accompanied by information on how to
33*    obtain complete source code for the OpenPBS software and any
34*    modifications and/or additions to the OpenPBS software.  The source code
35*    must either be included in the distribution or be available for no more
36*    than the cost of distribution plus a nominal fee, and all modifications
37*    and additions to the Software must be freely redistributable by any party
38*    (including Licensor) without restriction.
39*
40* 6. All advertising materials mentioning features or use of the Software must
41*    display the following acknowledgment:
42*
43*     "This product includes software developed by NASA Ames Research Center,
44*     Lawrence Livermore National Laboratory, and Veridian Information
45*     Solutions, Inc.
46*     Visit www.OpenPBS.org for OpenPBS software support,
47*     products, and information."
48*
49* 7. DISCLAIMER OF WARRANTY
50*
51* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. ANY EXPRESS
52* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
53* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT
54* ARE EXPRESSLY DISCLAIMED.
55*
56* IN NO EVENT SHALL VERIDIAN CORPORATION, ITS AFFILIATED COMPANIES, OR THE
57* U.S. GOVERNMENT OR ANY OF ITS AGENCIES BE LIABLE FOR ANY DIRECT OR INDIRECT,
58* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
59* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
60* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
61* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
62* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
63* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64*
65* This license will be governed by the laws of the Commonwealth of Virginia,
66* without reference to its choice of law rules.
67*/
68/*
69 *
70 * qstat - (PBS) show stats of batch jobs, queues, or servers
71 *
72 * Authors:
73 *      Terry Heidelberg
74 *      Livermore Computing
75 *
76 *      Bruce Kelly
77 *      National Energy Research Supercomputer Center
78 *
79 *      Lawrence Livermore National Laboratory
80 *      University of California
81 */
82
83#include <pbs_config.h>   /* the master config generated by configure */
84
85#include <pwd.h>
86#include <limits.h>
87
88#if TCL_QSTAT
89#include <sys/stat.h>
90#include <tcl.h>
91#if TCLX
92#include <tclExtend.h>
93#endif
94#endif
95
96#include "cmds.h"
97#include "mcom.h"
98#include "utils.h"
99
100static void states();
101
102#if !defined(PBS_NO_POSIX_VIOLATION)
103/* defines for alternative display formats */
104#define ALT_DISPLAY_a 1 /* -a option - show all jobs */
105#define ALT_DISPLAY_i 2 /* -i option - show not running */
106#define ALT_DISPLAY_r 4 /* -r option - show only running */
107#define ALT_DISPLAY_u 8 /* -u option - list user's jobs */
108#define ALT_DISPLAY_n 0x10 /* -n option - add node list */
109#define ALT_DISPLAY_s 0x20 /* -s option - add scheduler comment */
110#define ALT_DISPLAY_R 0x40 /* -R option - add SRFS info */
111
112#define ALT_DISPLAY_q 0x80 /* -q option - alt queue display */
113
114#define ALT_DISPLAY_Mb 0x100 /* show sizes in MB */
115#define ALT_DISPLAY_Mw 0x200 /* -M option - show sizes in MW */
116#define ALT_DISPLAY_G 0x400 /* -G option - show sizes in GB */
117#define ALT_DISPLAY_o   0x800   /* -1 option - add node list on same line */
118#endif /* not PBS_NO_POSIX_VIOLATION */
119
120
121
122/* globals */
123
124mbool_t DisplayXML = FALSE;
125#define maxlinesize 65536
126int   linesize = 77;
127
128int   tasksize;
129
130static char *summarize_arrays_extend_opt = "summarize_arrays";
131
132/* END globals */
133
134
135#define DEFTASKSIZE 6
136
137int   tasksize = DEFTASKSIZE;
138int   alias_opt = FALSE;
139
140
141
142int isjobid(
143
144  char *string)
145
146  {
147  int i;
148  int result;
149
150  i = strspn(string, " "); /* locate first non-blank */
151
152  if (isdigit(string[i]))
153    result = 1;  /* job_id */
154  else if (isalpha(string[i]))
155    result = 0; /* not a job_id */
156  else
157    result = 0;  /* who knows - probably a syntax error */
158
159  return(result);
160  }  /* END isjobid() */
161
162
163
164
165
166int istrue(
167
168  char *string)  /* I */
169
170  {
171  if (!strcasecmp(string, "TRUE"))
172    {
173    return(TRUE);
174    }
175
176  if (!strcmp(string, "1"))
177    {
178    return(TRUE);
179    }
180
181  return(FALSE);
182  }  /* END istrue() */
183
184
185
186
187
188static void states(
189
190  char *string, /* I */
191  char *q,      /* O */
192  char *r,      /* O */
193  char *h,      /* O */
194  char *w,      /* O */
195  char *t,      /* O */
196  char *e,      /* O */
197  int   len)    /* I */
198
199  {
200  char *c, *d, *f, *s, l;
201
202  /* FORMAT:  Queued:X Running:Y... */
203
204  c = string;
205
206  while (isspace(*c) && *c != '\0')
207    c++;
208
209  while (*c != '\0')
210    {
211    s = c;
212
213    while (*c != ':')
214      c++;
215
216    *c = '\0';
217
218    d = NULL;
219
220    if (strcmp(s, "Queued") == 0)
221      d = q;
222    else if (strcmp(s, "Running") == 0)
223      d = r;
224    else if (strcmp(s, "Held")    == 0)
225      d = h;
226    else if (strcmp(s, "Waiting") == 0)
227      d = w;
228    else if (strcmp(s, "Transit") == 0)
229      d = t;
230    else if (strcmp(s, "Exiting") == 0)
231      d = e;
232
233    c++;
234
235    if (d != NULL)
236      {
237      s = c;
238
239      while ((*c != ' ') && (*c != '\0'))
240        c++;
241
242      l = *c;
243
244      *c = '\0';
245
246      if (strlen(s) > (size_t)len)
247        {
248        f = s + len;
249        *f = '\0';
250        }
251
252      strcpy(d, s);
253
254      if (l != '\0')
255        c++;
256      }
257    }
258
259  return;
260  }  /* END states() */
261
262
263
264
265
266/*
267 * print an attribute value string, formating to break a comma if possible
268 */
269
270void prt_attr(
271
272  char *n,  /* I name */
273  char *r,  /* I resource (optional) */
274  char *v)  /* I value */
275
276  {
277  char *c;
278  char *comma = ",";
279  int   first = 1;
280  int   l;
281  int   start;
282
283  start = strlen(n) + 7; /* 4 spaces + ' = ' is 7 */
284
285  printf("    %s",
286         n);
287
288  if (r != NULL)
289    {
290    start += strlen(r) + 1;
291
292    printf(".%s",
293           r);
294    }
295
296  printf(" = ");
297
298  c = strtok(v, comma);
299
300  while (c != NULL)
301    {
302    if ((l = strlen(c)) + start < linesize)
303      {
304      printf("%s",
305             c);
306
307      start += l;
308      }
309    else
310      {
311      if (!first)
312        {
313        printf("\n\t");
314
315        start = 9;
316        }
317
318      while (*c)
319        {
320        putchar(*c++);
321
322        if (++start > linesize)
323          {
324          start = 8;
325
326          printf("\n\t");
327          }
328        }
329      }
330
331    if ((c = strtok(NULL, comma)) != NULL)
332      {
333      first = 0;
334
335      putchar(',');
336      }
337    }
338
339  return;
340  }  /* END prt_attr() */
341
342
343
344
345
346/*
347 * locate an attribute (attrl) by name (and resource) and return value
348 * returns null if not found
349 */
350
351static char *findattrl(
352
353  struct attrl *pattrl,
354  char        *name,
355  char         *resc)
356
357  {
358  while (pattrl != NULL)
359    {
360    if (!strcmp(name, pattrl->name))
361      {
362      if (resc != NULL)
363        {
364        if (!strcmp(resc, pattrl->resource))
365          {
366          return(pattrl->value);
367          }
368        }
369      else
370        {
371        return(pattrl->value);
372        }
373      }
374
375    pattrl = pattrl->next;
376    }
377
378  return(NULL);
379  }
380
381#ifndef PBS_MINNAMELEN
382#define PBS_MINNAMELEN  40 /* min size for printf job jobs, queues, and servers */
383#endif /* PBS_MINNAMELEN */
384
385#ifndef PBS_NAMELEN
386#define PBS_NAMELEN  40  /* printf of jobs, queues, and servers */
387#endif  /* PBS_NAMELEN */
388
389#define OWNERL  15  /* printf of jobs */
390#define TIMEUL  8   /* printf of jobs */
391#define STATEL  1   /* printf of jobs */
392#define LOCL    15  /* printf of jobs */
393#define SIZEL 6   /* length of "SIZE" fields in printf */
394
395
396
397
398/*
399 * Format and display string of assigned nodes, (1) strip off domain name
400 * if present and (2) break line at '+' sign.
401 */
402
403static void prt_nodes(
404
405  char *nodes)   /* I */
406
407  {
408  int   i;
409  char *stp;
410
411  char  linebuf[65536];
412
413  if ((nodes == NULL) || (*nodes == '\0'))
414    {
415    /* FAILURE - node is invalid */
416
417    return;
418    }
419
420  i = 0;
421
422  stp = nodes;
423
424  while (*nodes != '\0')
425    {
426    if ((*stp == '.') || (*stp == '+') || (*stp == '\0'))
427      {
428      /* does node fit into line? */
429
430      if (i + stp - nodes < linesize)
431        {
432        while (nodes < stp)
433          linebuf[i++] = *nodes++;
434        }
435      else
436        {
437        /* flush line and start next */
438
439        linebuf[i] = '\0';
440
441        printf("   %s\n",
442               linebuf);
443
444        i = 0;
445
446        while (nodes < stp)
447          linebuf[i++] = *nodes++;
448        }
449
450      /* strip off domain name to keep string short */
451
452      while ((*stp != '+') && (*stp != '\0'))
453        stp++;
454
455      nodes = stp++;
456      }
457    else
458      {
459      stp++;
460      }
461    }
462
463  if (i != 0)
464    {
465    linebuf[i] = '\0';
466
467    printf("   %s\n",
468           linebuf);
469    }
470
471  return;
472  }  /* END prt_nodes() */
473
474
475
476
477
478/*
479 * convert size from suffix string (nnnn[ kmgt][ bw]) to string of
480 * k[bw] for neither -M or -G
481 * mw    for   -M
482 * gb    for   -G
483 */
484
485static char *cnv_size(
486
487  char *value,
488  int   opt)
489
490  {
491  static int sift_factor[3][5] =
492    {
493      { -20, -10, 0, 10, 20 }, /* mb conversion */
494    { -23, -13, -3, 7, 17 }, /* mw conversion */
495    { -30, -20, -10, 0, 10 }
496    }; /* gb conversion */
497
498  int in;
499  int out;
500  int sft;
501  unsigned long nval;
502  char *pc;
503  char *suffix;
504  static char outbuf[25];
505
506  if (opt & ALT_DISPLAY_Mb)
507    {
508    out = 0;
509
510    suffix = "mb";
511    }
512  else if (opt & ALT_DISPLAY_Mw)
513    {
514    out = 1;
515
516    suffix = "mw";
517    }
518  else if (opt & ALT_DISPLAY_G)
519    {
520    out = 2;
521
522    suffix = "gb";
523    }
524  else
525    {
526    return (value);  /* return unmodified */
527    }
528
529  nval = strtol(value, &pc, 10);
530
531  if (*pc == 'k')
532    in = 1;
533  else if (*pc == 'm')
534    in = 2;
535  else if (*pc == 'g')
536    in = 3;
537  else if (*pc == 't')
538    in = 4;
539  else
540    in = 0;
541
542  sft = sift_factor[out][in];
543
544  if ((*pc == 'w') || (*(pc + 1) == 'w'))
545    nval = nval << 3; /* convert to bytes */
546
547  if (sft < 0)
548    {
549    nval = nval + ((1 << -sft) - 1);  /* round up (ceiling) */
550    nval = nval >> -sft;
551    }
552  else
553    {
554    nval = nval << sft;
555    }
556
557  sprintf(outbuf, "%lu%s",
558
559          nval,
560          suffix);
561
562  return(outbuf);
563  }
564
565
566
567
568
569/*
570 * Format and display status of job in alternate form (not POSIX standard)
571 */
572
573static void altdsp_statjob(
574
575  struct batch_status *pstat,     /* I */
576  struct batch_status *prtheader, /* I */
577  int                  alt_opt)   /* I */
578
579  {
580  char *comment;
581  char *pc;
582
583  struct attrl *pat;
584  char *exechost;
585  char *usern = NULL;
586  char *queuen = NULL;
587  char *jobn = NULL;
588  char *sess;
589  char *tasks;
590  char  calcTasks[64];
591  char *nodect;
592  char *rqtimecpu;
593  char *rqtimewal;
594  char *jstate;
595  char *eltimecpu;
596  char *eltimewal;
597  char tmpLine[MAX_LINE_LEN+1];
598
599  int   usecput;
600  static char  pfs[SIZEL];
601  static char  rqmem[SIZEL];
602  static char  srfsbig[SIZEL];
603  static char  srfsfast[SIZEL];
604  static char *blank = " -- ";
605
606  if (prtheader)
607    {
608    printf("\n%s: ",
609           prtheader->name);
610
611    if ((pc = findattrl(prtheader->attribs, ATTR_comment, NULL)) != NULL)
612      {
613      printf("%s",
614             pc);
615      }
616
617    if (alt_opt & ALT_DISPLAY_R)
618      {
619      printf("\n                                                 Req'd  Req'd   Elap \n");
620
621      printf("Job ID               Username    Queue    NDS   TSK    Memory Time  S Time   BIG  FAST   PFS\n");
622
623      printf("-------------------- ----------- -------- ----- ------ ------ ----- - ----- ----- ----- -----\n");
624      }
625    else
626      {
627      /*
628      printf("\n                                                                         Req'd  Req'd   Elap\n");
629
630      printf("Job ID               Username    Queue    Jobname          SessID NDS   TSK    Memory Time  S Time\n");
631
632      printf("-------------------- ----------- -------- ---------------- ------ ----- ------ ------ ----- - -----\n");
633      */
634      printf("\n                                                                                                       Req'd  Req'd   Elap\n");
635
636      printf("Job ID               Username    Queue    Jobname                                  SessID NDS   TSK    Memory Time  S Time\n");
637
638      printf("-------------------- ----------- -------- ---------------------------------------- ------ ----- ------ ------ ----- - -----\n");
639      }
640    }
641
642  while (pstat != NULL)
643    {
644    exechost  = blank;
645    sess      = blank;
646    nodect    = blank;
647    tasks     = blank;
648    rqtimecpu = blank;
649    rqtimewal = blank;
650    eltimecpu = blank;
651    eltimewal = blank;
652    jstate    = blank;
653    comment   = blank;
654    /* *pfs      = *blank;  */
655    strcpy(pfs, blank);
656    /* *rqmem    = *blank;  */
657    strcpy(rqmem, blank);
658    /* *srfsbig  = *blank;  */
659    strcpy(srfsbig, blank);
660    /* *srfsfast = *blank;  */
661    strcpy(srfsfast, blank);
662    usecput = 0;
663
664    pat = pstat->attribs;
665
666    while (pat != NULL)
667      {
668      if (!strcmp(pat->name, ATTR_N))
669        {
670        jobn = pat->value;
671        }
672      else if (!strcmp(pat->name, ATTR_owner))
673        {
674        usern = pat->value;
675
676        if ((pc = strchr(usern, (int)'@')) != NULL)
677          * pc = '\0';
678        }
679      else if (!strcmp(pat->name, ATTR_state))
680        {
681        jstate = pat->value;
682        }
683      else if (!strcmp(pat->name, ATTR_queue))
684        {
685        queuen = pat->value;
686        }
687      else if (!strcmp(pat->name, ATTR_session))
688        {
689        sess = pat->value;
690        }
691      else if (!strcmp(pat->name, ATTR_l))
692        {
693        if (!strcmp(pat->resource, "nodect"))
694          {
695          nodect = pat->value;
696          }
697        else if (!strcmp(pat->resource, "nodes"))
698          {
699          char *tmp = pat->value;
700          char *eq = strchr(tmp,'=');
701         
702          if (eq != NULL)
703            {
704            int nodes = atoi(pat->value);
705            int procs = atoi(eq+1);
706
707            sprintf(calcTasks,"%d",nodes*procs);
708            tasks = calcTasks;
709            }
710          else
711            {
712            tasks = pat->value;
713            }
714
715          }
716        else if (!strcmp(pat->resource, "ncpus"))
717          {
718          if ((!strcmp(tasks,blank)) && (strcmp(pat->value, "0")))
719            tasks = pat->value;
720          }
721        else if (!strcmp(pat->resource, "mppe"))
722          {
723          if (strcmp(pat->value, "0"))
724            tasks = pat->value;
725          }
726        else if (!strcmp(pat->resource, "size"))
727          {
728          if (strcmp(pat->value, "0"))
729            tasks = pat->value;
730          }
731        else if (!strcmp(pat->resource, "mem"))
732          {
733          strncpy(rqmem, cnv_size(pat->value, alt_opt), SIZEL);
734          }
735        else if (!strcmp(pat->resource, "walltime"))
736          {
737          rqtimewal = pat->value;
738          }
739        else if (!strcmp(pat->resource, "cput"))
740          {
741          rqtimecpu = pat->value;
742          usecput = 1;
743          }
744        else if (!strcmp(pat->resource, "srfs_big"))
745          {
746          strncpy(srfsbig, cnv_size(pat->value, alt_opt), SIZEL - 1);
747          }
748        else if (!strcmp(pat->resource, "srfs_fast"))
749          {
750          strncpy(srfsfast, cnv_size(pat->value, alt_opt), SIZEL - 1);
751          }
752        else if (!strcmp(pat->resource, "piofs"))
753          {
754          strncpy(pfs, cnv_size(pat->value, alt_opt), SIZEL - 1);
755          }
756        }
757      else if (!strcmp(pat->name, ATTR_exechost))
758        {
759        exechost = pat->value;
760        }
761      else if (!strcmp(pat->name, ATTR_used))
762        {
763        if (!strcmp(pat->resource, "walltime"))
764          {
765          eltimewal = pat->value;
766          }
767        else if (!strcmp(pat->resource, "cput"))
768          {
769          eltimecpu = pat->value;
770          }
771        }
772      else if (!strcmp(pat->name, ATTR_comment))
773        {
774        comment = pat->value;
775        }
776
777      pat = pat->next;
778      }
779
780    snprintf(tmpLine, MAX_LINE_LEN, "%%-20.%ds %%-11.11s %%-8.8s ",
781
782             PBS_NAMELEN);
783
784    printf(tmpLine,
785           pstat->name,
786           usern,
787           queuen);
788
789    if (alt_opt & ALT_DISPLAY_R)
790      {
791      printf("%5.5s %*.*s %6.6s %5.5s %1.1s %5.5s %5.5s %5.5s %5.5s",
792             nodect,
793             tasksize,
794             tasksize,
795             tasks,
796             rqmem,
797             usecput ? rqtimecpu : rqtimewal,
798             jstate,
799             usecput ? eltimecpu : eltimewal,
800             srfsbig,
801             srfsfast,
802             pfs);
803      }
804    else
805      {
806      snprintf(tmpLine, MAX_LINE_LEN, "%%-%d.%ds %%6.6s %%5.5s %%*.*s %%6.6s %%5.5s %%1.1s %%5.5s",
807               PBS_NAMELEN, PBS_NAMELEN);
808
809      printf(tmpLine,
810             jobn,
811             sess,
812             nodect,
813             tasksize,
814             tasksize,
815             tasks,
816             rqmem,
817             usecput ? rqtimecpu : rqtimewal,
818             jstate,
819             usecput ? eltimecpu : eltimewal);
820      }
821
822    if (linesize < maxlinesize)
823      printf("\n");
824
825    if (alt_opt & ALT_DISPLAY_n)
826      {
827      /* print assigned nodes */
828
829      prt_nodes(exechost);
830      }
831
832    if (alt_opt & ALT_DISPLAY_s)
833      {
834      /* print (scheduler) comment */
835
836      if (*comment != '\0')
837        printf("   %s\n",
838               comment);
839      }
840
841    pstat = pstat->next;
842    }
843
844  return;
845  }  /* END altdsp_statjob() */
846
847
848
849
850/*
851 * get_ct - get count of jobs in queue/run state
852 * support function for altdsp_statque()
853 */
854
855static void get_ct(
856
857  char *str,
858  int  *jque,
859  int  *jrun)
860
861  {
862  char *ps;
863  int   colon = (int)':';
864
865  ps = strchr(str, colon); /* Transit - skip */
866
867  ps = strchr(ps + 1, colon); /* Queued  - add to jque */
868
869  *jque += atoi(ps + 1);
870
871  ps = strchr(ps + 1, colon); /* Held    - add to jque  */
872
873  *jque += atoi(ps + 1);
874
875  ps = strchr(ps + 1, colon); /* Waiting - add to jque  */
876
877  *jque += atoi(ps + 1);
878
879  ps = strchr(ps + 1, colon); /* Running - add to jrun  */
880
881  *jrun += atoi(ps + 1);
882
883  return;
884  }  /* END get_ct() */
885
886
887
888
889
890/*
891 * altdsp_statque - alternative display for queue information, -q option
892 */
893
894static void altdsp_statque(
895
896  char                *serv,
897  struct batch_status *pstat,
898  int                  opt)
899
900  {
901  char  rmem[SIZEL];
902  char *cput;
903  char *wallt;
904  char *jmax;
905  char *nodect;
906  char *blank = "--   ";
907  int   jrun;
908  int   jque;
909  char  qenabled = '\0';
910  char  qstarted = '\0';
911  int   tot_jrun = 0;
912  int   tot_jque = 0;
913
914  struct attrl *pat;
915
916  printf("\nserver: %s\n\n", serv);
917  printf("Queue            Memory CPU Time Walltime Node  Run Que Lm  State\n");
918  printf("---------------- ------ -------- -------- ----  --- --- --  -----\n");
919
920  while (pstat != NULL)
921    {
922    /* *rmem = '\0'; */
923
924    strncpy(rmem, "--  ", SIZEL - 1);
925
926    cput  = blank;
927    wallt = blank;
928    nodect = "-- ";
929    jrun  = 0;
930    jque  = 0;
931    jmax  = blank;
932
933    pat = pstat->attribs;
934
935    while (pat != NULL)
936      {
937      if (strcmp(pat->name, ATTR_maxrun) == 0)
938        {
939        jmax = pat->value;
940        }
941      else if (strcmp(pat->name, ATTR_enable) == 0)
942        {
943        if (*pat->value == 'T')
944          qenabled = 'E';
945        else
946          qenabled = 'D';
947        }
948      else if (strcmp(pat->name, ATTR_start) == 0)
949        {
950        if (*pat->value == 'T')
951          qstarted = 'R';
952        else
953          qstarted = 'S';
954        }
955      else if (strcmp(pat->name, ATTR_count) == 0)
956        {
957        get_ct(pat->value, &jque, &jrun);
958
959        tot_jque += jque;
960        tot_jrun += jrun;
961        }
962      else if (strcmp(pat->name, ATTR_rescmax) == 0)
963        {
964        if (strcmp(pat->resource, "mem") == 0)
965          {
966          strncpy(
967            rmem,
968            cnv_size(pat->value, opt),
969            SIZEL);
970          }
971        else if (strcmp(pat->resource, "cput") == 0)
972          {
973          cput = pat->value;
974          }
975        else if (strcmp(pat->resource, "walltime") == 0)
976          {
977          wallt = pat->value;
978          }
979        else if (strcmp(pat->resource, "nodect") == 0)
980          {
981          nodect = pat->value;
982          }
983        }
984
985      pat = pat->next;
986      }
987
988    printf("%-16.16s %6.6s %8.8s %8.8s %5.5s ",
989
990           pstat->name,
991           rmem,
992           cput,
993           wallt,
994           nodect);
995
996    printf("%3d %3d %2.2s   %c %c\n",
997           jrun,
998           jque,
999           jmax,
1000           qenabled,
1001           qstarted);
1002
1003    pstat = pstat->next;
1004    }  /* END while (pstat != NULL) */
1005
1006  printf("                                               ----- -----\n");
1007
1008  printf("                                               %5d %5d\n",
1009         tot_jrun,
1010         tot_jque);
1011
1012  return;
1013  }  /* END altdsp_statque() */
1014
1015
1016
1017
1018
1019/* build and add an attropl struct to the list */
1020
1021static void add_atropl(
1022
1023  struct attropl **list,
1024  char            *name,
1025  char            *resc,
1026  char            *value,
1027  enum batch_op    op)
1028
1029  {
1030
1031  struct attropl *patro;
1032
1033  patro = (struct attropl *)malloc(sizeof(struct attropl));
1034
1035  if (patro == NULL)
1036    {
1037    fprintf(stderr, "cannot malloc space\n");
1038
1039    exit(1);
1040    }
1041
1042  patro->next     = *list;
1043
1044  patro->name     = name;
1045  patro->resource = resc;
1046  patro->value    = value;
1047  patro->op       = op;
1048
1049  *list = patro;
1050
1051  return;
1052  }  /* END add_atropl() */
1053
1054
1055
1056
1057/* display when a normal "qstat" is executed */
1058
1059void display_statjob(
1060
1061  struct batch_status *status,    /* I (data) */
1062  int                  prtheader, /* I (boolean) */
1063  int                  full)      /* I (boolean) */
1064
1065  {
1066
1067  struct batch_status *p;
1068
1069  struct attrl *a;
1070  int l;
1071  char *c;
1072  char *jid;
1073  char *name;
1074  char *owner;
1075  char *timeu;
1076  char *state;
1077  char *location;
1078  char format[80];
1079  char long_name[17];
1080  time_t epoch;
1081
1082  mxml_t *DE;
1083  mxml_t *JE;
1084  mxml_t *AE;
1085  mxml_t *RE1;
1086  mxml_t *JI;
1087
1088  /* XML only support for full output */
1089
1090  if (DisplayXML == TRUE)
1091    full = 1;
1092
1093  if (!full)
1094    {
1095    sprintf(format, "%%-%ds %%-%ds %%-%ds %%%ds %%%ds %%-%ds\n",
1096            PBS_MAXSEQNUM + PBS_MAXJOBARRAYLEN + 11,
1097            PBS_MINNAMELEN,
1098            OWNERL,
1099            TIMEUL,
1100            STATEL,
1101            LOCL);
1102
1103    if (prtheader)
1104      {
1105      /* display summary header TODO - the sizes of these fields should be determined from
1106         #defines in pbs_ifl.h */
1107      /*
1108      printf("Job id                    Name             User            Time Use S Queue\n");
1109      printf("------------------------- ---------------- --------------- -------- - -----\n");
1110      */
1111      printf("Job id                     Name                                     User            Time Use S Queue\n");
1112      printf("-------------------------- ---------------------------------------- --------------- -------- - ------------\n");
1113      }
1114    }    /* END if (!full) */
1115
1116  if (DisplayXML == TRUE)
1117    {
1118    /* create parent */
1119
1120    DE = NULL;
1121
1122    MXMLCreateE(&DE, "Data");
1123    }
1124
1125  for (p = status;p != NULL;p = p->next)
1126    {
1127    jid = NULL;
1128    name = NULL;
1129    owner = NULL;
1130    timeu = NULL;
1131    state = NULL;
1132    location = NULL;
1133
1134    if (full)
1135      {
1136      if (DisplayXML == TRUE)
1137        {
1138        JE = NULL;
1139
1140        MXMLCreateE(&JE, "Job");
1141
1142        MXMLAddE(DE, JE);
1143
1144        JI = NULL;
1145
1146        MXMLCreateE(&JI, "Job_Id");
1147
1148        MXMLSetVal(JI, p->name,mdfString);
1149
1150        MXMLAddE(JE, JI);
1151        }
1152      else
1153        {
1154        printf("Job Id: %s\n",
1155               p->name);
1156        }
1157
1158      a = p->attribs;
1159
1160      RE1 = NULL;
1161
1162      while (a != NULL)
1163        {
1164        if (a->name != NULL)
1165          {
1166          if (DisplayXML == TRUE)
1167            {
1168            /* lookup a->name -> XML attr name */
1169
1170            AE = NULL;
1171
1172            if (a->resource != NULL)
1173              {
1174              if (RE1 == NULL)
1175                {
1176                MXMLCreateE(&RE1, a->name);
1177                MXMLAddE(JE, RE1);
1178                }
1179
1180              MXMLCreateE(&AE, a->resource);
1181
1182              MXMLSetVal(AE, a->value, mdfString);
1183              MXMLAddE(RE1, AE);
1184              }
1185            else
1186              {
1187              RE1 = NULL;
1188              MXMLCreateE(&AE, a->name);
1189              MXMLSetVal(AE, a->value, mdfString);
1190              MXMLAddE(JE, AE);
1191              }
1192            }
1193          else
1194            {
1195            if (!strcmp(a->name, ATTR_ctime) ||
1196                !strcmp(a->name, ATTR_etime) ||
1197                !strcmp(a->name, ATTR_mtime) ||
1198                !strcmp(a->name, ATTR_qtime) ||
1199                !strcmp(a->name, ATTR_start_time) ||
1200                !strcmp(a->name, ATTR_comp_time) ||
1201                !strcmp(a->name, ATTR_checkpoint_time) ||
1202                !strcmp(a->name, ATTR_a))
1203              {
1204              epoch = (time_t)atoi(a->value);
1205
1206              prt_attr(a->name, a->resource, ctime(&epoch));
1207              }
1208            else
1209              {
1210              prt_attr(a->name, a->resource, a->value);
1211
1212              printf("\n");
1213              }
1214            }
1215          }
1216
1217        a = a->next;
1218        }
1219      }   /* END if (full) */
1220    else
1221      {
1222      /* display summary data */
1223
1224      if (p->name != NULL)
1225        {
1226        c = p->name;
1227
1228        while ((*c != '.') && (*c != '\0'))
1229          c++;
1230
1231        if (alias_opt == TRUE)
1232          {
1233          /* show the alias as well as the first part of the server name */
1234          if (*c == '.')
1235            {
1236            c++;
1237
1238            while((*c != '.') && (*c != '\0'))
1239              c++;
1240            }
1241          }
1242
1243        if (alias_opt == TRUE)
1244          {
1245          /* show the alias as well as the first part of the server name */
1246          if (*c == '.')
1247            {
1248            c++;
1249
1250            while((*c != '.') && (*c != '\0'))
1251              c++;
1252            }
1253          }
1254
1255        c++;    /* List the first part of the server name, too. */
1256
1257        while ((*c != '.') && (*c != '\0'))
1258          c++;
1259
1260        *c = '\0';
1261
1262        l = strlen(p->name);
1263
1264        if (l > (PBS_MAXSEQNUM + PBS_MAXJOBARRAYLEN + 8))
1265          {
1266          /* truncate job name */
1267
1268          c = p->name + PBS_MAXSEQNUM + PBS_MAXJOBARRAYLEN + 14;
1269
1270          *c = '\0';
1271          }
1272
1273        jid = p->name;
1274        }
1275
1276      a = p->attribs;
1277
1278      while (a != NULL)
1279        {
1280        if (a->name != NULL)
1281          {
1282          if (strcmp(a->name, ATTR_name) == 0)
1283            {
1284            l = strlen(a->value);
1285
1286            /* truncate AName */
1287
1288            if (l > PBS_NAMELEN)
1289              {
1290              l = l - PBS_NAMELEN + 3;
1291
1292              c = a->value + l;
1293
1294              while ((*c != '/') && (*c != '\0'))
1295                c++;
1296
1297              if (*c == '\0')
1298                c = a->value + l;
1299
1300              strcpy(long_name, "...");
1301
1302              strcat(long_name, c);
1303
1304              c = long_name;
1305              }
1306            else
1307              {
1308              c = a->value;
1309              }
1310
1311            name = c;
1312            }
1313          else if (!strcmp(a->name, ATTR_owner))
1314            {
1315            c = a->value;
1316
1317            while ((*c != '@') && (*c != '\0'))
1318              c++;
1319
1320            *c = '\0';
1321
1322            l = strlen(a->value);
1323
1324            if (l > OWNERL)
1325              {
1326              c = a->value + OWNERL;
1327
1328              *c = '\0';
1329              }
1330
1331            owner = a->value;
1332            }
1333          else if (!strcmp(a->name, ATTR_used))
1334            {
1335            if (!strcmp(a->resource, "cput"))
1336              {
1337              l = strlen(a->value);
1338
1339              if (l > TIMEUL)
1340                {
1341                c = a->value + TIMEUL;
1342
1343                *c = '\0';
1344                }
1345
1346              timeu = a->value;
1347              }
1348            }
1349          else if (!strcmp(a->name, ATTR_state))
1350            {
1351            l = strlen(a->value);
1352
1353            if (l > STATEL)
1354              {
1355              c = a->value + STATEL;
1356
1357              *c = '\0';
1358              }
1359
1360            state = a->value;
1361            }
1362          else if (!strcmp(a->name, ATTR_queue))
1363            {
1364            c = a->value;
1365
1366            while ((*c != '@') && (*c != '\0'))
1367              c++;
1368
1369            *c = '\0';
1370
1371            l = strlen(a->value);
1372
1373            if (l > LOCL)
1374              {
1375              c = a->value + LOCL;
1376
1377              *c = '\0';
1378              }
1379
1380            location = a->value;
1381            }
1382          }
1383
1384        a = a->next;
1385        }
1386
1387      if (timeu == NULL)
1388        timeu = "0";
1389
1390      /* display summary data */
1391
1392      printf(format,
1393             jid,
1394             name,
1395             owner,
1396             timeu,
1397             state,
1398             location);
1399      }  /* END else (full) */
1400
1401    if (DisplayXML != TRUE)
1402      {
1403      if (full)
1404        printf("\n");
1405      }
1406    }  /* END for (p = status) */
1407
1408  if (DisplayXML == TRUE)
1409    {
1410    char *tmpBuf = NULL, *tail = NULL;
1411    int  bufsize;
1412
1413    MXMLToXString(DE, &tmpBuf, &bufsize, INT_MAX, &tail, TRUE);
1414
1415    MXMLDestroyE(&DE);
1416
1417    fprintf(stdout, "%s\n",
1418            tmpBuf);
1419    }
1420
1421  return;
1422  }  /* END display_statjob() */
1423
1424
1425
1426#define MINNUML    3
1427#define MAXNUML    5
1428#define TYPEL     10
1429
1430void display_statque(
1431
1432  struct batch_status *status,
1433  int                  prtheader,
1434  int                  full)
1435
1436  {
1437
1438  struct batch_status *p;
1439
1440  struct attrl *a = NULL;
1441  int l;
1442  char *c;
1443  char *name;
1444  char *max;
1445  char *tot;
1446  char ena[MAXNUML + 1];
1447  char str[MAXNUML + 1];
1448  char que[MAXNUML + 1];
1449  char run[MAXNUML + 1];
1450  char hld[MAXNUML + 1];
1451  char wat[MAXNUML + 1];
1452  char trn[MAXNUML + 1];
1453  char ext[MAXNUML + 1];
1454  char *type;
1455  char format[80];
1456
1457  int  NUML = 5;
1458
1459
1460  sprintf(format, "%%-%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%-%ds\n",
1461          PBS_MINNAMELEN,
1462          NUML,
1463          NUML,
1464          NUML,
1465          NUML,
1466          NUML,
1467          NUML,
1468          NUML,
1469          NUML,
1470          NUML,
1471          NUML,
1472          TYPEL);
1473
1474  if (!full && prtheader)
1475    {
1476    printf(format, "Queue", "Max", "Tot", "Ena", "Str", "Que", "Run", "Hld", "Wat", "Trn", "Ext", "T");
1477    printf(format, "----------------", "---", "---", "---", "---", "---", "---", "---", "---", "---", "---", "-");
1478    }
1479
1480  p = status;
1481
1482  while (p != NULL)
1483    {
1484    name = NULL;
1485    max = "0";
1486    tot = "0";
1487    strcpy(ena, "no");
1488    strcpy(str, "no");
1489    strcpy(que, "0");
1490    strcpy(run, "0");
1491    strcpy(hld, "0");
1492    strcpy(wat, "0");
1493    strcpy(trn, "0");
1494    strcpy(ext, "0");
1495    type = "not defined";
1496
1497    if (full)
1498      {
1499      printf("Queue: %s\n",
1500             p->name);
1501
1502      a = p->attribs;
1503
1504      while (a != NULL)
1505        {
1506        if (a->name != NULL)
1507          {
1508          prt_attr(a->name, a->resource, a->value);
1509
1510          printf("\n");
1511          }
1512
1513        a = a->next;
1514        }
1515      }
1516    else
1517      {
1518      if (p->name != NULL)
1519        {
1520        l = strlen(p->name);
1521
1522        if (l > PBS_NAMELEN)
1523          {
1524          c = a->name + PBS_NAMELEN;
1525
1526          *c = '\0';
1527          }
1528
1529        name = p->name;
1530        }
1531
1532      a = p->attribs;
1533
1534      while (a != NULL)
1535        {
1536        if (a->name != NULL)
1537          {
1538          if (strcmp(a->name, ATTR_maxrun) == 0)
1539            {
1540            l = strlen(a->value);
1541
1542            if (l > NUML)
1543              {
1544              c = a->value + NUML;
1545
1546              *c = '\0';
1547              }
1548
1549            max = a->value;
1550            }
1551          else if (strcmp(a->name, ATTR_total) == 0)
1552            {
1553            l = strlen(a->value);
1554
1555            if (l > NUML)
1556              {
1557              c = a->value + NUML;
1558
1559              *c = '\0';
1560              }
1561
1562            tot = a->value;
1563            }
1564          else if (strcmp(a->name, ATTR_enable) == 0)
1565            {
1566            if (istrue(a->value))
1567              strcpy(ena, "yes");
1568            else
1569              strcpy(ena, "no");
1570            }
1571          else if (strcmp(a->name, ATTR_start) == 0)
1572            {
1573            if (istrue(a->value))
1574              strcpy(str, "yes");
1575            else
1576              strcpy(str, "no");
1577            }
1578          else if (strcmp(a->name, ATTR_count) == 0)
1579            {
1580            states(a->value, que, run, hld, wat, trn, ext, NUML);
1581            }
1582          else if (strcmp(a->name, ATTR_qtype) == 0)
1583            {
1584            type = a->value;
1585
1586            *(type + 1) = '\0';
1587            }
1588          }
1589
1590        a = a->next;
1591        }
1592
1593      printf(format,
1594
1595             name,
1596             max,
1597             tot,
1598             ena,
1599             str,
1600             que,
1601             run,
1602             hld,
1603             wat,
1604             trn,
1605             ext,
1606             type);
1607      }
1608
1609    if (full)
1610      printf("\n");
1611
1612    p = p->next;
1613    }
1614
1615  return;
1616  }
1617
1618
1619
1620#define STATUSL 10
1621
1622void display_statserver(
1623
1624  struct batch_status *status,
1625  int                  prtheader,
1626  int                  full)
1627
1628  {
1629
1630  struct batch_status *p;
1631
1632  struct attrl *a;
1633  int l;
1634  char *c;
1635  char *name;
1636  char *max;
1637  char *tot;
1638  char que[MAXNUML + 1];
1639  char run[MAXNUML + 1];
1640  char hld[MAXNUML + 1];
1641  char wat[MAXNUML + 1];
1642  char trn[MAXNUML + 1];
1643  char ext[MAXNUML + 1];
1644  char *stats;
1645  char format[80];
1646
1647  int  NUML;
1648
1649  NUML = MAXNUML;
1650
1651  sprintf(format, "%%-%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%-%ds\n",
1652          PBS_MINNAMELEN,
1653          NUML,
1654          NUML,
1655          NUML,
1656          NUML,
1657          NUML,
1658          NUML,
1659          NUML,
1660          NUML,
1661          STATUSL);
1662
1663  if (!full && prtheader)
1664    {
1665    printf(format, "Server", "Max", "Tot", "Que", "Run", "Hld", "Wat", "Trn", "Ext", "Status");
1666    printf(format, "----------------", "---", "---", "---", "---", "---", "---", "---", "---", "----------");
1667    }
1668
1669  p = status;
1670
1671  while (p != NULL)
1672    {
1673    name = NULL;
1674    max = "0";
1675    tot = "0";
1676    strcpy(que, "0");
1677    strcpy(run, "0");
1678    strcpy(hld, "0");
1679    strcpy(wat, "0");
1680    strcpy(trn, "0");
1681    strcpy(ext, "0");
1682    stats = "";
1683
1684    if (full)
1685      {
1686      printf("Server: %s\n", p->name);
1687      a = p->attribs;
1688
1689      while (a != NULL)
1690        {
1691        if (a->name != NULL)
1692          {
1693          prt_attr(a->name, a->resource, a->value);
1694          printf("\n");
1695          }
1696
1697        a = a->next;
1698        }
1699      }
1700    else
1701      {
1702      if (p->name != NULL)
1703        {
1704        l = strlen(p->name);
1705
1706        if (l > PBS_NAMELEN)
1707          {
1708          c = p->name + PBS_NAMELEN;
1709          *c = '\0';
1710          }
1711
1712        name = p->name;
1713        }
1714
1715      a = p->attribs;
1716
1717      while (a != NULL)
1718        {
1719        if (a->name != NULL)
1720          {
1721          if (strcmp(a->name, ATTR_maxrun) == 0)
1722            {
1723            l = strlen(a->value);
1724
1725            if (l > NUML)
1726              {
1727              c = a->value + NUML;
1728              *c = '\0';
1729              }
1730
1731            max = a->value;
1732            }
1733          else if (strcmp(a->name, ATTR_total) == 0)
1734            {
1735            l = strlen(a->value);
1736
1737            if (l > NUML)
1738              {
1739              c = a->value + NUML;
1740              *c = '\0';
1741              }
1742
1743            tot = a->value;
1744            }
1745          else if (strcmp(a->name, ATTR_count) == 0)
1746            {
1747            states(a->value, que, run, hld, wat, trn, ext, NUML);
1748            }
1749          else if (strcmp(a->name, ATTR_status) == 0)
1750            {
1751            l = strlen(a->value);
1752
1753            if (l > STATUSL)
1754              {
1755              c = a->value + STATUSL;
1756              *c = '\0';
1757              }
1758
1759            stats = a->value;
1760            }
1761          }
1762
1763        a = a->next;
1764        }
1765
1766      printf(format, name, max, tot, que, run, hld, wat, trn, ext, stats);
1767      }
1768
1769    if (full) printf("\n");
1770
1771    p = p->next;
1772    }
1773
1774  return;
1775  }  /* END display_statserver() */
1776
1777
1778
1779
1780
1781#if TCL_QSTAT
1782#define ARGNUM 1024
1783
1784char *attrlist(
1785
1786  struct attrl *ap)
1787
1788  {
1789  char nameres[256];
1790  char *argv[ARGNUM];
1791  char *ret;
1792  int i, num = 0;
1793
1794  while (ap)
1795    {
1796    char *twol[2];
1797
1798    if (ap->resource != NULL)
1799      {
1800      sprintf(nameres, "%s%s%s",
1801              ap->name,
1802              TCL_ATRSEP,
1803              ap->resource);
1804
1805      twol[0] = nameres;
1806      }
1807    else
1808      {
1809      twol[0] = ap->name;
1810      }
1811
1812    twol[1] = ap->value;
1813
1814    argv[num++] = Tcl_Merge(2, (const char **)twol);
1815
1816    if (num == ARGNUM)
1817      break;
1818
1819    ap = ap->next;
1820    }
1821
1822  ret = Tcl_Merge(num, (const char **)argv);
1823
1824  for (i = 0;i < num;i++)
1825    free(argv[i]);
1826
1827  return(ret);
1828  }
1829
1830
1831
1832
1833
1834Tcl_Interp *interp = NULL;
1835char  script[200];
1836char  flags[] = "flags";
1837char  ops[] = "operands";
1838char  error[] = "error";
1839
1840void
1841tcl_init(void)
1842  {
1843
1844  struct passwd *pw;
1845  uid_t  uid;
1846
1847  struct  stat    sb;
1848
1849  uid = getuid();
1850  pw = getpwuid(uid);
1851
1852  if (pw == NULL)
1853    return;
1854
1855  sprintf(script, "%s/.qstatrc", pw->pw_dir);
1856
1857  if (stat(script, &sb) == -1)
1858    {
1859    strcpy(script, QSTATRC_PATH);
1860
1861    if (stat(script, &sb) == -1)
1862      return;
1863    }
1864
1865  interp = Tcl_CreateInterp();
1866
1867  if (Tcl_Init(interp) == TCL_ERROR)
1868    {
1869    fprintf(stderr, "Tcl_Init error: %s",
1870            interp->result);
1871    }
1872
1873#if TCLX
1874#if TCL_MINOR_VERSION < 5  && TCL_MAJOR_VERSION < 8
1875  if (TclX_Init(interp) == TCL_ERROR)
1876    {
1877#else
1878
1879  if (Tclx_Init(interp) == TCL_ERROR)
1880    {
1881#endif
1882    fprintf(stderr, "Tclx_Init error: %s",
1883            interp->result);
1884    }
1885
1886#endif /* TCLX */
1887  return;
1888  }
1889
1890void
1891
1892tcl_addarg(name, arg)
1893char *name;
1894char *arg;
1895  {
1896  if (interp == NULL)
1897    return;
1898
1899  if (arg == NULL || *arg == '\0')
1900    return;
1901
1902  Tcl_SetVar(interp, name, arg,
1903             TCL_GLOBAL_ONLY |
1904             TCL_LIST_ELEMENT |
1905             TCL_APPEND_VALUE);
1906  }
1907
1908
1909
1910
1911
1912int tcl_stat(
1913
1914  char                *type,
1915  struct batch_status *bs,
1916  int                  f_opt)
1917
1918  {
1919
1920  struct batch_status *bp;
1921  char *twol[2];
1922  char *argv[ARGNUM];
1923  int i, num = 0;
1924  char *result;
1925
1926  if (interp == NULL)
1927    {
1928    return(1);
1929    }
1930
1931  if (f_opt == 0)
1932    {
1933    return(1);
1934    }
1935
1936  twol[0] = type;
1937
1938  for (bp = bs;bp != NULL;bp = bp->next)
1939    {
1940    char *threel[3];
1941
1942    threel[0] = bp->name;
1943    threel[1] = attrlist(bp->attribs);
1944    threel[2] = bp->text;
1945
1946    argv[num++] = Tcl_Merge(3, (const char **)threel);
1947
1948    free(threel[1]); /* malloc'ed in attrlist() */
1949
1950    if (num == ARGNUM)
1951      break;
1952    }
1953
1954  twol[1] = Tcl_Merge(num, (const char **)argv);
1955
1956  for (i = 0;i < num;i++)
1957    free(argv[i]);
1958
1959  result = Tcl_Merge(2, (const char **)twol);
1960
1961  Tcl_SetVar(
1962    interp,
1963    "objects",
1964    result,
1965    TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
1966
1967  free(twol[1]);
1968
1969  free(result);
1970
1971  return(0);
1972  }
1973
1974
1975
1976
1977void tcl_run(
1978
1979  int f_opt)
1980
1981  {
1982  if (interp == NULL)
1983    {
1984    return;
1985    }
1986
1987  if (f_opt && Tcl_EvalFile(interp, script) != TCL_OK)
1988    {
1989    char *trace;
1990
1991    trace = (char *)Tcl_GetVar(interp, "errorInfo", 0);
1992
1993    if (trace == NULL)
1994      trace = interp->result;
1995
1996    fprintf(stderr, "%s: TCL error @ line %d: %s\n",
1997            script, interp->errorLine, trace);
1998    }
1999
2000  Tcl_DeleteInterp(interp);
2001
2002  return;
2003  }  /* END tcl_run() */
2004
2005
2006
2007#else
2008#define tcl_init()
2009#define tcl_addarg(name, arg)
2010#define tcl_stat(type, bs, f_opt) 1
2011#define tcl_run(f_opt)
2012#endif /* TCL_QSTAT */
2013
2014
2015
2016
2017
2018
2019/* connects to server side routine pbs_statjob() in lib/Libifl/pbs_statjob.c */
2020/*  routes to req_stat_job() in server/req_stat.c (PBS_BATCH_StatusJob) */
2021
2022int main(
2023
2024  int    argc,  /* I */
2025  char **argv)  /* I */
2026
2027  {
2028  int c;
2029  int errflg = 0;
2030  int any_failed = 0;
2031  extern char *optarg;
2032  char *conflict = "qstat: conflicting options.\n";
2033#if (TCL_QSTAT == 0)
2034  char *pc;
2035#endif
2036  int located = FALSE;
2037
2038  char option[3];
2039
2040  char job_id[PBS_MAXCLTJOBID];
2041
2042  char job_id_out[PBS_MAXCLTJOBID];
2043  char server_out[MAXSERVERNAME];
2044  char server_old[MAXSERVERNAME] = "";
2045  char rmt_server[MAXSERVERNAME];
2046  char destination[PBS_MAXDEST + 1];
2047  char *def_server;
2048
2049  char *queue_name_out;
2050  char *server_name_out;
2051
2052  char *ExtendOpt = NULL;
2053
2054  char operand[PBS_MAXCLTJOBID + 1];
2055  int alt_opt;
2056  int f_opt, B_opt, Q_opt, t_opt, E_opt;
2057  int p_header = TRUE;
2058  int stat_single_job = 0;
2059  enum { JOBS, QUEUES, SERVERS } mode;
2060
2061  struct batch_status *p_status;
2062
2063  struct batch_status *p_server;
2064
2065  struct attropl *p_atropl = 0;
2066  char *errmsg;
2067  int exec_only = 0;
2068
2069#ifndef mbool
2070#define mbool char
2071#endif /* !mbool */
2072
2073#ifndef TRUE
2074#define TRUE 1
2075#endif /* !TRUE */
2076
2077#ifndef FALSE
2078#define FALSE 0
2079#endif /* !FALSE */
2080
2081#if !defined(PBS_NO_POSIX_VIOLATION)
2082#define GETOPT_ARGS "aeE:filn1qrstu:xGMQRBW:-:"
2083#else
2084#define GETOPT_ARGS "flQBW:"
2085#endif /* PBS_NO_POSIX_VIOLATION */
2086
2087  mode = JOBS; /* default */
2088  alt_opt = 0;
2089  f_opt = 0;
2090  B_opt = 0;
2091  Q_opt = 0;
2092  t_opt = 0;
2093  E_opt = 0;
2094
2095  tcl_init();
2096  tcl_addarg(flags, argv[0]);
2097
2098  option[0] = '-';
2099  option[2] = '\0';
2100
2101  if (getenv("PBS_QSTAT_EXECONLY") != NULL)
2102    exec_only = 1;
2103   
2104  while ((c = getopt(argc, argv, GETOPT_ARGS)) != EOF)
2105    {
2106    option[1] = (char)c;
2107
2108    tcl_addarg(flags, option);
2109    tcl_addarg(flags, optarg);
2110
2111    switch (c)
2112      {
2113#if !defined(PBS_NO_POSIX_VIOLATION)
2114
2115      case '1':
2116
2117        alt_opt |= ALT_DISPLAY_o;
2118
2119        break;
2120
2121      case 'a':
2122
2123        alt_opt |= ALT_DISPLAY_a;
2124
2125        break;
2126
2127      case 'e':
2128
2129        exec_only = 1;
2130
2131        break;
2132
2133      case 'E':
2134
2135        if (optarg != NULL)
2136          {
2137          ExtendOpt = strdup(optarg);
2138          E_opt = TRUE;
2139          }
2140        break;
2141
2142      case 'i':
2143
2144        alt_opt |= ALT_DISPLAY_i;
2145
2146        add_atropl(&p_atropl, ATTR_state, NULL, "EHQTW", EQ);
2147
2148        break;
2149
2150      case 'n':
2151
2152        alt_opt |= ALT_DISPLAY_n;
2153
2154        break;
2155
2156      case 'q':
2157
2158        alt_opt |= ALT_DISPLAY_q;
2159
2160        mode = QUEUES;
2161
2162        break;
2163
2164      case 'r':
2165
2166        alt_opt |= ALT_DISPLAY_r;
2167
2168        add_atropl(&p_atropl, ATTR_state, NULL, "RS", EQ);
2169
2170        break;
2171
2172      case 's':
2173
2174        alt_opt |= ALT_DISPLAY_s;
2175
2176        break;
2177      case 't':
2178     
2179        t_opt = 1;
2180       
2181        break;
2182
2183      case 'u':
2184
2185        alt_opt |= ALT_DISPLAY_u;
2186
2187        add_atropl(&p_atropl, ATTR_u, NULL, optarg, EQ);
2188
2189        break;
2190
2191      case 'R':
2192
2193        alt_opt |= ALT_DISPLAY_R;
2194
2195        break;
2196
2197      case 'G':
2198
2199        alt_opt |= ALT_DISPLAY_G;
2200
2201        break;
2202
2203      case 'M':
2204
2205        alt_opt |= ALT_DISPLAY_Mw;
2206
2207        break;
2208
2209#endif /* PBS_NO_POSIX_VIOLATION */
2210
2211      case 'f':
2212
2213        if (alt_opt != 0)
2214          {
2215            fprintf(stderr, "%s", conflict);
2216
2217          errflg++;
2218          }
2219
2220        f_opt = 1;
2221
2222        break;
2223
2224      case 'x':
2225
2226        DisplayXML = TRUE;
2227
2228        break;
2229
2230      case 'B':
2231
2232        B_opt = 1;
2233
2234        mode = SERVERS;
2235
2236        if (Q_opt || alt_opt)
2237          {
2238            fprintf(stderr, "%s", conflict);
2239
2240          errflg++;
2241          }
2242
2243        break;
2244
2245      case 'l':
2246
2247        alias_opt = TRUE;
2248
2249        break;
2250
2251      case 'Q':
2252
2253        Q_opt = 1;
2254
2255        mode = QUEUES;
2256
2257        if (B_opt || alt_opt)
2258          {
2259            fprintf(stderr, "%s", conflict);
2260
2261          errflg++;
2262          }
2263
2264        break;
2265
2266      case '-':
2267
2268        /* handle '--' options */
2269
2270        if ((optarg != NULL) && !strcmp(optarg, "version"))
2271          {
2272          fprintf(stderr, "version: %s\n",
2273                  PACKAGE_VERSION);
2274
2275          exit(0);
2276          }
2277
2278        if ((optarg != NULL) && !strcmp(optarg, "about"))
2279          {
2280          TShowAbout();
2281
2282          exit(0);
2283          }
2284
2285        /* unexpected '--' option received */
2286
2287        errflg = 1;
2288
2289        break;
2290
2291      case 'W':
2292
2293#if (TCL_QSTAT == 0)
2294        pc = optarg;
2295
2296        while (*pc)
2297          {
2298          switch (*pc)
2299            {
2300
2301            case 'a':
2302
2303              alt_opt |= ALT_DISPLAY_a;
2304
2305              break;
2306
2307            case 'i':
2308              alt_opt |= ALT_DISPLAY_i;
2309              add_atropl(&p_atropl, ATTR_state, (char *)0, "EHQTW", EQ);
2310              break;
2311
2312            case 'r':
2313              alt_opt |= ALT_DISPLAY_r;
2314              add_atropl(&p_atropl, ATTR_state, (char *)0, "RS", EQ);
2315              break;
2316
2317            case 'u':
2318              /* note - u option is assumed to be last in  */
2319              /* string and all remaining is the name list */
2320              alt_opt |= ALT_DISPLAY_u;
2321
2322              while (*++pc == ' ');
2323
2324              add_atropl(&p_atropl, ATTR_u, (char *)0, pc, EQ);
2325
2326              pc = pc + strlen(pc) - 1; /* for the later incr */
2327
2328              break;
2329
2330            case 'n':
2331              alt_opt |= ALT_DISPLAY_n;
2332
2333              break;
2334
2335            case 's':
2336              alt_opt |= ALT_DISPLAY_s;
2337
2338              break;
2339
2340            case 'q':
2341              alt_opt |= ALT_DISPLAY_q;
2342
2343              mode = QUEUES;
2344
2345              break;
2346
2347            case 'R':
2348              alt_opt |= ALT_DISPLAY_R;
2349
2350              break;
2351
2352            case 'G':
2353              alt_opt |= ALT_DISPLAY_G;
2354
2355              break;
2356
2357            case 'M':
2358              alt_opt |= ALT_DISPLAY_Mw;
2359
2360              break;
2361
2362            case ' ':
2363              break;  /* ignore blanks */
2364
2365            default:
2366              errflg++;
2367            }
2368
2369          ++pc;
2370          }
2371
2372#endif /* (TCL_QSTAT == 0) */
2373        break;
2374
2375      case '?':
2376
2377      default:
2378
2379        /* unexpected argument */
2380
2381        errflg++;
2382
2383        break;
2384      }  /* END switch (c) */
2385    }    /* END while (c = getopt()) */
2386
2387#if !defined(PBS_NO_POSIX_VIOLATION)
2388
2389  /* certain combinations are not allowed */
2390
2391  c = alt_opt & (ALT_DISPLAY_a | ALT_DISPLAY_i | ALT_DISPLAY_r | ALT_DISPLAY_q);
2392
2393  if ((c != 0) &&
2394      (c != ALT_DISPLAY_a) &&
2395      (c != ALT_DISPLAY_i) &&
2396      (c != ALT_DISPLAY_r) &&
2397      (c != ALT_DISPLAY_q))
2398    {
2399      fprintf(stderr, "%s", conflict);
2400
2401    errflg++;
2402    }
2403
2404  c = alt_opt & (ALT_DISPLAY_Mw | ALT_DISPLAY_G);
2405
2406  if (c == (ALT_DISPLAY_Mw | ALT_DISPLAY_G))
2407    {
2408      fprintf(stderr, "%s", conflict);
2409
2410    errflg++;
2411    }
2412
2413  if ((alt_opt & ALT_DISPLAY_q) && (f_opt == 1))
2414    {
2415      fprintf(stderr, "%s", conflict);
2416
2417    errflg++;
2418    }
2419
2420  if ((alt_opt & ALT_DISPLAY_o) && !((alt_opt & ALT_DISPLAY_n) || (f_opt)))
2421    {
2422      fprintf(stderr, "%s", conflict);
2423
2424    errflg++;
2425    }
2426
2427  if (alt_opt & ALT_DISPLAY_o)
2428    {
2429    linesize = maxlinesize;
2430    alt_opt &= ~ALT_DISPLAY_o;
2431    }
2432
2433#endif /* PBS_NO_POSIX_VIOLATION */
2434
2435  if (errflg)
2436    {
2437    static char usage[] = "usage: \n\
2438                          qstat [-f [-1]] [-W site_specific] [-x] [ job_identifier... | destination... ]\n\
2439                          qstat [-a|-i|-r|-e] [-u user] [-n [-1]] [-s] [-t] [-G|-M] [-R] [job_id... | destination...]\n\
2440                          qstat -Q [-f [-1]] [-W site_specific] [ destination... ]\n\
2441                          qstat -q [-G|-M] [ destination... ]\n\
2442                          qstat -B [-f [-1]] [-W site_specific] [ server_name... ]\n\
2443                          qstat -t\n";
2444
2445    fprintf(stderr,"%s", usage);
2446
2447    exit(2);
2448    }
2449
2450  if (!t_opt && !E_opt && !exec_only)
2451    {
2452    ExtendOpt = summarize_arrays_extend_opt;
2453    }
2454
2455  def_server = pbs_default();
2456
2457  if (def_server == NULL)
2458    def_server = "";
2459
2460  if (optind >= argc)
2461    {
2462    /* If no arguments, then set defaults */
2463
2464    switch (mode)
2465      {
2466
2467      case JOBS:
2468
2469        server_out[0] = '@';
2470        strcpy(&server_out[1], def_server);
2471        tcl_addarg(ops, server_out);
2472
2473        job_id_out[0] = '\0';
2474        server_out[0] = '\0';
2475
2476        goto job_no_args;
2477
2478        /*NOTREACHED*/
2479
2480        break;
2481
2482      case QUEUES:
2483
2484        server_out[0] = '@';
2485        strcpy(&server_out[1], def_server);
2486
2487        tcl_addarg(ops, server_out);
2488
2489        queue_name_out = NULL;
2490
2491        server_out[0] = '\0';
2492
2493        goto que_no_args;
2494
2495        /*NOTREACHED*/
2496
2497        break;
2498
2499      case SERVERS:
2500
2501        tcl_addarg(ops, def_server);
2502
2503        server_out[0] = '\0';
2504
2505        goto svr_no_args;
2506
2507        /*NOTREACHED*/
2508
2509        break;
2510
2511      default:
2512
2513        /* NO-OP */
2514
2515        break;
2516      }
2517    }    /* END if (optind >= argc) */
2518
2519  for (;optind < argc;optind++)
2520    {
2521    int connect;
2522    int ret;
2523
2524    located = FALSE;
2525
2526    strcpy(operand, argv[optind]);
2527
2528    tcl_addarg(ops, operand);
2529
2530    switch (mode)
2531      {
2532
2533      case JOBS:      /* get status of batch jobs */
2534
2535        if (isjobid(operand))
2536          {
2537          /* must be a job-id */
2538
2539          stat_single_job = 1;
2540
2541          strcpy(job_id, operand);
2542
2543          if (get_server(job_id, job_id_out, server_out))
2544            {
2545            fprintf(stderr, "qstat: illegally formed job identifier: %s\n",
2546                    job_id);
2547
2548            ret = tcl_stat(error, NULL, f_opt);
2549
2550            any_failed = 1;
2551
2552            break;
2553            }
2554          }
2555        else
2556          {
2557          /* must be a destination-id */
2558
2559          stat_single_job = 0;
2560
2561          strcpy(destination, operand);
2562
2563          if (parse_destination_id(
2564                destination,
2565                &queue_name_out,
2566                &server_name_out))
2567            {
2568            fprintf(stderr, "qstat: illegally formed destination: %s\n",
2569                    destination);
2570
2571            ret = tcl_stat(error, NULL, f_opt);
2572
2573            any_failed = 1;
2574
2575            break;
2576            }
2577
2578          if (notNULL(server_name_out))
2579            {
2580            strcpy(server_out, server_name_out);
2581            }
2582          else
2583            {
2584            server_out[0] = '\0';
2585            }
2586
2587          strcpy(job_id_out, queue_name_out);
2588
2589          if (*queue_name_out != '\0')
2590            {
2591            add_atropl(&p_atropl, ATTR_q, NULL, queue_name_out, EQ);
2592            }
2593          }    /* END else */
2594
2595job_no_args:
2596
2597        connect = cnt2server(server_out);
2598
2599        if (connect <= 0)
2600          {
2601          fprintf(stderr, "qstat: cannot connect to server %s (errno=%d) %s\n",
2602                  pbs_server,
2603                  pbs_errno,
2604                  pbs_strerror(pbs_errno));
2605
2606          ret = tcl_stat(error, NULL, f_opt);
2607
2608          any_failed = connect;
2609
2610          break;
2611          }
2612
2613        if ((alt_opt != 0) && (strcmp(pbs_server, server_old) != 0))
2614          {
2615          /* changing to a different server */
2616
2617          p_server = pbs_statserver(connect, NULL, NULL);
2618
2619          strcpy(server_old, pbs_server);
2620          }
2621        else
2622          {
2623          p_server = 0;
2624          }
2625
2626        if ((stat_single_job == 1) || (p_atropl == 0))
2627          {
2628          p_status = pbs_statjob(
2629                       connect,
2630                       job_id_out,
2631                       NULL,
2632                       exec_only ? EXECQUEONLY : ExtendOpt);
2633          }
2634        else
2635          {
2636          if (t_opt)
2637            {
2638            p_status = pbs_selstat(connect, p_atropl, exec_only ? EXECQUEONLY : NULL);
2639            }
2640          else
2641            {
2642            p_status = pbs_selstat(connect, p_atropl, exec_only ? EXECQUEONLY : summarize_arrays_extend_opt);
2643            }
2644          }
2645
2646        if (p_status == NULL)
2647          {
2648          if ((pbs_errno == PBSE_UNKJOBID) && !located)
2649            {
2650            located = TRUE;
2651
2652            if (locate_job(job_id_out, server_out, rmt_server))
2653              {
2654              pbs_disconnect(connect);
2655
2656              strcpy(server_out, rmt_server);
2657
2658              goto job_no_args;
2659              }
2660
2661            ret = tcl_stat("job", NULL, f_opt);
2662
2663            prt_job_err("qstat", connect, job_id_out);
2664
2665            any_failed = pbs_errno;
2666            }
2667          else
2668            {
2669            ret = tcl_stat("job", NULL, f_opt);
2670
2671            if (pbs_errno != PBSE_NONE)
2672              {
2673              prt_job_err("qstat", connect, job_id_out);
2674
2675              any_failed = pbs_errno;
2676              }
2677            }
2678          }
2679        else
2680          {
2681          if (alt_opt != 0)
2682            {
2683            altdsp_statjob(p_status, p_server, alt_opt);
2684            }
2685          else if ((f_opt == 0) || tcl_stat("job", p_status, f_opt))
2686            {
2687            display_statjob(p_status, p_header, f_opt);
2688            }
2689
2690          p_header = FALSE;
2691
2692          pbs_statfree(p_status);
2693          }
2694
2695        pbs_disconnect(connect);
2696
2697        break;
2698
2699      case QUEUES:        /* get status of batch queues */
2700
2701        strcpy(destination, operand);
2702
2703        if (parse_destination_id(destination,
2704                                 &queue_name_out,
2705                                 &server_name_out))
2706          {
2707          fprintf(stderr, "qstat: illegal 'destination' value\n");
2708          ret = tcl_stat(error, NULL, f_opt);
2709          any_failed = 1;
2710          break;
2711          }
2712        else
2713          {
2714          if (notNULL(server_name_out))
2715            {
2716            strcpy(server_out, server_name_out);
2717            }
2718          else
2719            server_out[0] = '\0';
2720          }
2721
2722que_no_args:
2723
2724        connect = cnt2server(server_out);
2725
2726        if (connect <= 0)
2727          {
2728          fprintf(stderr, "qstat: cannot connect to server %s (errno=%d) %s\n",
2729                  pbs_server, pbs_errno, pbs_strerror(pbs_errno));
2730          ret = tcl_stat(error, NULL, f_opt);
2731          any_failed = connect;
2732          break;
2733          }
2734
2735        p_status = pbs_statque(connect, queue_name_out, NULL, NULL);
2736
2737        if (p_status == NULL)
2738          {
2739          if (pbs_errno)
2740            {
2741            errmsg = pbs_geterrmsg(connect);
2742
2743            if (errmsg != NULL)
2744              {
2745              fprintf(stderr, "qstat: %s ", errmsg);
2746              }
2747            else
2748              fprintf(stderr, "qstat: Error (%d - %s) getting status of queue ",
2749                      pbs_errno, pbs_strerror(pbs_errno));
2750
2751            fprintf(stderr, "%s\n", queue_name_out);
2752
2753            ret = tcl_stat(error, NULL, f_opt);
2754
2755            any_failed = pbs_errno;
2756            }
2757          }
2758        else
2759          {
2760          if (alt_opt & ALT_DISPLAY_q)
2761            {
2762            altdsp_statque(pbs_server, p_status, alt_opt);
2763            }
2764          else if (tcl_stat("queue", p_status, f_opt))
2765            {
2766            display_statque(p_status, p_header, f_opt);
2767            }
2768
2769          p_header = FALSE;
2770
2771          pbs_statfree(p_status);
2772          }
2773
2774        pbs_disconnect(connect);
2775
2776        break;
2777
2778      case SERVERS:           /* get status of batch servers */
2779        strcpy(server_out, operand);
2780
2781svr_no_args:
2782        connect = cnt2server(server_out);
2783
2784        if (connect <= 0)
2785          {
2786          fprintf(stderr, "qstat: cannot connect to server %s (errno=%d) %s\n",
2787                  pbs_server, pbs_errno, pbs_strerror(pbs_errno));
2788          ret = tcl_stat(error, NULL, f_opt);
2789          any_failed = connect;
2790          break;
2791          }
2792
2793        p_status = pbs_statserver(connect, NULL, NULL);
2794
2795        if (p_status == NULL)
2796          {
2797          if (pbs_errno)
2798            {
2799            errmsg = pbs_geterrmsg(connect);
2800
2801            if (errmsg != NULL)
2802              {
2803              fprintf(stderr, "qstat: %s ", errmsg);
2804              }
2805            else
2806              fprintf(stderr, "qstat: Error (%d - %s) getting status of server ",
2807                      pbs_errno, pbs_strerror(pbs_errno));
2808
2809            fprintf(stderr, "%s\n", server_out);
2810
2811            ret = tcl_stat(error, NULL, f_opt);
2812
2813            any_failed = pbs_errno;
2814            }
2815          }
2816        else
2817          {
2818          if (tcl_stat("server", p_status, f_opt))
2819            display_statserver(p_status, p_header, f_opt);
2820
2821          p_header = FALSE;
2822
2823          pbs_statfree(p_status);
2824          }
2825
2826        pbs_disconnect(connect);
2827
2828        break;
2829      }    /* END switch (mode) */
2830    }      /* END for () */
2831
2832  tcl_run(f_opt);
2833
2834  exit(any_failed);
2835  }  /* END main() */