/* int last_error = 0; * * qstat - (PBS) show stats of batch jobs, queues, or servers * * Authors: * Terry Heidelberg * Livermore Computing * * Bruce Kelly * National Energy Research Supercomputer Center * * Lawrence Livermore National Laboratory * University of California */ #include /* the master config generated by configure */ #include #include #include #if TCL_QSTAT #include #include #if TCLX #include #endif #endif #include "cmds.h" #include "mcom.h" #include "utils.h" #include "libcmds.h" /* TShowAbout_exit */ #include "net_cache.h" #include "../lib/Libifl/lib_ifl.h" bool do_not_display_complete = false; static void states( char *string, /* I */ char *queued, /* O */ char *running, /* O */ char *held, /* O */ char *waiting, /* O */ char *transit, /* O */ char *exiting, /* O */ char *complete, /* O */ int len); /* I */ #if !defined(PBS_NO_POSIX_VIOLATION) /* defines for alternative display formats */ #define ALT_DISPLAY_a 1 /* -a option - show all jobs */ #define ALT_DISPLAY_i 2 /* -i option - show not running */ #define ALT_DISPLAY_r 4 /* -r option - show only running */ #define ALT_DISPLAY_u 8 /* -u option - list user's jobs */ #define ALT_DISPLAY_n 0x10 /* -n option - add node list */ #define ALT_DISPLAY_s 0x20 /* -s option - add scheduler comment */ #define ALT_DISPLAY_R 0x40 /* -R option - add SRFS info */ #define ALT_DISPLAY_q 0x80 /* -q option - alt queue display */ #define ALT_DISPLAY_Mb 0x100 /* show sizes in MB */ #define ALT_DISPLAY_Mw 0x200 /* -M option - show sizes in MW */ #define ALT_DISPLAY_G 0x400 /* -G option - show sizes in GB */ #define ALT_DISPLAY_o 0x800 /* -1 option - add node list on same line */ #endif /* not PBS_NO_POSIX_VIOLATION */ #define MAX_RETRIES 3 /* globals */ extern char *optarg; enum qstat_mode { JOBS, QUEUES, SERVERS } mode; mbool_t DisplayXML = FALSE; #define maxlinesize 65536 int linesize = 77; int alt_opt; int f_opt; int B_opt; int Q_opt; int t_opt; int E_opt; const char *ExtendOpt = NULL; struct attropl *p_atropl = 0; struct attrl *attrib = NULL; char user[MAXPATHLEN]; #if (TCL_QSTAT == 0) char *pc; #else char option[3]; #endif int exec_only = 0; const char *conflict_msg = "qstat: conflicting options.\n"; static const char *summarize_arrays_extend_opt = "summarize_arrays"; /* END globals */ #define DEFTASKSIZE 6 int tasksize = DEFTASKSIZE; int alias_opt = FALSE; bool isjobid( const char *string) { int i; int result; i = strspn(string, " "); /* locate first non-blank */ if (isdigit(string[i])) result = true; /* job_id */ else if (isalpha(string[i])) result = false; /* not a job_id */ else result = false; /* who knows - probably a syntax error */ return(result); } /* END isjobid() */ bool istrue( const char *string) /* I */ { if (!strcasecmp(string, "TRUE")) { return(true); } if (!strcmp(string, "1")) { return(true); } return(false); } /* END istrue() */ int time_to_string( char *time_string, int time_to_convert) { int seconds = 0; int total_minutes = 0; int minutes = 0; int hours = 0; int time_in_seconds = 0; time_in_seconds = time_to_convert; /* Get the number of seconds in the job */ seconds = time_in_seconds % 60; /* Calculate the total minutes and then get the minutes less than an hour */ total_minutes = time_in_seconds / 60; /* Calculate hours */ hours = total_minutes / 60; /* calculate minutes */ minutes = total_minutes % 60; sprintf(time_string, "%.2d:%.2d:%.2d", hours, minutes, seconds); return(PBSE_NONE); } int timestring_to_int( const char *timestring, int *req_walltime) { char *ptr_string; char *ptr; char *number; int hours; int minutes; int seconds; ptr_string = (char *)malloc(strlen(timestring)+1); if (ptr_string == NULL) return(PBSE_MEM_MALLOC); strcpy(ptr_string, timestring); number = ptr_string; ptr = strstr(ptr_string, ":"); if (ptr == NULL) { free(ptr_string); return (PBSE_BAD_PARAMETER); } *ptr = 0; ptr++; hours = atoi(number); hours = hours * 3600; number = ptr; ptr = strstr(ptr, ":"); if (ptr == NULL) { free(ptr_string); return (PBSE_BAD_PARAMETER); } *ptr = 0; ptr++; minutes = atoi(number); minutes = minutes * 60; number = ptr; if (number == NULL) { free(ptr_string); return(PBSE_BAD_PARAMETER); } seconds = atoi(number); *req_walltime = hours + minutes + seconds; free(ptr_string); return(PBSE_NONE); } static void states( char *string, /* I */ char *queued, /* O */ char *running, /* O */ char *held, /* O */ char *waiting, /* O */ char *transit, /* O */ char *exiting, /* O */ char *complete, /* O */ int len) /* I */ { char *c, *d, *f, *s, l; /* FORMAT: Queued:X Running:Y... */ c = string; while (isspace(*c) && *c != '\0') c++; while (*c != '\0') { s = c; while ((*c != ':')&&(*c != '\0')) c++; if(*c != '\0') { *c = '\0'; c++; } d = NULL; if (strcmp(s, "Queued") == 0) d = queued; else if (strcmp(s, "Running") == 0) d = running; else if (strcmp(s, "Held") == 0) d = held; else if (strcmp(s, "Waiting") == 0) d = waiting; else if (strcmp(s, "Transit") == 0) d = transit; else if (strcmp(s, "Exiting") == 0) d = exiting; else if (strcmp(s, "Complete") == 0) d = complete; if (d != NULL) { s = c; while ((*c != ' ') && (*c != '\0')) c++; l = *c; *c = '\0'; if (strlen(s) > (size_t)len) { f = s + len; *f = '\0'; } strcpy(d, s); if (l != '\0') c++; } } return; } /* END states() */ /* * print an attribute value string, formating to break a comma if possible */ void prt_attr( char *n, /* I name */ char *r, /* I resource (optional) */ char *v) /* I value */ { char *c; const char *comma = ","; int first = 1; int l; int start; start = strlen(n) + 7; /* 4 spaces + ' = ' is 7 */ printf(" %s", n); if (r != NULL) { start += strlen(r) + 1; printf(".%s", r); } printf(" = "); c = strtok(v, comma); while (c != NULL) { if ((l = strlen(c)) + start < linesize) { printf("%s", c); start += l; } else { if (!first) { printf("\n\t"); start = 9; } while (*c) { putchar(*c++); if (++start > linesize) { start = 8; printf("\n\t"); } } } if ((c = strtok(NULL, comma)) != NULL) { first = 0; putchar(','); } } return; } /* END prt_attr() */ /* * locate an attribute (attrl) by name (and resource) and return value * returns null if not found */ static char *findattrl( struct attrl *pattrl, char *name, char *resc) { while (pattrl != NULL) { if (!strcmp(name, pattrl->name)) { if (resc != NULL) { if (!strcmp(resc, pattrl->resource)) { return(pattrl->value); } } else { return(pattrl->value); } } pattrl = pattrl->next; } return(NULL); } #ifndef PBS_MINNAMELEN #define PBS_MINNAMELEN 16 /* min size for printf job jobs, queues, and servers */ #endif /* PBS_MINNAMELEN */ #ifndef PBS_NAMELEN #define PBS_NAMELEN 16 /* printf of jobs, queues, and servers */ #endif /* PBS_NAMELEN */ #define PBS_JOB_ID_LEN 22 #define OWNERL 15 /* printf of jobs */ #define TIMEUL 8 /* printf of jobs */ #define STATEL 1 /* printf of jobs */ #define LOCL 15 /* printf of jobs */ #define SIZEL 6 /* length of "SIZE" fields in printf */ /* * Format and display string of assigned nodes, (1) strip off domain name * if present and (2) break line at '+' sign. */ static void prt_nodes( const char *nodes) /* I */ { int i; const char *stp; char linebuf[65536]; if ((nodes == NULL) || (*nodes == '\0')) { /* FAILURE - node is invalid */ return; } i = 0; stp = nodes; while (*nodes != '\0') { if ((*stp == '.') || (*stp == '+') || (*stp == '\0')) { /* does node fit into line? */ if (i + stp - nodes < linesize) { while (nodes < stp) linebuf[i++] = *nodes++; } else { /* flush line and start next */ linebuf[i] = '\0'; printf(" %s\n", linebuf); i = 0; while (nodes < stp) linebuf[i++] = *nodes++; } /* strip off domain name to keep string short */ while ((*stp != '+') && (*stp != '\0')) stp++; nodes = stp++; } else { stp++; } } if (i != 0) { linebuf[i] = '\0'; printf(" %s\n", linebuf); } return; } /* END prt_nodes() */ /* * convert size from suffix string (nnnn[ kmgt][ bw]) to string of * k[bw] for neither -M or -G * mw for -M * gb for -G */ static char *cnv_size( char *value, int opt) { static int sift_factor[3][5] = { { -20, -10, 0, 10, 20 }, /* mb conversion */ { -23, -13, -3, 7, 17 }, /* mw conversion */ { -30, -20, -10, 0, 10 } }; /* gb conversion */ int in; int out; int sft; unsigned long nval; char *pc; const char *suffix; static char outbuf[25]; if (opt & ALT_DISPLAY_Mb) { out = 0; suffix = "mb"; } else if (opt & ALT_DISPLAY_Mw) { out = 1; suffix = "mw"; } else if (opt & ALT_DISPLAY_G) { out = 2; suffix = "gb"; } else { return (value); /* return unmodified */ } nval = strtol(value, &pc, 10); if (*pc == 'k') in = 1; else if (*pc == 'm') in = 2; else if (*pc == 'g') in = 3; else if (*pc == 't') in = 4; else in = 0; sft = sift_factor[out][in]; if ((*pc == 'w') || (*(pc + 1) == 'w')) nval = nval << 3; /* convert to bytes */ if (sft < 0) { nval = nval + ((1 << -sft) - 1); /* round up (ceiling) */ nval = nval >> -sft; } else { nval = nval << sft; } sprintf(outbuf, "%lu%s", nval, suffix); return(outbuf); } /* * Format and display status of job in alternate form (not POSIX standard) */ static void altdsp_statjob( struct batch_status *pstat, /* I */ struct batch_status *prtheader, /* I */ int alt_opt) /* I */ { const char *comment; char *pc; struct attrl *pat; const char *exechost; char *usern = NULL; char *queuen = NULL; char *jobn = NULL; const char *sess; const char *tasks; char calcTasks[64]; const char *nodect; const char *rqtimecpu; const char *rqtimewal; const char *jstate; const char *eltimecpu; const char *walltime_remaining = "0"; int rem_walltime = 0; int req_walltime = 0; int elap_time = 0; char elap_time_string[100]; char format_string[MAX_LINE_LEN]; int usecput; static char pfs[SIZEL]; static char rqmem[SIZEL]; static char srfsbig[SIZEL]; static char srfsfast[SIZEL]; static const char *blank = " -- "; if (prtheader) { printf("\n%s: ", prtheader->name); if ((pc = findattrl(prtheader->attribs, (char *)ATTR_comment, NULL)) != NULL) { printf("%s", pc); } if (alt_opt & ALT_DISPLAY_R) { printf("\n Req'd Req'd Elap"); printf("\nJob ID Username Queue NDS TSK Memory Time S Time BIG FAST PFS"); printf("\n---- ---------------- ----------- -------- ----- ------ ------ --------- - --------- ----- ----- -----\n"); } else { printf("\n Req'd Req'd Elap"); printf("\nJob ID Username Queue Jobname SessID NDS TSK Memory Time S Time"); printf("\n----------------------- ----------- -------- ---------------- ------ ----- ------ ------ --------- - ---------\n"); } } while (pstat != NULL) { exechost = blank; sess = blank; nodect = blank; tasks = blank; rqtimecpu = blank; rqtimewal = blank; eltimecpu = blank; jstate = blank; comment = blank; strcpy(elap_time_string, blank); snprintf(pfs, sizeof(pfs), "%s", blank); snprintf(rqmem, sizeof(rqmem), "%s", blank); snprintf(srfsbig, sizeof(srfsbig), "%s", blank); snprintf(srfsfast, sizeof(srfsfast), "%s", blank); usecput = 0; elap_time = 0; req_walltime = 0; rem_walltime = 0; pat = pstat->attribs; while (pat != NULL) { if (!strcmp(pat->name, ATTR_N)) { jobn = pat->value; } else if (!strcmp(pat->name, ATTR_owner)) { usern = pat->value; if ((pc = strchr(usern, (int)'@')) != NULL) * pc = '\0'; } else if (!strcmp(pat->name, ATTR_state)) { jstate = pat->value; } else if (!strcmp(pat->name, ATTR_queue)) { queuen = pat->value; } else if (!strcmp(pat->name, ATTR_session)) { sess = pat->value; } else if (!strcmp(pat->name, ATTR_l)) { if (!strcmp(pat->resource, "nodect")) { nodect = pat->value; } else if (!strcmp(pat->resource, "nodes")) { char *tmp = pat->value; char *eq = strchr(tmp,'='); if (eq != NULL) { int nodes = atoi(pat->value); int procs = atoi(eq+1); sprintf(calcTasks,"%d",nodes*procs); tasks = calcTasks; } else { tasks = pat->value; } } else if (!strcmp(pat->resource, "ncpus")) { if ((!strcmp(tasks,blank)) && (strcmp(pat->value, "0"))) tasks = pat->value; } else if (!strcmp(pat->resource, "mppe")) { if (strcmp(pat->value, "0")) tasks = pat->value; } else if (!strcmp(pat->resource, "size")) { if (strcmp(pat->value, "0")) tasks = pat->value; } else if (!strcmp(pat->resource, "mem")) { snprintf(rqmem, sizeof(rqmem), "%s", cnv_size(pat->value, alt_opt)); } else if (!strcmp(pat->resource, "pmem")) { snprintf(rqmem, sizeof(rqmem), "%s", cnv_size(pat->value, alt_opt)); } else if (!strcmp(pat->resource, "dmem")) { snprintf(rqmem, sizeof(rqmem), "%s", cnv_size(pat->value, alt_opt)); } else if (!strcmp(pat->resource, "vmem")) { snprintf(rqmem, sizeof(rqmem), "%s", cnv_size(pat->value, alt_opt)); } else if (!strcmp(pat->resource, "pvmem")) { snprintf(rqmem, sizeof(rqmem), "%s", cnv_size(pat->value, alt_opt)); } else if (!strcmp(pat->resource, "walltime")) { rqtimewal = pat->value; timestring_to_int(pat->value, &req_walltime); } else if (!strcmp(pat->resource, "cput")) { rqtimecpu = pat->value; usecput = 1; } else if (!strcmp(pat->resource, "srfs_big")) { snprintf(srfsbig, sizeof(srfsbig), "%s", cnv_size(pat->value, alt_opt)); } else if (!strcmp(pat->resource, "srfs_fast")) { snprintf(srfsfast, sizeof(srfsfast), "%s", cnv_size(pat->value, alt_opt)); } else if (!strcmp(pat->resource, "piofs")) { snprintf(pfs, sizeof(pfs), "%s", cnv_size(pat->value, alt_opt)); } } else if (!strcmp(pat->name, ATTR_exechost)) { exechost = pat->value; } else if (!strcmp(pat->name, ATTR_used)) { if (!strcmp(pat->resource, "cput")) { eltimecpu = pat->value; } //else if (!strcmp(pat->resource, "walltime")) } else if (!strcmp(pat->name, ATTR_comment)) { comment = pat->value; } else if (!strcmp(pat->name, "Walltime")) { walltime_remaining = pat->value; rem_walltime = atoi(walltime_remaining); } pat = pat->next; } if ((*jstate != 'Q') && (*jstate != 'C') && (*jstate != 'H')) { elap_time = req_walltime - rem_walltime; time_to_string(elap_time_string, elap_time); } /* inject precision into the format string */ snprintf(format_string, sizeof(format_string), "%%-23.%ds %%-11.11s %%-8.8s ", PBS_JOB_ID_LEN); printf(format_string, pstat->name, usern, queuen); if (alt_opt & ALT_DISPLAY_R) { printf("%5.5s %*.*s %6.6s %9.9s %1.1s %9.9s %5.5s %5.5s %5.5s", nodect, tasksize, tasksize, tasks, rqmem, usecput ? rqtimecpu : rqtimewal, jstate, usecput ? eltimecpu : elap_time_string, srfsbig, srfsfast, pfs); } else { /* inject precision into the format string */ snprintf(format_string, sizeof(format_string), "%%-%d.%ds %%6.6s %%5.5s %%*.*s %%6.6s %%9.9s %%1.1s %%9.9s", PBS_NAMELEN, PBS_NAMELEN); printf(format_string, jobn, sess, nodect, tasksize, tasksize, tasks, rqmem, usecput ? rqtimecpu : rqtimewal, jstate, usecput ? eltimecpu : elap_time_string); } if (linesize < maxlinesize) printf("\n"); if (alt_opt & ALT_DISPLAY_n) { /* print assigned nodes */ prt_nodes(exechost); } if (alt_opt & ALT_DISPLAY_s) { /* print (scheduler) comment */ if (*comment != '\0') printf(" %s\n", comment); } pstat = pstat->next; } } /* END altdsp_statjob() */ /* * get_ct - get count of jobs in queue/run state * support function for altdsp_statque() */ void get_ct( const char *str, int *jque, int *jrun) { char *ps; int colon = (int)':'; ps = strchr((char *)str, colon); /* Transit - skip */ ps = strchr(ps + 1, colon); /* Queued - add to jque */ *jque += atoi(ps + 1); ps = strchr(ps + 1, colon); /* Held - add to jque */ *jque += atoi(ps + 1); ps = strchr(ps + 1, colon); /* Waiting - add to jque */ *jque += atoi(ps + 1); ps = strchr(ps + 1, colon); /* Running - add to jrun */ *jrun += atoi(ps + 1); return; } /* END get_ct() */ /* * altdsp_statque - alternative display for queue information, -q option */ static void altdsp_statque( char *serv, struct batch_status *pstat, int opt) { char rmem[SIZEL]; const char *cput; const char *wallt; const char *jmax; const char *nodect; const char *blank = "-- "; int jrun; int jque; char qenabled = '\0'; char qstarted = '\0'; int tot_jrun = 0; int tot_jque = 0; struct attrl *pat; printf("\nserver: %s\n\n", serv); printf("Queue Memory CPU Time Walltime Node Run Que Lm State\n"); printf("---------------- ------ -------- -------- ---- --- --- -- -----\n"); while (pstat != NULL) { snprintf(rmem, sizeof(rmem), "-- "); cput = blank; wallt = blank; nodect = "-- "; jrun = 0; jque = 0; jmax = blank; pat = pstat->attribs; while (pat != NULL) { if (strcmp(pat->name, ATTR_maxrun) == 0) { jmax = pat->value; } else if (strcmp(pat->name, ATTR_enable) == 0) { if (*pat->value == 'T') qenabled = 'E'; else qenabled = 'D'; } else if (strcmp(pat->name, ATTR_start) == 0) { if (*pat->value == 'T') qstarted = 'R'; else qstarted = 'S'; } else if (strcmp(pat->name, ATTR_count) == 0) { get_ct(pat->value, &jque, &jrun); tot_jque += jque; tot_jrun += jrun; } else if (strcmp(pat->name, ATTR_rescmax) == 0) { if (strcmp(pat->resource, "mem") == 0) { snprintf(rmem, sizeof(rmem), "%s", cnv_size(pat->value, opt)); } else if (strcmp(pat->resource, "cput") == 0) { cput = pat->value; } else if (strcmp(pat->resource, "walltime") == 0) { wallt = pat->value; } else if (strcmp(pat->resource, "nodect") == 0) { nodect = pat->value; } } pat = pat->next; } printf("%-16.16s %6.6s %8.8s %8.8s %5.5s ", pstat->name, rmem, cput, wallt, nodect); printf("%3d %3d %2.2s %c %c\n", jrun, jque, jmax, qenabled, qstarted); pstat = pstat->next; } /* END while (pstat != NULL) */ printf(" ----- -----\n"); printf(" %5d %5d\n", tot_jrun, tot_jque); return; } /* END altdsp_statque() */ /* build and add an attropl struct to the list */ static void add_atropl( struct attropl **list, char *name, char *resc, char *value, enum batch_op op) { struct attropl *patro; patro = (struct attropl *)calloc(1, sizeof(struct attropl)); if (patro == NULL) { fprintf(stderr, "cannot calloc space\n"); exit(1); } patro->next = *list; patro->name = name; patro->resource = resc; patro->value = value; patro->op = op; *list = patro; return; } /* END add_atropl() */ /* * is_the_user * determine whether or not this job is owned by the specified user * * @param user - the user to check against * @param a - the attribute list for this job */ bool is_the_user( char *user, struct attrl *a) { char *at_user; char *at_owner; bool is_the_user = false; if ((user == NULL) || (user[0] == '\0')) return(TRUE); at_user = strchr(user, '@'); for (; a != NULL; a = a->next) { if (!strcmp(a->name, ATTR_owner)) { if (at_user == NULL) { if ((at_owner = strchr(a->value, '@')) != NULL) { *at_owner = '\0'; if (!strcmp(a->value, user)) is_the_user = true; *at_owner = '@'; return(is_the_user); } else { if (!strcmp(a->value, user)) return(true); else return(false); } } else if (!strcmp(a->value, user)) return(true); else return(false); } } return(false); } /* END is_the_user() */ /* display when a normal "qstat" is executed */ void display_statjob( struct batch_status *status, /* I (data) */ bool prtheader, /* I (boolean) */ int full, /* I (boolean) */ char *user) { struct batch_status *p; struct attrl *a; int l; char *c; char *jid; char *name; char *owner; const char *timeu; char *state; char *location; char format[80]; char long_name[17]; time_t epoch; bool do_not_display = false; mxml_t *DE; mxml_t *JE; mxml_t *AE; mxml_t *RE1; mxml_t *JI; /* XML only support for full output */ if (DisplayXML == TRUE) full = 1; if (!full) { sprintf(format, "%%-%ds %%-%ds %%-%ds %%%ds %%%ds %%-%ds\n", PBS_MAXSEQNUM + PBS_MAXJOBARRAYLEN + 11, PBS_MINNAMELEN, OWNERL, TIMEUL, STATEL, LOCL); if (prtheader == true) { /* display summary header TODO - the sizes of these fields should be determined from #defines in pbs_ifl.h */ printf("Job ID Name User Time Use S Queue\n"); printf("------------------------- ---------------- --------------- -------- - -----\n"); } } /* END if (!full) */ if (DisplayXML == TRUE) { /* create parent */ DE = NULL; MXMLCreateE(&DE, "Data"); } for (p = status;p != NULL;p = p->next) { jid = NULL; name = NULL; owner = NULL; timeu = NULL; state = NULL; location = NULL; do_not_display = false; if (is_the_user(user, p->attribs) == false) { continue; } if (full) { a = p->attribs; while (a != NULL) { if (!strcmp(a->name, ATTR_state)) { l = strlen(a->value); if (l > STATEL) { c = a->value + STATEL; *c = '\0'; } state = a->value; if (*state == 'C') { if ( do_not_display_complete == true ) { do_not_display = true; } break; } } a = a->next; } if (do_not_display == true) continue; if (DisplayXML == TRUE) { JE = NULL; MXMLCreateE(&JE, "Job"); MXMLAddE(DE, JE); JI = NULL; MXMLCreateE(&JI, "Job_Id"); MXMLSetVal(JI, p->name,mdfString); MXMLAddE(JE, JI); } else { printf("Job Id: %s\n", p->name); } RE1 = NULL; a = p->attribs; while (a != NULL) { if (a->name != NULL) { if (DisplayXML == TRUE) { /* lookup a->name -> XML attr name */ AE = NULL; if (a->resource != NULL) { if (RE1 == NULL) { MXMLCreateE(&RE1, a->name); MXMLAddE(JE, RE1); } MXMLCreateE(&AE, a->resource); MXMLSetVal(AE, a->value, mdfString); MXMLAddE(RE1, AE); } else { RE1 = NULL; MXMLCreateE(&AE, a->name); MXMLSetVal(AE, a->value, mdfString); MXMLAddE(JE, AE); } } else { if (!strcmp(a->name, ATTR_ctime) || !strcmp(a->name, ATTR_etime) || !strcmp(a->name, ATTR_mtime) || !strcmp(a->name, ATTR_qtime) || !strcmp(a->name, ATTR_start_time) || !strcmp(a->name, ATTR_comp_time) || !strcmp(a->name, ATTR_checkpoint_time) || !strcmp(a->name, ATTR_a)) { epoch = (time_t)atoi(a->value); prt_attr(a->name, a->resource, ctime(&epoch)); } else { if ((!strcmp(a->name, "Walltime")) && (a->value[0] == '-')) prt_attr(a->name, (char *)"Exceeded", a->value); else prt_attr(a->name, a->resource, a->value); printf("\n"); } } } a = a->next; } } /* END if (full) */ else { /* display summary data */ if (p->name != NULL) { c = p->name; while ((*c != '.') && (*c != '\0')) c++; if (alias_opt == TRUE) { /* show the alias as well as the first part of the server name */ if (*c == '.') { c++; while((*c != '.') && (*c != '\0')) c++; } } if (alias_opt == TRUE) { /* show the alias as well as the first part of the server name */ if (*c == '.') { c++; while((*c != '.') && (*c != '\0')) c++; } } if (*c != '\0') c++; /* List the first part of the server name, too. */ while ((*c != '.') && (*c != '\0')) c++; *c = '\0'; l = strlen(p->name); if (l > (PBS_MAXSEQNUM + PBS_MAXJOBARRAYLEN + 8)) { /* truncate job name */ c = p->name + PBS_MAXSEQNUM + PBS_MAXJOBARRAYLEN + 14; *c = '\0'; } jid = p->name; } a = p->attribs; while (a != NULL) { if (a->name != NULL) { if (strcmp(a->name, ATTR_name) == 0) { l = strlen(a->value); /* truncate AName */ if (l > PBS_NAMELEN) { l = l - PBS_NAMELEN + 3; c = a->value + l; while ((*c != '/') && (*c != '\0')) c++; if (*c == '\0') c = a->value + l; snprintf(long_name, sizeof(long_name), "...%s", c); c = long_name; } else { c = a->value; } name = c; } else if (!strcmp(a->name, ATTR_owner)) { c = a->value; while ((*c != '@') && (*c != '\0')) c++; *c = '\0'; l = strlen(a->value); if (l > OWNERL) { c = a->value + OWNERL; *c = '\0'; } owner = a->value; } else if (!strcmp(a->name, ATTR_used)) { if (!strcmp(a->resource, "cput")) { l = strlen(a->value); if (l > TIMEUL) { c = a->value + TIMEUL; *c = '\0'; } timeu = a->value; } } else if (!strcmp(a->name, ATTR_state)) { l = strlen(a->value); if (l > STATEL) { c = a->value + STATEL; *c = '\0'; } state = a->value; if (*state == 'C') { if ( do_not_display_complete == true ) do_not_display = true; } } else if (!strcmp(a->name, ATTR_queue)) { c = a->value; while ((*c != '@') && (*c != '\0')) c++; *c = '\0'; l = strlen(a->value); if (l > LOCL) { c = a->value + LOCL; *c = '\0'; } location = a->value; } } a = a->next; } if (timeu == NULL) timeu = "0"; /* display summary data */ if (do_not_display == false) { printf(format, jid, name, owner, timeu, state, location); } } /* END else (full) */ if (DisplayXML != TRUE && do_not_display == false) { if (full) printf("\n"); } } /* END for (p = status) */ if (DisplayXML == TRUE) { char *tmpBuf = NULL, *tail = NULL; int bufsize; MXMLToXString(DE, &tmpBuf, &bufsize, INT_MAX, &tail, TRUE); MXMLDestroyE(&DE); fprintf(stdout, "%s\n", tmpBuf); } return; } /* END display_statjob() */ #define MINNUML 3 #define MAXNUML 5 #define TYPEL 1 void display_statque( struct batch_status *status, bool prtheader, int full) { struct batch_status *p; struct attrl *a = NULL; int l; char *c; char *name; const char *max; const char *tot; char ena[MAXNUML + 1]; char str[MAXNUML + 1]; char que[MAXNUML + 1]; char run[MAXNUML + 1]; char hld[MAXNUML + 1]; char wat[MAXNUML + 1]; char trn[MAXNUML + 1]; char ext[MAXNUML + 1]; char dne[MAXNUML + 1]; const char *type; char format[80]; int NUML = 5; sprintf(format, "%%-%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%-%ds %%%ds\n", PBS_MINNAMELEN, NUML, NUML+1, NUML, NUML, NUML, NUML, NUML, NUML, NUML, NUML, TYPEL, NUML); if (!full && (prtheader == true)) { printf(format, "Queue", "Max", "Tot", "Ena", "Str", "Que", "Run", "Hld", "Wat", "Trn", "Ext", "T", "Cpt"); printf(format, "----------------", "---", "----", "--", "--", "---", "---", "---", "---", "---", "---", "-", "---"); } p = status; while (p != NULL) { name = NULL; max = "0"; tot = "0"; strcpy(ena, "no"); strcpy(str, "no"); strcpy(que, "0"); strcpy(run, "0"); strcpy(hld, "0"); strcpy(wat, "0"); strcpy(trn, "0"); strcpy(ext, "0"); strcpy(dne, "0"); type = "not defined"; if (full) { printf("Queue: %s\n", p->name); a = p->attribs; while (a != NULL) { if (a->name != NULL) { prt_attr(a->name, a->resource, a->value); printf("\n"); } a = a->next; } } else { a = p->attribs; if (p->name != NULL) { l = strlen(p->name); if ((l > PBS_NAMELEN) && (a != NULL)) { c = a->name + PBS_NAMELEN; *c = '\0'; } name = p->name; } while (a != NULL) { if (a->name != NULL) { if (strcmp(a->name, ATTR_maxrun) == 0) { l = strlen(a->value); if (l > NUML) { c = a->value + NUML; *c = '\0'; } max = a->value; } else if (strcmp(a->name, ATTR_total) == 0) { l = strlen(a->value); if (l > (NUML+1)) { c = a->value + (NUML+1); *c = '\0'; } tot = a->value; } else if (strcmp(a->name, ATTR_enable) == 0) { if (istrue(a->value) == true) strcpy(ena, "yes"); else strcpy(ena, "no"); } else if (strcmp(a->name, ATTR_start) == 0) { if (istrue(a->value) == true) strcpy(str, "yes"); else strcpy(str, "no"); } else if (strcmp(a->name, ATTR_count) == 0) { states(a->value, que, run, hld, wat, trn, ext, dne, NUML); } else if (strcmp(a->name, ATTR_qtype) == 0) { type = a->value; *((char *)type + 1) = '\0'; } } a = a->next; } printf(format, name, max, tot, ena, str, que, run, hld, wat, trn, ext, type, dne); } if (full) printf("\n"); p = p->next; } return; } #define STATUSL 10 void display_statserver( struct batch_status *status, bool prtheader, int full) { struct batch_status *p; struct attrl *a; int l; char *c; char *name; const char *max; const char *tot; char que[MAXNUML + 1]; char run[MAXNUML + 1]; char hld[MAXNUML + 1]; char wat[MAXNUML + 1]; char trn[MAXNUML + 1]; char ext[MAXNUML + 1]; char dne[MAXNUML + 1]; const char *stats; char format[80]; int NUML; NUML = MAXNUML; sprintf(format, "%%-%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%-%ds\n", PBS_MINNAMELEN, NUML, NUML, NUML, NUML, NUML, NUML, NUML, NUML, NUML, STATUSL); if (!full && (prtheader == true)) { printf(format, "Server", "Max", "Tot", "Que", "Run", "Hld", "Wat", "Trn", "Ext", "Com", "Status"); printf(format, "----------------", "---", "---", "---", "---", "---", "---", "---", "---", "---", "----------"); } p = status; while (p != NULL) { name = NULL; max = "0"; tot = "0"; strcpy(que, "0"); strcpy(run, "0"); strcpy(hld, "0"); strcpy(wat, "0"); strcpy(trn, "0"); strcpy(ext, "0"); strcpy(dne, "0"); stats = ""; if (full) { printf("Server: %s\n", p->name); a = p->attribs; while (a != NULL) { if (a->name != NULL) { prt_attr(a->name, a->resource, a->value); printf("\n"); } a = a->next; } } else { if (p->name != NULL) { l = strlen(p->name); if (l > PBS_NAMELEN) { c = p->name + PBS_NAMELEN; *c = '\0'; } name = p->name; } a = p->attribs; while (a != NULL) { if (a->name != NULL) { if (strcmp(a->name, ATTR_maxrun) == 0) { l = strlen(a->value); if (l > NUML) { c = a->value + NUML; *c = '\0'; } max = a->value; } else if (strcmp(a->name, ATTR_total) == 0) { l = strlen(a->value); if (l > NUML) { c = a->value + NUML; *c = '\0'; } tot = a->value; } else if (strcmp(a->name, ATTR_count) == 0) { states(a->value, que, run, hld, wat, trn, ext, dne, NUML); } else if (strcmp(a->name, ATTR_status) == 0) { l = strlen(a->value); if (l > STATUSL) { c = a->value + STATUSL; *c = '\0'; } stats = a->value; } } a = a->next; } printf(format, name, max, tot, que, run, hld, wat, trn, ext, dne, stats); } if (full) printf("\n"); p = p->next; } return; } /* END display_statserver() */ #if TCL_QSTAT #define ARGNUM 1024 char *attrlist( struct attrl *ap) { char nameres[256]; char *argv[ARGNUM]; char *ret; int i, num = 0; while (ap) { char *twol[2]; if (ap->resource != NULL) { sprintf(nameres, "%s%s%s", ap->name, TCL_ATRSEP, ap->resource); twol[0] = nameres; } else { twol[0] = ap->name; } twol[1] = ap->value; argv[num++] = Tcl_Merge(2, (const char **)twol); if (num == ARGNUM) break; ap = ap->next; } ret = Tcl_Merge(num, (const char **)argv); for (i = 0;i < num;i++) free(argv[i]); return(ret); } Tcl_Interp *interp = NULL; char script[200]; char flags[] = "flags"; char ops[] = "operands"; char error[] = "error"; void tcl_init(void) { struct passwd *pw; uid_t uid; struct stat sb; uid = getuid(); pw = getpwuid(uid); if (pw == NULL) return; sprintf(script, "%s/.qstatrc", pw->pw_dir); if (stat(script, &sb) == -1) { strcpy(script, QSTATRC_PATH); if (stat(script, &sb) == -1) return; } interp = Tcl_CreateInterp(); if (Tcl_Init(interp) == TCL_ERROR) { fprintf(stderr, "Tcl_Init error: %s", interp->result); } #if TCLX #if TCL_MINOR_VERSION < 5 && TCL_MAJOR_VERSION < 8 if (TclX_Init(interp) == TCL_ERROR) { #else if (Tclx_Init(interp) == TCL_ERROR) { #endif fprintf(stderr, "Tclx_Init error: %s", interp->result); } #endif /* TCLX */ return; } void tcl_addarg( const char *name, const char *arg) { if (interp == NULL) return; if (arg == NULL || *arg == '\0') return; Tcl_SetVar(interp, name, arg, TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE); } /* END tcl_addarg() */ int tcl_stat( const char *type, struct batch_status *bs, int f_opt) { struct batch_status *bp; const char *twol[2]; const char *word_one; char *word_two; char *argv[ARGNUM]; int i; int num = 0; char *result; if (interp == NULL) { return(1); } if (f_opt == 0) { return(1); } word_one = type; for (bp = bs;bp != NULL;bp = bp->next) { char *threel[3]; threel[0] = bp->name; threel[1] = attrlist(bp->attribs); threel[2] = bp->text; argv[num++] = Tcl_Merge(3, (const char **)threel); free(threel[1]); /* calloc'ed in attrlist() */ if (num == ARGNUM) break; } word_two = Tcl_Merge(num, (const char **)argv); for (i = 0;i < num;i++) free(argv[i]); twol[0] = word_one; twol[1] = word_two; result = Tcl_Merge(2, twol); Tcl_SetVar( interp, "objects", result, TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE); free(word_two); free(result); return(0); } void tcl_run( int f_opt) { if (interp == NULL) { return; } if (f_opt && Tcl_EvalFile(interp, script) != TCL_OK) { char *trace; trace = (char *)Tcl_GetVar(interp, "errorInfo", 0); if (trace == NULL) trace = interp->result; fprintf(stderr, "%s: TCL error @ line %d: %s\n", script, interp->errorLine, trace); } Tcl_DeleteInterp(interp); return; } /* END tcl_run() */ #else #define tcl_init() #define tcl_addarg(name, arg) #define tcl_stat(type, bs, f_opt) ; #define tcl_run(f_opt) #endif /* TCL_QSTAT */ int process_commandline_opts( int argc, char **argv, int *exec_only_flg, int *errflg_out) { int c; int exec_only = 0; int errflg = 0; int rc = PBSE_NONE; #if !defined(PBS_NO_POSIX_VIOLATION) #define GETOPT_ARGS "aceE:filn1qrstu:xGMQRBW:-:" #else #define GETOPT_ARGS "flQBW:" #endif /* PBS_NO_POSIX_VIOLATION */ mode = JOBS; user[0] = '\0'; alt_opt = 0; f_opt = 0; B_opt = 0; Q_opt = 0; t_opt = 0; E_opt = 0; while ((c = getopt(argc, argv, GETOPT_ARGS)) != EOF) { #ifdef TCL_QSTAT option[1] = (char)c; tcl_addarg(flags, option); tcl_addarg(flags, optarg); #endif switch (c) { #if !defined(PBS_NO_POSIX_VIOLATION) case '1': alt_opt |= ALT_DISPLAY_o; break; case 'a': alt_opt |= ALT_DISPLAY_a; break; case 'c': do_not_display_complete = true; break; case 'e': exec_only = 1; break; case 'E': if (optarg != NULL) { ExtendOpt = strdup(optarg); E_opt = TRUE; } break; case 'i': alt_opt |= ALT_DISPLAY_i; add_atropl(&p_atropl, (char *)ATTR_state, NULL, (char *)"EHQTW", EQ); break; case 'n': alt_opt |= ALT_DISPLAY_n; if (attrib != NULL) set_attr(&attrib, ATTR_exechost, NULL); break; case 'q': alt_opt |= ALT_DISPLAY_q; if (mode == SERVERS) { /* we can only process one mode at a time */ fprintf(stderr, "cannot combine -B with -q option\n"); return(PBSE_IVALREQ); } mode = QUEUES; break; case 'r': alt_opt |= ALT_DISPLAY_r; add_atropl(&p_atropl, (char *)ATTR_state, NULL, (char *)"RS", EQ); break; case 's': alt_opt |= ALT_DISPLAY_s; if (attrib != NULL) set_attr(&attrib, ATTR_comment, NULL); break; case 't': t_opt = 1; break; case 'u': alt_opt |= ALT_DISPLAY_u; snprintf(user, sizeof(user), "%s", optarg); break; case 'R': alt_opt |= ALT_DISPLAY_R; break; case 'G': alt_opt |= ALT_DISPLAY_G; break; case 'M': alt_opt |= ALT_DISPLAY_Mw; break; #endif /* PBS_NO_POSIX_VIOLATION */ case 'f': if ((alt_opt != 0) && (alt_opt != ALT_DISPLAY_u)) { fprintf(stderr, "%s -f incompatible with one or more options. Read qstat man page\n", conflict_msg); errflg++; return(PBSE_IVALREQ); } f_opt = 1; /* We want to return all attributes */ attrib = NULL; break; case 'x': DisplayXML = TRUE; /* We want to return all attributes */ attrib = NULL; break; case 'B': B_opt = 1; mode = SERVERS; if (Q_opt || alt_opt) { fprintf(stderr, "%s -B incompatible with one or more options. Read qstat man page\n", conflict_msg); errflg++; return(PBSE_IVALREQ); } break; case 'l': alias_opt = TRUE; break; case 'Q': Q_opt = 1; mode = QUEUES; if (B_opt || alt_opt) { fprintf(stderr, "%s -Q incompatible with one or more options. Read qstat man page\n", conflict_msg); errflg++; return(PBSE_IVALREQ); } break; case '-': /* handle '--' options */ if ((optarg != NULL) && !strcmp(optarg, "version")) { fprintf(stderr, "Version: %s\nCommit: %s\n", PACKAGE_VERSION, GIT_HASH); exit(0); } if ((optarg != NULL) && !strcmp(optarg, "about")) { TShowAbout_exit(); } /* unexpected '--' option received */ errflg = 1; break; case 'W': #if (TCL_QSTAT == 0) pc = optarg; while (*pc) { switch (*pc) { case 'a': alt_opt |= ALT_DISPLAY_a; break; case 'i': alt_opt |= ALT_DISPLAY_i; add_atropl(&p_atropl, (char *)ATTR_state, (char *)0, (char *)"EHQTW", EQ); break; case 'r': alt_opt |= ALT_DISPLAY_r; add_atropl(&p_atropl, (char *)ATTR_state, (char *)0, (char *)"RS", EQ); break; case 'u': /* note - u option is assumed to be last in */ /* string and all remaining is the name list */ alt_opt |= ALT_DISPLAY_u; while (*++pc == ' ') /* NO-OP, moving pointer */; snprintf(user, sizeof(user), "%s", pc); pc = pc + strlen(pc) - 1; /* for the later incr */ break; case 'n': alt_opt |= ALT_DISPLAY_n; break; case 's': alt_opt |= ALT_DISPLAY_s; break; case 'q': alt_opt |= ALT_DISPLAY_q; mode = QUEUES; break; case 'R': alt_opt |= ALT_DISPLAY_R; break; case 'G': alt_opt |= ALT_DISPLAY_G; break; case 'M': alt_opt |= ALT_DISPLAY_Mw; break; case ' ': break; /* ignore blanks */ default: errflg++; } ++pc; } #endif /* (TCL_QSTAT == 0) */ break; case '?': default: /* unexpected argument */ errflg++; break; } /* END switch (c) */ } /* END while (c = getopt()) */ #if !defined(PBS_NO_POSIX_VIOLATION) /* certain combinations are not allowed */ c = alt_opt & (ALT_DISPLAY_a | ALT_DISPLAY_i | ALT_DISPLAY_r | ALT_DISPLAY_q); if ((c != 0) && (c != ALT_DISPLAY_a) && (c != ALT_DISPLAY_i) && (c != ALT_DISPLAY_r) && (c != ALT_DISPLAY_q)) { fprintf(stderr, "%s", conflict_msg); errflg++; rc = PBSE_IVALREQ; } c = alt_opt & (ALT_DISPLAY_Mw | ALT_DISPLAY_G); if (c == (ALT_DISPLAY_Mw | ALT_DISPLAY_G)) { fprintf(stderr, "%s", conflict_msg); errflg++; rc = PBSE_IVALREQ; } if ((alt_opt & ALT_DISPLAY_q) && (f_opt == 1)) { fprintf(stderr, "%s", conflict_msg); errflg++; rc = PBSE_IVALREQ; } if ((alt_opt & ALT_DISPLAY_o) && !((alt_opt & ALT_DISPLAY_n) || (f_opt))) { fprintf(stderr, "%s", conflict_msg); errflg++; rc = PBSE_IVALREQ; } if (alt_opt & ALT_DISPLAY_o) { linesize = maxlinesize; alt_opt &= ~ALT_DISPLAY_o; } #endif /* PBS_NO_POSIX_VIOLATION */ *errflg_out = errflg; *exec_only_flg = exec_only; return(rc); } int run_job_mode( bool have_args, const char *operand, int *located, char *server_out, char *server_old, char *queue_name_out, char *server_name_out, char *job_id_out) { int any_failed = PBSE_NONE; int stat_single_job = 0; int connect; int job_id_out_size = PBS_MAXCLTJOBID; int server_out_size = MAXSERVERNAME; int server_old_size = MAXSERVERNAME; bool p_header = true; int retry_count = 0; char destination[PBS_MAXDEST + 1]; char job_id[PBS_MAXCLTJOBID]; char rmt_server[MAXSERVERNAME]; struct batch_status *p_server; struct batch_status *p_status; if (have_args == true) { if (!strcmp(operand, "(null)")) { return(PBSE_NONE); } if (isjobid(operand) == true) { /* must be a job-id */ stat_single_job = 1; snprintf(job_id, sizeof(job_id), "%s", operand); any_failed = get_server(job_id, job_id_out, job_id_out_size, server_out, server_out_size); if (any_failed != PBSE_NONE) { fprintf(stderr, "qstat: illegally formed job identifier: %s\n", job_id); tcl_stat(error, NULL, f_opt); any_failed = 1; return(any_failed); } } else { /* must be a destination-id */ stat_single_job = 0; snprintf(destination, sizeof(destination), "%s", operand); if (parse_destination_id( destination, &queue_name_out, &server_name_out)) { fprintf(stderr, "qstat: illegally formed destination: %s\n", destination); tcl_stat(error, NULL, f_opt); any_failed = PBSE_IVALREQ; return(any_failed); } if (notNULL(server_name_out)) { snprintf(server_out, server_out_size, "%s", server_name_out); } else { server_out[0] = '\0'; } snprintf(job_id_out, job_id_out_size, "%s", queue_name_out); if (*queue_name_out != '\0') { add_atropl(&p_atropl, (char *)ATTR_q, NULL, queue_name_out, EQ); } } /* END else */ } while (retry_count < MAX_RETRIES) { connect = cnt2server(server_out); any_failed = -1 * connect; if (connect <= 0 ) { if ((++retry_count < MAX_RETRIES) && ((any_failed != PBSE_TIMEOUT) && (any_failed != PBSE_SOCKET_FAULT))) { continue; } if (server_out[0] != 0) fprintf(stderr, "qstat: cannot connect to server %s (errno=%d) %s\n", server_out, any_failed, pbs_strerror(any_failed)); else fprintf(stderr, "qstat: cannot connect to server %s (errno=%d) %s\n", pbs_server, any_failed, pbs_strerror(any_failed)); tcl_stat(error, NULL, f_opt); return(any_failed); } if ((alt_opt != 0) && (strcmp(pbs_server, server_old) != 0)) { /* changing to a different server */ p_server = pbs_statserver_err(connect, NULL, NULL, &any_failed); snprintf(server_old, server_old_size, "%s", pbs_server); } else { p_server = 0; } if ((stat_single_job == 1) || (p_atropl == 0)) { p_status = pbs_statjob_err( connect, job_id_out, attrib, exec_only ? (char *)EXECQUEONLY : (char *)ExtendOpt, &any_failed); } else { if (t_opt) { p_status = pbs_selstatattr_err(connect, p_atropl, attrib, exec_only ? (char *)EXECQUEONLY : NULL, &any_failed); if (any_failed == PBSE_UNKREQ) p_status = pbs_selstat_err(connect, p_atropl, exec_only ? (char *)EXECQUEONLY : NULL, &any_failed); } else { p_status = pbs_selstatattr_err(connect, p_atropl, attrib, exec_only ? (char *)EXECQUEONLY : (char *)summarize_arrays_extend_opt, &any_failed); if (any_failed == PBSE_UNKREQ) p_status = pbs_selstat_err(connect, p_atropl, exec_only ? (char *)EXECQUEONLY : (char *)summarize_arrays_extend_opt, &any_failed); } } if (p_status == NULL) { if ((any_failed == PBSE_UNKJOBID) && !*located) { *located = TRUE; if (locate_job(job_id_out, server_out, rmt_server)) { pbs_disconnect(connect); snprintf(server_out, server_out_size, "%s", rmt_server); ++retry_count; continue; } tcl_stat("job", NULL, f_opt); prt_job_err((char *)"qstat", connect, job_id_out); break; } else { if ((any_failed != PBSE_NONE) && (++retry_count >= MAX_RETRIES)) { prt_job_err((char *)"qstat", connect, job_id_out); break; } if (any_failed && (retry_count < MAX_RETRIES)) { pbs_disconnect(connect); continue; } tcl_stat("job", NULL, f_opt); } } else { int condition = TRUE; #ifdef TCL_QSTAT condition = tcl_stat("job", p_status, f_opt); #endif if (alt_opt != 0) { altdsp_statjob(p_status, p_server, alt_opt); } else if ((f_opt == 0) || (condition)) { display_statjob(p_status, p_header, f_opt, user); } p_header = false; pbs_statfree(p_status); } pbs_disconnect(connect); break; } return(any_failed); } int run_queue_mode( bool have_args, const char *operand, char *server_out, char *queue_name_out, char *server_name_out) { int any_failed = PBSE_NONE; int connect; int server_out_size = MAXSERVERNAME; bool p_header = true; int retry_count = 0; char destination[PBS_MAXDEST + 1]; char *errmsg; struct batch_status *p_status; if (have_args == true) { if (!strcmp(operand, "(null)")) { return(any_failed); } snprintf(destination, sizeof(destination), "%s", operand); if (parse_destination_id(destination, &queue_name_out, &server_name_out)) { fprintf(stderr, "qstat: illegal 'destination' value\n"); tcl_stat(error, NULL, f_opt); return(PBSE_IVALREQ); } else { if (notNULL(server_name_out)) { snprintf(server_out, server_out_size, "%s", server_name_out); } else server_out[0] = '\0'; } } while(retry_count < MAX_RETRIES) { connect = cnt2server(server_out); if (connect <= 0) { if (++retry_count < MAX_RETRIES) { continue; } any_failed = -1 * connect; if (server_out[0] != 0) fprintf(stderr, "qstat: cannot connect to server %s (errno=%d) %s\n", server_out, any_failed, pbs_strerror(any_failed)); else fprintf(stderr, "qstat: cannot connect to server %s (errno=%d) %s\n", pbs_server, any_failed, pbs_strerror(any_failed)); tcl_stat(error, NULL, f_opt); return(any_failed); } p_status = pbs_statque_err(connect, queue_name_out, NULL, NULL, &any_failed); if (p_status == NULL) { if (any_failed && (++retry_count < MAX_RETRIES)) { pbs_disconnect(connect); continue; } if (any_failed) { errmsg = pbs_geterrmsg(connect); if (errmsg != NULL) { fprintf(stderr, "qstat: %s ", errmsg); free(errmsg); } else fprintf(stderr, "qstat: Error (%d - %s) getting status of queue ", any_failed, pbs_strerror(any_failed)); fprintf(stderr, "%s\n", queue_name_out); tcl_stat(error, NULL, f_opt); } } else { int condition = TRUE; #ifdef TCL_QSTAT condition = tcl_stat("queue", p_status, f_opt); #endif if (alt_opt & ALT_DISPLAY_q) { altdsp_statque(pbs_server, p_status, alt_opt); } else if (condition) { display_statque(p_status, p_header, f_opt); } p_header = false; pbs_statfree(p_status); } pbs_disconnect(connect); break; } return(any_failed); } int run_server_mode( bool have_args, const char *operand, char *server_out) { int connect; int any_failed = PBSE_NONE; int server_out_size = MAXSERVERNAME; bool p_header = true; int retry_count = 0; char *errmsg = NULL; struct batch_status *p_status; if (have_args == true) { if (!strcmp(operand, "(null)")) { return(PBSE_NONE); } snprintf(server_out, server_out_size, "%s", operand); } while (retry_count < MAX_RETRIES) { connect = cnt2server(server_out); if (connect <= 0) { if (++retry_count < MAX_RETRIES) { continue; } any_failed = -1 * connect; if (server_out[0] != 0) fprintf(stderr, "qstat: cannot connect to server %s (errno=%d) %s\n", server_out, any_failed, pbs_strerror(any_failed)); else fprintf(stderr, "qstat: cannot connect to server %s (errno=%d) %s\n", pbs_server, any_failed, pbs_strerror(any_failed)); tcl_stat(error, NULL, f_opt); any_failed = connect; return(any_failed); } p_status = pbs_statserver_err(connect, NULL, NULL, &any_failed); if (p_status == NULL) { /* check to see if we will do a retry before we print any error messages */ if (any_failed && (++retry_count < MAX_RETRIES)) { pbs_disconnect(connect); continue; } if (any_failed) { errmsg = pbs_geterrmsg(connect); if (errmsg != NULL) { fprintf(stderr, "qstat: %s ", errmsg); free(errmsg); } else fprintf(stderr, "qstat: Error (%d - %s) getting status of server ", any_failed, pbs_strerror(any_failed)); fprintf(stderr, "%s\n", server_out); tcl_stat(error, NULL, f_opt); } } else { int condition = TRUE; #ifdef TCL_QSTAT condition = tcl_stat("server", p_status, f_opt); #endif if (condition) display_statserver(p_status, p_header, f_opt); p_header = false; pbs_statfree(p_status); } pbs_disconnect(connect); break; } /* end while */ return(any_failed); } void print_usage() { static char usage[] = "usage: \n\ qstat [-f [-1]] [-W site_specific] [-x] [ job_identifier... | destination... ]\n\ qstat [-a|-i|-r|-e] [-u user] [-n [-1]] [-s] [-t] [-G|-M] [-R] [job_id... | destination...]\n\ qstat -Q [-f [-1]] [-W site_specific] [ destination... ]\n\ qstat -q [-G|-M] [ destination... ]\n\ qstat -B [-f [-1]] [-W site_specific] [ server_name... ]\n\ qstat -t\n"; fprintf(stderr,"%s", usage); } /* connects to server side routine pbs_statjob() in lib/Libifl/pbs_statjob.c */ /* routes to req_stat_job() in server/req_stat.c (PBS_BATCH_StatusJob) */ int main( int argc, /* I */ char **argv) /* I */ { int rc; int errflg = 0; int exec_only = 0; int any_failed = 0; int located = FALSE; char job_id_out[PBS_MAXCLTJOBID]; char server_out[MAXSERVERNAME] = ""; char server_old[MAXSERVERNAME] = ""; const char *def_server; char *queue_name_out = NULL; char *server_name_out = NULL; char operand[PBS_MAXCLTJOBID + 1]; bool have_args = false; #ifndef mbool #define mbool char #endif /* !mbool */ #ifndef TRUE #define TRUE 1 #endif /* !TRUE */ #ifndef FALSE #define FALSE 0 #endif /* !FALSE */ /* Attributes needed for default view */ set_attr(&attrib, ATTR_name, NULL); set_attr(&attrib, ATTR_owner, NULL); set_attr(&attrib, ATTR_used, NULL); set_attr(&attrib, ATTR_state, NULL); set_attr(&attrib, ATTR_queue, NULL); tcl_init(); tcl_addarg(flags, argv[0]); #ifdef TCL_QSTAT option[0] = '-'; option[2] = '\0'; #endif if (getenv("PBS_QSTAT_EXECONLY") != NULL) exec_only = 1; if (getenv("PBS_QSTAT_NO_COMPLETE") != NULL) do_not_display_complete = true; rc = process_commandline_opts(argc, argv, &exec_only, &errflg); if (rc != PBSE_NONE) { print_usage(); exit(2); } if (errflg) { print_usage(); exit(2); } if (!t_opt && !E_opt && !exec_only) { ExtendOpt = summarize_arrays_extend_opt; } def_server = pbs_default(); if (def_server == NULL) def_server = ""; /* Alternate display requires a few extra attributes */ if (alt_opt && (attrib != NULL)) { set_attr(&attrib, ATTR_session, NULL); set_attr(&attrib, ATTR_used, NULL); set_attr(&attrib, ATTR_l, NULL); } if (alt_opt & ALT_DISPLAY_u) { if (f_opt == 0) add_atropl(&p_atropl, (char *)ATTR_u, NULL, user, EQ); else alt_opt &= ~ALT_DISPLAY_u; } if (optind >= argc) { /* If no arguments, then set defaults */ server_out[0] = '@'; strcpy(&server_out[1], def_server); tcl_addarg(ops, server_out); job_id_out[0] = '\0'; server_out[0] = '\0'; queue_name_out = NULL; have_args = false; } /* END if (optind >= argc) */ else { have_args = true; } for (;optind <= argc;optind++) { located = FALSE; snprintf(operand, sizeof(operand), "%s", argv[optind]); tcl_addarg(ops, operand); switch (mode) { case JOBS: /* get status of batch jobs */ any_failed = run_job_mode(have_args, operand, &located, server_out, server_old, queue_name_out, server_name_out, job_id_out); if (any_failed != PBSE_NONE) exit(any_failed); break; case QUEUES: /* get status of batch queues */ any_failed = run_queue_mode(have_args, operand, server_out, queue_name_out, server_name_out); if (any_failed != PBSE_NONE) exit(any_failed); break; case SERVERS: /* get status of batch servers */ any_failed = run_server_mode(have_args, operand, server_out); if (any_failed != PBSE_NONE) exit(any_failed); break; } /* END switch (mode) */ } /* END for () */ tcl_run(f_opt); exit(any_failed); } /* END main() */