COMPILATION LISTING OF SEGMENT print_apt_entry Compiled by: Multics PL/I Compiler, Release 30, of February 16, 1988 Compiled at: Honeywell Bull, Phoenix AZ, SysM Compiled on: 08/22/88 1301.8 mst Mon Options: optimize map 1 /****^ *********************************************************** 2* * * 3* * Copyright, (C) Honeywell Bull Inc., 1987 * 4* * * 5* * Copyright, (C) Honeywell Information Systems Inc., 1982 * 6* * * 7* * Copyright (c) 1972 by Massachusetts Institute of * 8* * Technology and Honeywell Information Systems, Inc. * 9* * * 10* *********************************************************** */ 11 12 /* DESCRIPTION: 13* Prints the apt entry. 14**/ 15 16 /****^ HISTORY: 17*Written by unknown, sometime. 18*Modified: 19*06/01/78 by T. Casey: to add several new control args, print more info 20* for -brief, and always print channel and person. 21*06/01/81 by T. Casey: to fix it up for installation, and add process_id 22* active function. 23*11/01/81 by E. N. Kittlitz: user_table_entry conversion. 24*06/30/83 by E. A. Ranzenbach: for processor subset changes. 25*07/30/84 by R. Michael Tague: IPS name lengths were changed from 4 chars to 26* 32. Added dm_shutdown_warning_ and dm_user_shutdown_ signals. 27*08/22/84 by R. Michael Tague: Removed dm_shutdown_warning_ and 28* dm_user_shutdown_ IPS signals. Added system_shutdown_scheduled_ 29* and dm_shutdown_scheduled_ IPS signals. 30* Modified November 1984 by M. Pandolf to include hc_lock. 31* 32* 12/10/84 by E. Swenson for new IPC variables. 33**/ 34 35 36 /****^ HISTORY COMMENTS: 37* 1) change(87-04-26,GDixon), approve(87-07-13,MCR7741), 38* audit(87-07-24,Brunelle), install(87-08-04,MR12.1-1055): 39* Upgraded for change to answer_table.incl.pl1 and user_table_entry.incl.pl1 40* 2) change(87-07-24,GDixon), approve(87-07-24,MCR7741), 41* audit(87-07-24,Brunelle), install(87-08-04,MR12.1-1055): 42* A) Correct stringsize errors. 43* 3) change(87-11-03,GDixon), approve(88-08-08,MCR7960), 44* audit(88-08-09,Lippard), install(88-08-22,MR12.2-1088): 45* A) Add process lock-id to normal pae output, to aid in debugging locking 46* problems. (phx13768) 47* B) Avoid referencing apte elements via the f array; reference them by 48* name instead. Use the f array only to display the apte in octal. 49* C) Split lengthy output lines to avoid breaking across line boundary. 50* 4) change(88-07-26,Lippard), approve(88-08-08,MCR7960), 51* audit(88-08-16,Farley), install(88-08-22,MR12.2-1088): 52* Use user's default time zone instead of system default. (Hardcore 53* 1014, 1026). Make pae -absentee print APTEs for the user's absentee 54* processes (instead of the user's own APTE). (Hardcore 1061) 55* END HISTORY COMMENTS */ 56 57 58 /* format: style4 */ 59 60 print_apt_entry: pae: proc; 61 62 /* DECLARATIONS */ 63 64 /* Automatic and based variables */ 65 66 /* based, and pointers, lengths, and things they're based on */ 67 68 dcl ap ptr; 69 dcl al fixed bin; 70 dcl bchr char (al) based (ap); 71 72 dcl f (0:size (apte) - 1) fixed bin (35) based (aptep); 73 74 dcl proc_id bit (36) aligned; 75 dcl procid fixed bin (35) aligned based (addr (proc_id)); 76 77 dcl temp_date_time char (16); /* mm/dd/yy HHMM.M */ 78 dcl temp_date char (8) based (addr (temp_date_time)); /* mm/dd/yy */ 79 80 dcl first_17_flags (17) bit (1) unaligned based (addr (apte.flags)); 81 dcl flag18 bit (1) unaligned based (addr (apte.flags.firstsw)); 82 83 dcl return_ptr ptr; 84 dcl return_len fixed bin; 85 dcl return_string char (return_len) varying based (return_ptr); /* active function return string */ 86 87 /* switches */ 88 89 dcl display_mode fixed bin init (2); /* 0= -no_display, 1= -brief_display, 2= -display */ 90 91 dcl (af_sw, apte_offset_sw, as_sw, chn_sw, dmn_sw, dump_sw, ia_sw, id_sw, multiple_sw, 92 pae_sw, pdir_sw, pid_sw, process_id_sw, short_sw, term_channel_sw, user_sw) bit (1) aligned init (""b); 93 94 /* fixed bin */ 95 96 dcl (total_matched, this_id_matched) fixed bin; 97 98 dcl argno fixed bin; 99 dcl nargs fixed bin; 100 dcl ids fixed bin init (0); 101 dcl code fixed bin (35); 102 dcl i fixed bin; 103 dcl apte_offset fixed bin (18); 104 105 dcl alrm fixed bin (71); 106 dcl now fixed bin (71); 107 dcl cpu_mon fixed bin (71) init (0); 108 109 /* character strings */ 110 111 dcl pers char (24); 112 dcl proj char (12); 113 dcl tag char (1); 114 dcl channel char (32); 115 116 dcl pers_arg char (23) varying; 117 dcl proj_arg char (10) varying; 118 dcl tag_arg char (2) varying; 119 120 dcl today char (8); 121 dcl c32 char (32); 122 dcl (flags, ips_pending) char (256) varying init (""); 123 dcl segname char (32); 124 dcl me char (16); 125 126 /* structures */ 127 128 dcl 1 tc_data like apte aligned; /* place in stack to put one APTE */ 129 130 131 /* Internal static constants */ 132 133 dcl state_names (0:6) char (8) int static options (constant) init 134 ("Empty", "Running", "Ready", "Waiting", "Blocked", "Stopped", "Ptl_wait"); 135 dcl flag_names (17) char (16) int static options (constant) init 136 ("mbz1", "wakeup_waiting", "stop_pending", "pre-empted", "hproc", "loaded", "eligible", "idle", "interaction", 137 "pre-empt_pending", "default_proc_set", "realtime_burst", "always_loaded", "dbr_loaded", "being_loaded", "shared_stack_0", "page_wait"); 138 139 dcl sysdir char (168) int static options (constant) init (">system_control_1"); 140 dcl CAPS char (26) int static options (constant) init ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 141 142 /* Internal static variables */ 143 144 dcl apte1_offset fixed bin int static init (0); 145 dcl (static_ansp, static_dutp, tcdp0, static_autp) ptr static; 146 dcl (tables_initiated, tcd_initiated) bit (1) aligned int static init (""b); 147 148 /* External static variables */ 149 150 dcl error_table_$badopt ext fixed bin (35); 151 dcl error_table_$inconsistent ext fixed bin (35); 152 dcl error_table_$not_act_fnc ext fixed bin (35); 153 154 /* Entries, external constant, and variable */ 155 156 dcl err_proc variable entry options (variable); /* com_err_ or active_fnc_err_ */ 157 158 dcl active_fnc_err_ entry options (variable); 159 dcl com_err_ entry options (variable); 160 dcl cu_$af_return_arg entry (fixed bin, ptr, fixed bin, fixed bin (35)); 161 dcl cu_$arg_ptr entry (fixed bin, ptr, fixed bin, fixed bin (35)); 162 dcl cv_oct_check_ entry (char (*), fixed bin (35)) returns (fixed bin (35)); 163 dcl date_time_ entry (fixed bin (71), char (*)); 164 dcl date_time_$format entry (char (*), fixed bin (71), char (*), char (*)) returns (char (250) var); 165 dcl get_group_id_ entry returns (char (32)); 166 dcl get_line_length_$switch entry (ptr, fixed bin (35)) returns (fixed bin); 167 dcl get_process_id_ entry returns (bit (36)); 168 dcl hcs_$initiate entry (char (*), char (*), char (*), fixed bin (1), fixed bin (2), ptr, fixed bin (35)); 169 dcl ioa_ entry options (variable); 170 dcl ioa_$rsnnl entry options (variable); 171 dcl match_star_name_ entry (char (*), char (*), fixed bin (35)); 172 dcl ring0_get_$segptr entry (char (*) aligned, char (*) aligned, ptr, fixed bin (35)); 173 dcl ring_zero_peek_ entry (ptr, ptr, fixed bin, fixed bin (35)); 174 dcl unique_chars_ entry (bit (*) aligned) returns (char (15)); 175 dcl user_info_$terminal_data entry (char (*), char (*), char (*)); 176 177 /* Builtin */ 178 179 dcl (addr, after, before, bin, clock, divide, fixed, hbound, index, lbound, 180 length, log10, ltrim, max, mod, null, ptr, rel, rtrim, search, size, 181 string, substr, unspec) builtin; 182 183 /* This is the pae entry point */ 184 185 pae_sw = "1"b; 186 me = "print_apt_entry"; 187 goto af_common; /* go see if we're a command or an active function */ 188 189 process_id: entry; 190 191 process_id_sw = "1"b; 192 me = "process_id"; 193 194 af_common: 195 196 call cu_$af_return_arg (nargs, return_ptr, return_len, code); 197 198 if code = 0 then do; /* active function */ 199 af_sw = "1"b; 200 err_proc = active_fnc_err_; 201 end; 202 203 else if code = error_table_$not_act_fnc then do; /* command */ 204 af_sw = ""b; 205 err_proc = com_err_; 206 end; 207 208 else do; /* some other code - something is wrong */ 209 call com_err_ (code, me); 210 return; 211 end; 212 213 /* Initialize entry-point-dependent defaults before looking at control args */ 214 215 if process_id_sw | af_sw then multiple_sw = ""b; /* default for process_id and [pae] is one process */ 216 else multiple_sw = "1"b; /* default for pae is multiple processes */ 217 218 /* Initialize offset of Initializer's APTE */ 219 220 if apte1_offset = 0 then 221 apte1_offset = size (tcm) - 1; 222 223 /* Look at control arguments */ 224 225 do argno = 1 to nargs; 226 call cu_$arg_ptr (argno, ap, al, code); /* this works for both commands and active functions */ 227 if code ^= 0 then do; 228 call err_proc (code, me); 229 return; 230 end; 231 232 if substr (bchr, 1, 1) ^= "-" then /* if this is an ID */ 233 ids = ids + 1; /* count it, and skip it until next pass thru arg list */ 234 235 /* Check for control arguments common to both entry points */ 236 237 else if bchr = "-ia" | bchr = "-interactive" then 238 ia_sw = "1"b; 239 else if bchr = "-as" | bchr = "-abs" | bchr = "-absentee" then 240 as_sw = "1"b; 241 else if bchr = "-dmn" | bchr = "-daemon" then 242 dmn_sw = "1"b; 243 else if bchr = "-only" then 244 ia_sw, as_sw, dmn_sw = ""b; 245 else if bchr = "-all" | bchr = "-a" then 246 ia_sw, as_sw, dmn_sw = "1"b; 247 else if bchr = "-single" then 248 multiple_sw = ""b; 249 else if bchr = "-multiple" then 250 multiple_sw = "1"b; 251 252 else if bchr = "-user" 253 | bchr = "-chn" | bchr = "-channel" 254 | bchr = "-pid" | bchr = "-process_id" then do; /* if next argument is an ID */ 255 argno = argno + 1; /* skip over it this time thru arglist */ 256 ids = ids + 1; /* count ID args */ 257 end; 258 259 /* Check for control arguments accepted only by pae */ 260 261 else if pae_sw then do; 262 if bchr = "-dump" then 263 dump_sw = "1"b; 264 else if bchr = "-no_dump" then 265 dump_sw = ""b; 266 else if bchr = "-sh" | bchr = "-short" then 267 short_sw = "1"b; 268 else if bchr = "-lg" | bchr = "-long" then 269 short_sw = ""b; 270 else if bchr = "-dpy" | bchr = "-display" then 271 display_mode = 2; 272 else if bchr = "-bfdpy" | bchr = "-brief_display" then 273 display_mode = 1; 274 else if bchr = "-ndpy" | bchr = "-no_display" then 275 display_mode = 0; 276 else if bchr = "-pd" | bchr = "-pdir" | bchr = "-process_dir" | bchr = "-process_directory" then 277 pdir_sw = "1"b; 278 else if bchr = "-tchn" | bchr = "-term" | bchr = "-term_chn" | bchr = "-term_channel" then 279 term_channel_sw = "1"b; 280 else goto badopt; 281 end; /* end pae args */ 282 283 else do; 284 badopt: call err_proc (error_table_$badopt, me, "^a", bchr); 285 return; 286 end; 287 288 end; /* end first pass thru argument list */ 289 290 /* Now, see what args were given, check legality, and apply defaults */ 291 292 if pdir_sw | term_channel_sw /* if returning pdir or term channel */ 293 then pae_sw = ""b; /* then we're not going to print the APTE */ 294 295 if pae_sw & af_sw then do; /* can't return a whole APTE */ 296 call err_proc (0, me, "No APTE item specified."); 297 return; 298 end; 299 300 if pdir_sw & term_channel_sw then do; /* if both given, complain */ 301 call err_proc (error_table_$inconsistent, me, "-process_dir and -term_channel"); 302 return; 303 end; 304 305 if ids > 1 then multiple_sw = "1"b; /* single only makes sense with one ID */ 306 307 /* Initialize only what is needed for what we've been asked to do */ 308 309 if pae_sw then do; /* if printing APTE, get date and time */ 310 now = clock (); 311 call date_time_ (now, temp_date_time); /* format current date and time */ 312 today = temp_date; /* copy mm/dd/yy */ 313 end; 314 315 if ids > 0 then /* if no IDs given, we're doing it for this process */ 316 call table_init; /* otherwise we need pointers to the user tables */ 317 /* (all users do not have access, so only try if needed) */ 318 319 if pae_sw | term_channel_sw then /* if printing APTE or returning term channel */ 320 call tcd_init; /* we'll need to look in tc_data */ 321 322 aptep = addr (tc_data); /* get pointer to temporary storage */ 323 id_sw = ""b; 324 total_matched, this_id_matched = 0; 325 326 /* If no ID arguments given, do it for the current process */ 327 328 if ids = 0 then do; 329 id_sw = valid_id (rtrim (get_group_id_ ())); /* get User_ID */ 330 pers = pers_arg; /* copy components of user_ID */ 331 proj = proj_arg; 332 tag = tag_arg; 333 if ia_sw | as_sw | dmn_sw then do; 334 tag_arg = "*"; 335 call table_init; 336 call print_matching_processes (rtrim (pers_arg) || "." || rtrim (proj_arg) || "." || tag_arg); 337 return; 338 end; 339 call user_info_$terminal_data ((""), (""), channel); /* and channel */ 340 proc_id = get_process_id_ (); 341 call print_it; /* either print APTE, or return something */ 342 return; 343 end; 344 345 if ^(ia_sw | as_sw | dmn_sw) then /* if none of -ia -as -dmn given */ 346 ia_sw, as_sw, dmn_sw = "1"b; /* default is all three */ 347 348 /* There were IDs given. Go back thru the argument list and look for them. */ 349 350 do argno = 1 to nargs; /* go thru args again to process user and channel names */ 351 call cu_$arg_ptr (argno, ap, al, code); /* ignore code this time around */ 352 353 if ^id_sw /* if previous arg wasn't -user, -chn, or -pid, */ 354 & substr (bchr, 1, 1) = "-" then do; /* and this is a control arg, see if it's one of those */ 355 if bchr = "-user" then 356 user_sw, id_sw = "1"b; 357 else if bchr = "-chn" | bchr = "-channel" then 358 chn_sw, id_sw = "1"b; 359 else if bchr = "-pid" | bchr = "-process_id" then 360 pid_sw, id_sw = "1"b; 361 362 else user_sw, chn_sw, pid_sw, id_sw, apte_offset_sw = ""b; /* if not_sw,clear all the switches */ 363 end; /* end previous arg not -user, -chn or -pid */ 364 365 else if id_sw /* if previous arg was one of the above */ 366 | substr (bchr, 1, 1) ^= "-" then do; /* or if this one is not a control arg */ 367 /* treat it as an ID arg */ 368 this_id_matched = 0; /* we'll count processes that match this ID */ 369 370 371 if valid_id (bchr) then do; /* if ID is legal, search user tbales for match */ 372 /* (if it's not legal, valid_id prints an error message) */ 373 call print_matching_processes ((bchr)); 374 end; /* end valid ID */ 375 376 id_sw = ""b; /* clear this, in case it was on for this ID argument */ 377 378 end; /* end ID argument */ 379 380 total_matched = total_matched + this_id_matched; /* count total matches */ 381 382 end; /* end second pass thru argument list */ 383 384 /* If we're a command, or an active function with just one ID argument, we already 385* reported on failure of any process to match the ID(s), But if we're an active 386* function with multiple IDs, we could get here without matching any processes 387* or putting anything in the return string. We'll complain about that, 388* rather then quietly returning a null string. */ 389 390 if af_sw & ids > 1 & total_matched = 0 then 391 call err_proc (0, me, "The given identifiers did not match any processes."); 392 MAIN_RETURN: 393 return; 394 395 /* Come here from internal procedures if unable to get pointers to user tables or tc_data */ 396 397 init_error: 398 call err_proc (code, me, "Cannot get ptr to ^a", segname); 399 return; 400 401 match_ute: proc returns (bit (1) aligned); 402 403 dcl ec fixed bin (35); 404 405 if chn_sw then do; /* -chn ID or ID with no uppercase letters * */ 406 call match_star_name_ ((ute.tty_name), (bchr), ec); 407 if ec = 0 then goto matched; 408 end; 409 410 else if user_sw then do; /* -user ID or ID containing uppercase letters */ 411 call match_star_name_ ((ute.person), (pers_arg), ec); 412 if ec = 0 then do; /* person matched; check project */ 413 call match_star_name_ ((ute.project), (proj_arg), ec); 414 if ec = 0 then do; /* project matched; check tag */ 415 if tag_arg ^= "m" & tag_arg ^= "p" /* only for two kinds of absentee tags */ 416 then goto matched; /* since main loop does process type checking */ 417 if ute.proxy then /* if this process is proxy */ 418 if tag_arg = "p" then goto matched; 419 else ; /* it wasn't "p" so don't goto matched */ 420 else /* this process is not proxy */ 421 if tag_arg = "m" then goto matched; 422 end; /* end project matched */ 423 end; /* end person matched */ 424 end; 425 426 else if pid_sw then do; /* -pid ID, or octal ID */ 427 if ute.proc_id = proc_id then goto matched; 428 if apte_offset_sw then 429 if substr (ute.proc_id, 1, 18) = substr (proc_id, 1, 18) then goto matched; 430 end; 431 return (""b); 432 matched: 433 434 /* Copy stuff out of the answer table entry */ 435 436 proc_id = ute.proc_id; 437 proj = ute.project; 438 pers = ute.person; 439 channel = ute.tty_name; 440 441 if ute.queue = -1 then /* daemon */ 442 tag = "z"; 443 else if ute.queue = 0 & ^ute.adjust_abs_q_no then /* interactive */ 444 tag = "a"; 445 else /* absentee */ 446 if ute.proxy then /* proxy absentee */ 447 tag = "p"; 448 else tag = "m"; /* normal absentee */ 449 450 return ("1"b); 451 end match_ute; 452 453 print_it: proc; 454 455 /* We call this procedure either to print the whole APTE, or to print or return one value from it. */ 456 457 dcl fxl fixed bin; /* length of dump lines, either 4 or 8 words */ 458 dcl fxp ptr; /* pointer to first word in line */ 459 dcl fx (fxl) fixed bin (35) based (fxp); /* array of 4 or 8 words in dump line */ 460 dcl i fixed bin; 461 dcl integer_len fixed bin; /* length of integer part of float nums */ 462 dcl l fixed bin; /* for octal dump, index of first APTE word in dump line */ 463 dcl line_len fixed bin; /* terminal line length */ 464 465 this_id_matched = this_id_matched + 1; /* count processes matching the ID */ 466 467 if this_id_matched > 1 then /* if this is the 2nd (or more) match for this ID */ 468 if ^multiple_sw /* and the user only wanted one */ 469 then return; /* don't print or return any more */ 470 471 if pae_sw | term_channel_sw | apte_offset_sw then do; /* if we need to look in the APTE */ 472 tcdp0 = ptr (tcdp0, substr (proc_id, 1, 18));/* generate pointer to APTE in ring 0 */ 473 call ring_zero_peek_ (tcdp0, aptep, size (apte), code); /* copy the data out */ 474 if code ^= 0 then do; 475 call err_proc (code, me, "from ring_zero_peek_"); 476 return; 477 end; 478 if apte_offset_sw then /* if just apt offset given */ 479 unspec (procid) = apte.processid; /* copy full procid out of apt entry */ 480 end; /* end we need to look in the APTE */ 481 482 if pae_sw | pdir_sw then do; /* if we need the process directory name, get it */ 483 apte_offset = divide (procid, 2 ** 18, 18, 0); 484 if apte_offset = apte1_offset then /* special case the Initializer's pdir name */ 485 c32 = ">pdd>!zzzzzzzbBBBBBB"; /* it is unique_chars_ (777777777777) */ 486 else c32 = ">pdd>" || unique_chars_ (proc_id); /* all other pdir names come from process id */ 487 end; /* end we need pdir name */ 488 489 /* If we didn't need the pdir name, the user must have asked for either process_id or term_channel */ 490 491 else if process_id_sw then /* if process id wanted */ 492 call ioa_$rsnnl ("^w", c32, (0), procid); /* format it */ 493 494 else if term_channel_sw then /* if process termination event channel wanted */ 495 call ioa_$rsnnl ("^24.3b", c32, (0), unspec (apte.term_channel)); /* format it */ 496 497 /* Now, if we're not the pae command, we either return or print an active function value */ 498 499 if af_sw then do; /* active function */ 500 if length (return_string) > 0 then /* if there's anything in the return string */ 501 return_string = return_string || " "; /* put a blank after it */ 502 return_string = return_string || rtrim (c32);/* put the return value in it */ 503 return; /* return to the main loop */ 504 end; 505 506 else if ^pae_sw then do; /* if not pae, print what the A/F would have returned */ 507 call ioa_ ("^a", c32); 508 return; 509 end; 510 511 /* If it was pae, fall thru and print the APTE */ 512 513 /* First, the heading */ 514 515 line_len = get_line_length_$switch (null, code); 516 call ioa_ ("^/^a.^a.^a ^a at ^o in tc_data, ^a", pers, proj, tag, channel, fixed (rel (tcdp0), 18), c32); 517 518 /* Print line 1 unless -no_display */ 519 520 if display_mode > 0 then 521 call ioa_ ("^[FLAGS: ^w^2x^;^s^]^[EVENT: ^w^2x^;^s^]PID: ^w^2xLOCK_ID: ^w^[^2x^; 522 ^]TRM CHN: ^w ^w", 523 (display_mode < 2), unspec (apte.flags), 524 (apte.wait_event ^= ""b), apte.wait_event, 525 apte.processid, apte.lock_id, 526 bin (display_mode < 2) * length ("FLAGS: oooooooooooo ") + 527 bin (apte.wait_event ^= ""b) * length ("EVENT: oooooooooooo ") + 528 length ("PID: oooooooooooo LOCK_ID: oooooooooooo ") + 529 length ("TRM CHN: oooooooooooo oooooooooooo") <= line_len, 530 substr (unspec (apte.term_channel), 1, 36), 531 substr (unspec (apte.term_channel), 37, 36)); 532 533 if display_mode = 2 then do; /* -display */ 534 535 /* -display: print the following three lines (stuff in [] only if interesting): 536* 2) for (since ]). Usage: cpu ; vcpu ; pf . 537* 3) te/s/i/x: E S I X.[ pending.][ Flags: .] 538* 4) [Alarm in (at