Article View: mod.computers.vax
Article #3794An enhanced SHOW SYSTEM utility
From: Bruce Bergman
Date: Mon, 16 Mar 1987 20:33
Date: Mon, 16 Mar 1987 20:33
781 lines
24179 bytes
24179 bytes
It occurred to me the other day that I have been using this neat
utility for viewing processes (similar to SHOW SYSTEM), and that
there are others who may like this program.
Enclosed you will find a DCL archive which contains two files:
bigsis.c
bigsis.man
The .c file should be compiled with DEC C V2.0 or greater, on
VMS V4.2 or greater. I wrote this to run on that configuration,
and since I no longer have access to a C compiler, I can't tell
you if it compiles on anything else. However, if you get it to
compile, it will tell you all sorts of useful information about
the jobs currently running on your system (not cluster).
It was written as a quick hak, and I never got around to putting
in all the features I wanted (like ability to work on 80 column
displays, selective process info, etc). It has one bug. If you
run it on a non-clustered environment, it won't display the sub
process parent information correctly. This can be fixed easily
as it is in a small routine at the bottom of the code. Other
than that, there are no known bugs. Read the man page to get an
idea of what it will tell you.
I'd be interested in hearing from you if you like the program!!
I've got a bunch of other nifty utilities I wrote, which I may
post at a later date. I'd like to see how this one goes over
first, though. Oh yes, the means of collecting the files into
one 'archive' is my own design. I didn't have any of the shar
programs running around, so I wrote my own. Hope it works okay.
Comments, suggestions, flames, etc., can be sent to me.
bruce bergman
$ !------------------------------ cut here ------------------------------
$ set noon
$ on control then goto YOU_QUIT
$ on error then goto I_QUIT
$ file = "BIGSIS.C"
$ chksum = 309885657
$ pass_fail = "FAILED"
$ write sys$output "Extracting ""''file'"" - original checksum was: ''chksum'"
$ create/nolog 'file'
$ deck/dollars="EoF@11:34:11.17"
/************************************************************************
* *
* B I G S I S *
* *
************************************************************************
** PURPOSE --------------------------------------------------------------
Show VMS system/process information concisely.
** PACKAGE --------------------------------------------------------------
VAX/VMS BIGSIS
** HISTORY --------------------------------------------------------------
1.0 01-Jun-85 Creation (Bruce A. Bergman)
1.1 27-Jun-85 Added ability to see process children
and parent id's. (Bruce A. Bergman)
1.1a 10-Sep-85 Suspended processes were hanging the
program so added code to display them
and continue. (Bruce A. Bergman)
** NON-DISCLOSURE -------------------------------------------------------
This program can be copied or modified, not for profit, as
long as this disclosure notice and author/edit information
remain with the source code at all times. No use of this
software or its associated source is permitted for commercial
or personal monetary gain (profit) in any form.
The author of this software is not responsible for any
repercussions that may arise from use of this software.
Bugs and/or suggestions may be sent to the author at:
Bruce A. Bergman
460 East Washington Avenue, #109
Escondido, CA. 92025-2958
(619) 489-8195
fido: 103/203
uucp: ...sdcsvax!telesoft!bruceb
** CODE -------------------------------------------------------------- */
#include <stdio.h>
#include <descrip.h>
#include <ssdef.h>
#include <jpidef.h>
/*
| These weren't identified in the sys$library:jpidef.h
| files so they MUST be included.
*/
globalvalue JPI$_CLINAME;
globalvalue JPI$_MODE;
globalvalue JPI$K_OTHER;
globalvalue JPI$K_INTERACTIVE;
globalvalue JPI$K_BATCH;
globalvalue JPI$K_NETWORK;
globalvalue JPI$_MASTER_PID;
globalvalue JPI$_MAXDETACH;
globalvalue JPI$_MAXJOBS;
#include <pcbdef.h>
#include <statedef.h>
main(argc, argv) /* show vms system/process information */
int argc;
char *argv[];
{
struct _itmlst {
unsigned short int buf_len;
unsigned short int item_code;
unsigned int buf_addr;
unsigned int ret_len;
} item_list[20];
char username[13],
procname[16],
terminal[9],
cliname[128],
states[6],
subs[6],
cputime[10],
imag_name[132],
image_name[50];
float fcputim;
unsigned
int ret_flag,
pid,
cur_pid,
mem,
pri,
prib,
cputim,
susp_flag,
ppgcnt,
sts,
state,
mode,
master_pid,
jobprccnt,
owner,
all_p,
net_w,
iosb;
unsigned
short
int maxjobs;
/*
| Set our options to none (until we evauluate
| them and determine that some are wanted.
*/
all_p = net_w = FALSE;
/*
| Check arguments for all possible info (a)
| or just network info (n). If no options
| just display the normal stuff. 'ALL' assumes
| user wants network info also.
*/
if (argc > 1 && argv[1][0] == '-') {
if (argv[1][1] == 'a' || argv[1][1] == 'A')
all_p = net_w = TRUE;
if (argv[1][1] == 'n' || argv[1][1] == 'N')
net_w = TRUE;
}
/*
| Set up item list with the information
| we want. This includes:
| Username
| Process name
| Process identification
| Amount of memory used
| Priority (current)
| Priority (base)
| CPU time
| Page count for image
| Virtual terminal id
| Mode
| CLI name
| Job status
| Job state
| Process parent's PID
| Sub-process count (current)
| Sub-process count (max)
| PID of owner of job
| Image name
*/
item_list[0].buf_len = 12;
item_list[0].item_code = JPI$_USERNAME;
item_list[0].buf_addr = username;
item_list[0].ret_len = 0;
item_list[1].buf_len = 15;
item_list[1].item_code = JPI$_PRCNAM;
item_list[1].buf_addr = procname;
item_list[1].ret_len = 0;
item_list[2].buf_len = 4;
item_list[2].item_code = JPI$_PID;
item_list[2].buf_addr = &pid;
item_list[2].ret_len = 0;
item_list[3].buf_len = 4;
item_list[3].item_code = JPI$_MEM;
item_list[3].buf_addr = &mem;
item_list[3].ret_len = 0;
item_list[4].buf_len = 4;
item_list[4].item_code = JPI$_PRI;
item_list[4].buf_addr = &pri;
item_list[4].ret_len = 0;
item_list[5].buf_len = 4;
item_list[5].item_code = JPI$_PRIB;
item_list[5].buf_addr = &prib;
item_list[5].ret_len = 0;
item_list[6].buf_len = 4;
item_list[6].item_code = JPI$_CPUTIM;
item_list[6].buf_addr = &cputim;
item_list[6].ret_len = 0;
item_list[7].buf_len = 4;
item_list[7].item_code = JPI$_PPGCNT;
item_list[7].buf_addr = &ppgcnt;
item_list[7].ret_len = 0;
item_list[8].buf_len = 8;
item_list[8].item_code = JPI$_TERMINAL;
item_list[8].buf_addr = terminal;
item_list[8].ret_len = 0;
item_list[9].buf_len = 4;
item_list[9].item_code = JPI$_MODE;
item_list[9].buf_addr = &mode;
item_list[9].ret_len = 0;
item_list[10].buf_len = 39;
item_list[10].item_code = JPI$_CLINAME;
item_list[10].buf_addr = cliname;
item_list[101].ret_len = 0;
item_list[11].buf_len = 4;
item_list[11].item_code = JPI$_STS;
item_list[11].buf_addr = &sts;
item_list[11].ret_len = 0;
item_list[12].buf_len = 4;
item_list[12].item_code = JPI$_STATE;
item_list[12].buf_addr = &state;
item_list[12].ret_len = 0;
item_list[13].buf_len = 4;
item_list[13].item_code = JPI$_MASTER_PID;
item_list[13].buf_addr = &master_pid;
item_list[13].ret_len = 0;
item_list[14].buf_len = 4;
item_list[14].item_code = JPI$_JOBPRCCNT;
item_list[14].buf_addr = &jobprccnt;
item_list[14].ret_len = 0;
item_list[15].buf_len = 2;
item_list[15].item_code = JPI$_MAXJOBS;
item_list[15].buf_addr = &maxjobs;
item_list[15].ret_len = 0;
item_list[16].buf_len = 4;
item_list[16].item_code = JPI$_OWNER;
item_list[16].buf_addr = &owner;
item_list[16].ret_len = 0;
item_list[17].buf_len = 132;
item_list[17].item_code = JPI$_IMAGNAME;
item_list[17].buf_addr = imag_name;
item_list[17].ret_len = 0;
/*
| Signal no more information required.
*/
item_list[18].buf_len = 0;
/*
| Print formatted headers.
*/
printf("%-8s %-12s %-15s %-8s ", "PID", "Username", "Process name", "Terminal");
printf("%-5s %-7s %-9s %-5s %-5s ", "Sub's", "Pri's", "CPU time", "State", "Size");
printf("%-11s\n", "Image name");
printf("-------- ------------ --------------- -------- ");
printf("----- ------- --------- ----- ----- ");
printf("-------------------------------------------------\n");
/*
| We want information from all processes.
*/
cur_pid = -1;
while (1) {
/*
| Set a flag saying we this process is
| NOT suspended (we handle this special).
*/
susp_flag = FALSE;
/*
| Call $GETJPI to obtain the actual info.
*/
ret_flag = sys$getjpi(32, &cur_pid, 0, &item_list, &iosb, 0, 0);
/*
| If $GETJPI says this process is suspended, mark
| it as such and pretend like it is okay - we will
| deal with it later.
*/
if (ret_flag == SS$_SUSPENDED) {
ret_flag |= SS$_NORMAL;
susp_flag = TRUE;
}
/*
| If $GETJPI says everything was 'queued' okay,
| let's wait until VMS says it has given us all
| the info we requested (we're being nice
| to VMS since we could have not waited).
*/
if (ret_flag & SS$_NORMAL) {
if (susp_flag == FALSE) {
ret_flag = sys$waitfr(32);
if (!ret_flag & SS$_NORMAL)
sys$exit(ret_flag);
}
/*
| Everything is okay, so now check and see
| if this job is at a terminal.
*/
if (terminal[0] == 0)
/*
| If this job is a batch job, check
| its pid with its parent pid. If they
| match, then this is a spawned job.
| If they don't match, it must be batch.
*/
if (mode & PCB$V_BATCH)
if (master_pid == pid)
strcpy(terminal, "*BATCH*");
else
strcpy(terminal, "Spawned");
else
/*
| This job is interactive (not batch).
| If this job is a network server
| and the user wants to know about
| networks, say so. If we aren't
| network then if the user wants to
| know about all jobs, then announce
| system jobs too.
*/
if (net_w && mode & PCB$V_NETWRK)
strcpy(terminal, "Network");
else
if (all_p)
strcpy(terminal, "[System]");
else
continue;
/*
| If this job has no children, set a value indicating
| how many children are possible out of the max allowed.
*/
if (master_pid == pid)
if (jobprccnt > 0)
sprintf(subs, "%2d/%-2d", jobprccnt, maxjobs);
else
strcpy(subs, " ");
else
/*
| If this job has children, place the last 4 characters
| of the parent pid into the process count area instead
| of indicating how many the job could have. This makes
| it easier to track down children processes.
*/
set_sub(subs, owner);
/*
| Set process state.
*/
set_state(states, state);
/*
| If user is not running an image, then
| check to see if it has a CLI, if not,
| it must be a dead system process so place
| defunct into image slot.
| Otherwise display the CLI name when appropriate.
*/
if (imag_name[0] == 0)
if (cliname[0] == 0)
sprintf(image_name, "<defunct>");
else
sprintf(image_name, "(%s)", cliname);
else
/*
| Now we see if the job was suspended.
| If it was, make it obvious to all and
| change state to relfect type of MWAIT.
| Otherwise just copy the image name into
| the slot (truncating and parsing as necessary).
*/
if (susp_flag == TRUE) {
strcpy(states, "SUSP");
sprintf(image_name, "[Out To Lunch]");
}
else
set_name(image_name, imag_name);
/*
| Change CPU time to float so we can display
| it as a decimal value rather than time; its
| easier to see change that way (who says?!).
*/
fcputim = cputim;
/*
| If no username, just defunct it also.
*/
if (username[0] == 0)
strcpy(username, "<defunct>");
/*
| At long last, time to print the info.
| Format everything so my sense of taste is not
| offended and make sure all process id's are in
| hexadecimal and hope the CPU time never gets HUGE.
*/
printf("%-8x %-12s %-15s %-8s ", pid, username, procname, terminal);
printf("%-5s %3d/%-3d %9.2f %-5s %-5d ", subs, pri, prib, fcputim/100, states, ppgcnt);
printf("%-49s\n", image_name);
/*
| Go get another process until done.
*/
continue;
}
/*
| Hooray we're done! Let's clean up and get outta here.
*/
if (ret_flag == SS$_NOMOREPROC)
break;
/*
| The user has no oper priv so we must just
| skip over this process like a good little program.
*/
if (ret_flag == SS$_NOPRIV)
continue;
/*
| Some unknown nasty has interrupted our
| session (how rude!). Let VMS handle it.
*/
sys$exit(ret_flag);
}
}
set_state(destin, state) /* turn process state code into readable form */
char *destin;
unsigned int state;
{
/*
| Assume we don't know what state we are in.
*/
strcpy(destin, "?????");
/* Start evaluating states until we find a match.
| Note: we could have done this with a switch() had
| these not been gloabalvalues. We're really better
| off this way and we don't loose any functionality.
*/
if (state == SCH$C_CEF)
strcpy(destin, "CEF");
if (state == SCH$C_COM)
strcpy(destin, "COM");
if (state == SCH$C_COMO)
strcpy(destin, "COMO");
if (state == SCH$C_CUR)
strcpy(destin, "CUR");
if (state == SCH$C_COLPG)
strcpy(destin, "COLPG");
if (state == SCH$C_FPG)
strcpy(destin, "FPG");
if (state == SCH$C_HIB)
strcpy(destin, "HIB");
if (state == SCH$C_HIBO)
strcpy(destin, "HIBO");
if (state == SCH$C_LEF)
strcpy(destin, "LEF");
if (state == SCH$C_LEFO)
strcpy(destin, "LEFO");
if (state == SCH$C_MWAIT)
strcpy(destin, "MWAIT");
if (state == SCH$C_PFW)
strcpy(destin, "PFW");
if (state == SCH$C_SUSP)
strcpy(destin, "SUSP");
if (state == SCH$C_SUSPO)
strcpy(destin, "SUSPO");
/*
| Return pointer to state
*/
return (destin);
}
set_sub(destin, pid) /* evaulate and set parent process id */
char *destin;
unsigned int pid;
{
char temp[9];
int i;
/*
| Print the parent process id into
| a holding region and put 'P' at
| first char position so user knows that
| the number following is a PARENT!
*/
sprintf(temp, "%-8x", pid);
*destin = 'P';
/*
| Copy the last 4 characters in the parent pid
| into destination. If pid was 0, just blank
| out (occurs in some defunct system processes).
*/
for (i = 1; i <= 4; i++)
*(destin+i) = temp[i+3];
*(destin+i) = '\0';
if (pid == 0)
*destin = '\0';
/*
| Return pointer to process string.
*/
return (destin);
}
set_name(destin, source) /* parse and truncate image name */
char *destin, *source;
{
int pos;
/*
| Search for first occurence of a directory spec
| searching from the end backwards. This will
| get rid of long (like in VMS 4.x) disk pathnames.
| Note: look to "SHOW DEVICE/FILES/NOSYSTEM" to see what
| is on which disk.
*/
pos = strrchr(source, '[');
/*
| Only copy the next 49 characters (so won't run
| off end of 132 col screen).
*/
strncpy(destin, pos, 49);
/*
| Return pointer to the image name.
*/
return (destin);
}
EoF@11:34:11.17
$ checksum 'file'
$ if 'chksum' .eq. 'checksum$checksum' then pass_fail = "PASSED"
$ write sys$output " Computed checksum is: ''checksum$checksum' (''pass_fail')"
$ file = "BIGSIS.MAN"
$ chksum = 979708107
$ pass_fail = "FAILED"
$ write sys$output "Extracting ""''file'"" - original checksum was: ''chksum'"
$ create/nolog 'file'
$ deck/dollars="EoF@11:35:48.99"
BIGSIS(1) VAX/VMS Utilities BIGSIS(1)
NAME
bigsis - display system and process information
SYNOPSIS
bigsis [ -an ]
DESCRIPTION
Bigsis displays VAX/VMS system and process information. The information
taken is a 'snapshot' of the system at the moment the request was given.
The -a option asks for information about all processes, including defunct
ones. The -n option asks that network processes be included as part of
the display (they are not normally). Specifying the -a option includes
the -n option automatically. Bigsis is formatted for a 132 column
screen.
The information returned to the user includes:
PID The process id of the current process. The PID is in
hexadecimal notation.
USERNAME The username is the actual login name that was used. It
will never change, whereas the process name CAN change
during the process' session. The username may appear as
"<defunct>" if the process is a defunct system process
(e.g. NULL or SWAPPER).
NAME The process name can be changed by the user, but initially
is identical to the username unless more than one process
already share the same username.
TERMINAL The terminal name (a virtual keyboard id under VMS V4.x)
will appear if the process is an active job connected to a
physical terminal. If the job is a _b_a_t_c_h job, the special
identifier "*BATCH*" will be shown in place of the
terminal name. If the process belongs to the system
(created by the system), "[SYSTEM]" appears in this
column. If the process is _s_p_a_w_n_e_d from another process,
"Spawned" is displayed and the user is shown the parent
process in the adjecent column (see SUBS for more
detail).
SUBS If a job has been spawned by this process, a count appears
that shows how many processes have been spawned and how
many processes CAN be spawned. The two pieces of
information are separated by a slash (/). If the maximum
number of possible sub-processes is zero, then unlimited
processes may be spawned. Note that this information
appears for the _p_a_r_e_n_t of the spawned process only.
If the process is a _c_h_i_l_d of another process, then the
special identifier "Pxxxx" is displayed in this column,
where xxxx refers to the last four (4) characters of the
parent process. The characters are also hexadecimal.
PRIORITY The priority of the current process is shown in this
column, in the form xx/xx. The first xx refers to the
process' CURRENT priority. The second xx refers to the
- 1 -
BIGSIS(1) VAX/VMS Utilities BIGSIS(1)
process' BASE priority.
CPUTIME The amount of CPU time the process has accumulated is
displayed as an integer rather than an actual 'time'
value. The decimal place separates seconds from
hundredth's of seconds. Later, when cows fly, the value
may be converted to an actual time.
STATE The current state that the process was in at the moment
the 'snapshot' was taken is displayed as an abbreviation.
Refer to the VAX/VMS System Routines manual for a complete
description of each state. The special state, "SUSP"
appears when a process has been suspended for some
reason. If this is the case, the image name will appear
as "[Out To Lunch]" to bring attention to the process.
SIZE The size (in pages) of the image that the current process
is executing is displayed. This is an approximate value
and should not be construed as an accurate reflection of
the image size.
IMAGE The image name is displayed for the current process, if it
is executing an image. Otherwise, if the process is not
suspended (see the STATE column for more detail), and if
it is not a defunct system process, the CLI (Command
Language Interpreter) for the current process is displayed
enclosed in parenthesis. If the process is a defunct
system process, "<defunct>" will appear in this column.
The image name, if displayed, is parsed and truncated to
show only the _l_a_s_t directory specification and the next 49
characters (e.g. [SYSEXE]BIGSIS.EXE;1 rather than
DUA0:[SYSEXE]BIGSIS.EXE;1).
BUGS
Bigsis requires that the user have appropriate privileges to obtain
information about other processes. If the user does not have these
privileges, only the user's process information is displayed.
The CPU time value is really not perfect, but it is easier to see a
change in the value in this form. I hope the process time never
exceeds the what can be stored as a 32 bit longword!
Finally, the parsing of the image name to fit on the screen can be
deceptive, in that an image from one directory can be on several
disks and never appear different from the bigsis display. I suggest
using "SHOW DEVICE/FILES/NOSYSTEM" for process-disk information.
- 2 -
EoF@11:35:48.99
$ checksum 'file'
$ if 'chksum' .eq. 'checksum$checksum' then pass_fail = "PASSED"
$ write sys$output " Computed checksum is: ''checksum$checksum' (''pass_fail')"
$ write sys$output "Finished."
$ exit
$YOU_QUIT:
$ write sys$output "Aborting upon request of user..."
$ exit
$I_QUIT:
$ write sys$output "Encountered a fatal condition - aborting..."
$ exit
$ !------------------------------ cut here ------------------------------
Technical Details
Message-ID:
<8703162033.AA04165@sdcsvax.UCSD.EDU>Path:
arc1-ca.pugleaf.net!utzoo!mnetor!seismo!columbia!rutgers!sri-spam!ames!ucbcad!ucbvax!telesoft.UUCP!brucebShow Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: arc1-ca.pugleaf.net!utzoo!mnetor!seismo!columbia!rutgers!sri-spam!ames!ucbcad!ucbvax!telesoft.UUCP!bruceb From: bruceb@telesoft.UUCP (Bruce Bergman @spot) Newsgroups: mod.computers.vax Subject: An enhanced SHOW SYSTEM utility Message-ID: <8703162033.AA04165@sdcsvax.UCSD.EDU> Date: Mon, 16-Mar-87 15:33:33 EST Article-I.D.: sdcsvax.8703162033.AA04165 Posted: Mon Mar 16 15:33:33 1987 Date-Received: Thu, 19-Mar-87 00:35:57 EST Sender: daemon@ucbvax.BERKELEY.EDU Distribution: world Organization: The ARPA Internet Lines: 781 Approved: info-vax@sri-kl.arpa