home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / sources / wanted / 5377 < prev    next >
Encoding:
Internet Message Format  |  1992-12-15  |  16.0 KB

  1. Xref: sparky comp.sources.wanted:5377 alt.sources:2781
  2. Newsgroups: comp.sources.wanted,alt.sources
  3. Path: sparky!uunet!munnari.oz.au!metro!usage!spectrum!cameron
  4. From: cameron@spectrum.cs.unsw.oz.au (Cameron Simpson)
  5. Subject: Re: kill-by-name that *works*
  6. Message-ID: <1992Dec15.061328.4646@usage.csd.unsw.OZ.AU>
  7. Followup-To: alt.sources.d
  8. Sender: news@usage.csd.unsw.OZ.AU
  9. Nntp-Posting-Host: fuligin.spectrum.cs.unsw.oz.au
  10. Reply-To: cameron@spectrum.cs.unsw.oz.au (Cameron Simpson)
  11. Organization: CS&E Computing Facility, Uni Of NSW, Oz
  12. References: <1gia4iINN5t1@iraul1.ira.uka.de> <1992Dec14.161245.24863@pony.Ingres.COM>
  13. Date: Tue, 15 Dec 1992 06:13:28 GMT
  14. Lines: 693
  15.  
  16. [followups to alt.sources.d]
  17.  
  18. prechelt@i41s18.ira.uka.de (Lutz Prechelt) writes...
  19. | I have a shell script (written myself) that works most of the time, 
  20. | but when the youngest processes do not have the highest PIDs of all
  21. | existing processes (which is possible, if a system runs long
  22. | enough and PIDs wrap around after about 30000 processes), 
  23. | it gets into trouble.
  24.  
  25. jonm@Ingres.COM (Don't Judge a book by your cover) writes:
  26. |     You could extend your current script to include a small C routine that
  27. | provides the process group information.  This will apply to all processes
  28. | that are children of another process.
  29. | main(argc, argv)
  30. | int argc;
  31. | char *argv[];
  32. | {
  33. |     exit getpgrp(atoi(argv[1]))
  34. | }
  35. | Where your first argument is the pid of the process you located in your 
  36. | first step.
  37. | Then let your killing fingers do the talking.
  38.  
  39. Um, why do this the hard way? I append a package for such purposes I use here.
  40. It's all scripts. It is a trivial exercise to modify the tkill script to match
  41. process names instead of process numbers. You will have to install the
  42. appropriate instance of ps_ppid.*.sh as ps_ppid.
  43.     - Cameron Simpson
  44.       cameron@cs.unsw.oz.au, DoD 0743
  45. --
  46. "The engine purrs beneath me with a purpose,
  47.  ready for the pleasure of my hand upon the throttle." - Peter Smith
  48.  
  49. #!/bin/sh
  50. #
  51. # Cut here and feed through /bin/sh.
  52. #
  53.  
  54. sed 's/^X//' > 'ps_bsd2ppid.pl' <<'EOF-ps_bsd2ppid.pl'
  55. X#!/usr/local/bin/perl
  56. X#
  57. X# Convert BSD ps lagx output to ps_ppid output.
  58. X# We produce
  59. X#    USER PID PPID TTY SZ RSS STAT TIME COMMAND
  60. X# separated by tabs.
  61. X#
  62. X
  63. X$"="\t";
  64. Xwhile (<>)
  65. X    { if ($. == 1)
  66. X    # replace heading
  67. X    { print "UID\tPID\tPPID\tTTY\tSZ\tRSS\tSTAT\tTIME\tCOMMAND\n";
  68. X      next;
  69. X    }
  70. X
  71. X#                 F      UID     PID     PPID   CP    PRI       NI       ADDR                SZ              RSS     STAT                    TTY   TIME         COMMAND
  72. X      if (@f=/^\s*\d+\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+\s+[- ]\d+\s*[- ]\d+\s[\s\da-f]{3}[\da-z]([\s\d]{4}\d)\s+(\d+)\s+([RTPDSIZ][W >][N< ])\s+(\S+\s*\d+:\d\d)\s+(.*\S)\s*$/o)
  73. X    { if ($f[6] =~ /(\S+)\s+(\d+:\d\d)/
  74. X       || $f[6] =~ /(\S*\D)(\d+:\d\d)/
  75. X       || $f[6] =~ /(.*)(\d+:\d\d)/)
  76. X        { @f=(@f[0,1,2],$1,@f[3,4,5],$2,@f[7]);
  77. X            print "@f\n";
  78. X        }
  79. X      else
  80. X      { print STDERR $_;
  81. X      }
  82. X    }
  83. X      elsif (/^\S/)
  84. X    { print STDERR $_;
  85. X    }
  86. X    }
  87. EOF-ps_bsd2ppid.pl
  88.  
  89. sed 's/^X//' > 'ps_bsdw2ppid.pl' <<'EOF-ps_bsdw2ppid.pl'
  90. X#!/usr/local/bin/perl
  91. X#
  92. X# Convert BSD ps lagx output to ps_ppid output.
  93. X# We produce
  94. X#    USER PID PPID TTY SZ RSS STAT TIME COMMAND
  95. X# separated by tabs.
  96. X#
  97. X
  98. X$"="\t";
  99. Xwhile (<>)
  100. X    { if ($. == 1)
  101. X    # replace heading
  102. X    { print "UID\tPID\tPPID\tTTY\tSZ\tRSS\tSTAT\tTIME\tCOMMAND\n";
  103. X      next;
  104. X    }
  105. X
  106. X#               F                    UID     PID     PPID   CP    PRI       NI       ADDR                   SZ      RSS    WCHAN  STAT                             TT   TIME         COMMAND
  107. X      if (@f=/^(\d{8}|\s*\d{1,7})\s*(\d+)\s+(\d+)\s+(\d+)\s+\d+\s+[- ]\d+\s*[- ]\d+\s[\s\da-f]{3}[\da-z]\s*(\d+)\s+(\d+)\s+\w*\s+([RTPDSIZ][W >][N< ][AS ][V ]?)\s+(\S+\s*\d+:\d\d)\s+(.*\S)\s*$/o)
  108. X    { shift @f;
  109. X      if ($f[6] =~ /(\S+)\s+(\d+:\d\d)/
  110. X       || $f[6] =~ /(\S*\D)(\d+:\d\d)/
  111. X       || $f[6] =~ /(.*)(\d+:\d\d)/)
  112. X        { @f=(@f[0,1,2],$1,@f[3,4,5],$2,@f[7]);
  113. X            print "@f\n";
  114. X        }
  115. X      else
  116. X      { print STDERR $_;
  117. X      }
  118. X    }
  119. X      elsif (/^\S/)
  120. X    { print STDERR $_;
  121. X    }
  122. X    }
  123. EOF-ps_bsdw2ppid.pl
  124.  
  125. sed 's/^X//' > 'ps_ppid.bsd.sh' <<'EOF-ps_ppid.bsd.sh'
  126. X#!/bin/sh
  127. X#
  128. X# Produce a ps listing containing nine fields:
  129. X#       USER PID PPID TTY SZ RSS STAT TIME COMMAND
  130. X# from a BSD-style ps command.
  131. X#
  132. X
  133. Xps lagx ${1+"$@"} | ps_bsd2ppid
  134. EOF-ps_ppid.bsd.sh
  135.  
  136. sed 's/^X//' > 'ps_ppid.bsdw.sh' <<'EOF-ps_ppid.bsdw.sh'
  137. X#!/bin/sh
  138. X#
  139. X# Produce a ps listing containing nine fields:
  140. X#       USER PID PPID TTY SZ RSS STAT TIME COMMAND
  141. X# from a BSD-style ps command with a WCHAN column.
  142. X#
  143. X
  144. Xps lagx ${1+"$@"} | ps_bsdw2ppid
  145. EOF-ps_ppid.bsdw.sh
  146.  
  147. sed 's/^X//' > 'ps_ppid.inetd.sh' <<'EOF-ps_ppid.inetd.sh'
  148. X#!/bin/sh
  149. X#
  150. X# Stub to run ps_ppid with useful PATH from inetd.
  151. X#
  152. X
  153. XPATH=/usr/local/bin:$PATH
  154. Xexport PATH
  155. Xexec /usr/local/bin/ps_ppid ${1+"$@"}
  156. EOF-ps_ppid.inetd.sh
  157.  
  158. sed 's/^X//' > 'ps_ppid.sysv.sh' <<'EOF-ps_ppid.sysv.sh'
  159. X#!/bin/sh
  160. X#
  161. X# Produce a ps listing containing nine fields:
  162. X#       USER PID PPID TTY SZ RSS STAT TIME COMMAND
  163. X# from a SYSV-style ps command.
  164. X#
  165. X
  166. Xps -elf ${1+"$@"} | ps_sysv2ppid
  167. EOF-ps_ppid.sysv.sh
  168.  
  169. sed 's/^X//' > 'ps_sysv2ppid.pl' <<'EOF-ps_sysv2ppid.pl'
  170. X#!/usr/local/bin/perl
  171. X#
  172. X# Convert SYSV ps -elf output to ps_ppid output.
  173. X# We produce
  174. X#    USER PID PPID TTY SZ RSS STAT TIME COMMAND
  175. X# separated by tabs.
  176. X#
  177. X
  178. Xwhile (<>)
  179. X    { if ($. == 1)
  180. X    # replace heading
  181. X    { print "UID\tPID\tPPID\tTTY\tSZ\tRSS\tSTAT\tTIME\tCOMMAND\n";
  182. X      next;
  183. X    }
  184. X
  185. X#            F           S            UID     PID     PPID   C     PRI       NI   P      SZ    RSS      WCHAN       STIME   TTY     TIME         COMD
  186. X      if (s/^[\da-f]{2} ([SRZTIX])\s*(\S+)\s+(\d+)\s+(\d+)\s+\d+\s*[ +]\d+\s+\d+\s\S+\s+(\d+):([ \d]{5})[ \da-f]{8} .{8}\s+(\S+)\s+(\d+:\d\d)\s+(.*)/\2\t\3\t\4\t\7\t\5\t\6\t\1\t\8\t\9/o)
  187. X    { print;
  188. X    }
  189. X      elsif (/^\S/)
  190. X    { print STDERR $_;
  191. X    }
  192. X    }
  193. EOF-ps_sysv2ppid.pl
  194.  
  195. sed 's/^X//' > 'pt.1' <<'EOF-pt.1'
  196. X.TH PT 1 Local
  197. X.SH NAME
  198. Xpt \- print process tree
  199. X.br
  200. Xrpt \- print remote process tree
  201. X.br
  202. Xtkill \- kill process tree
  203. X.br
  204. Xps_ppid \- print uid, pid, ppid, tty, cmd+args for use by pt
  205. X.br
  206. Xps_bsd2ppid \- convert Apollo ps lagx output into ps_ppid output
  207. X.br
  208. Xps_bsdw2ppid \- convert BSD ps lagx output into ps_ppid output
  209. X.br
  210. Xps_sysv2ppid \- convert SYSV ps -ef output into ps_ppid output
  211. X.SH SYNOPSIS
  212. X.B pt
  213. X.RB [ - ]
  214. X.RB [ -b ]
  215. X.RB [ -f ]
  216. X.RI [ subtree... ]
  217. X.RI [ secondary-ps_ppid-arguments ]
  218. X.br
  219. X.B rpt
  220. X.RB [ -b ]
  221. X.RB [ -f ]
  222. X.RI [ subtree... ]
  223. X.I hosts...
  224. X.br
  225. X.B tkill
  226. X.RB [ -v ]
  227. X.RB [ -\fIsignal\fB ]
  228. X.I subtree
  229. X.RI [ secondary-ps-arguments ]
  230. X.br
  231. X.B ps_ppid
  232. X.RI [ secondary-ps-arguments ]
  233. X.br
  234. X.B ps_bsd2ppid
  235. X.RI [ files... ]
  236. X.br
  237. X.B ps_bsdw2ppid
  238. X.RI [ files... ]
  239. X.br
  240. X.B ps_sysv2ppid
  241. X.RI [ files... ]
  242. X.SH DESCRIPTION
  243. XThese programs comprise a collection of filters
  244. Xfor producing process tree listings.
  245. X
  246. X.B pt
  247. Xprints an indented process listing
  248. Xreflecting the parent-child relationships
  249. Xof the process tree.
  250. XOutput consists of ten columns: 
  251. X.TP
  252. XUSER
  253. XEffective username.
  254. X.TP
  255. XUID
  256. XEffective user id.
  257. X.TP
  258. XPID
  259. XProcess id.
  260. X.TP
  261. XPPID
  262. XParent process id.
  263. X.TP
  264. XSZ
  265. XVirtual size of the process.
  266. X.TP
  267. XRSS
  268. XReal memory (resident set) size of the process.
  269. X.TP
  270. XTTY
  271. XControlling terminal.
  272. X.TP
  273. XSTAT
  274. XProcess state.
  275. X.TP
  276. XTIME
  277. XCPU time.
  278. X.TP
  279. XCOMMAND
  280. XProcess argument list.
  281. XThe COMMAND column is indented by two spaces for each depth of pedigree.
  282. X.P
  283. XAll columns are separated by white space,
  284. Xand except for COMMAND are guarrenteed to contains no white space,
  285. Xthus rending the list easy to parse.
  286. X.P
  287. XThe following arguments affect the listing:
  288. X.TP
  289. X.B \-
  290. XThis causes
  291. X.B pt
  292. Xto read a
  293. X.BR ps_ppid -style
  294. Xprocess listing from standard input rather than opening a pipe to
  295. X.B ps_ppid
  296. Xitself.
  297. X.TP
  298. X.B \-b
  299. XTake the basename of argument zero of the process.
  300. XThis often produces a much more readable listing.
  301. XIt is the default.
  302. X.TP
  303. X.B \-f
  304. XTake the full name of argument zero of the process.
  305. XThis produces a much more informative listing.
  306. X.TP
  307. X.I subtree
  308. XAn argument consisting entirely of digits is taken
  309. Xto be a process-id to be the root of the tree printed.
  310. XOnly descendants of this process will be printed.
  311. XNormally,
  312. X.B pt
  313. Xproduces the entire list for the current host.
  314. X.P
  315. XAny other arguments are passed to the internal invocation of
  316. X.B ps_ppid
  317. X(or ignored if the\ \fB\-\fR\ option is used).
  318. XSince
  319. X.B ps_ppid
  320. Xpasses these arguments in turn to the
  321. X.B ps
  322. Xcommand it is possible, for example,
  323. Xto take direct advantage of the remote capabilites of the Apollo ps, viz:
  324. X.[]
  325. Xpt //fuligin
  326. X.][
  327. X
  328. X.B rpt
  329. Xruns
  330. X.B pt
  331. Xwith a process listing obtains from a remote host.
  332. XIt takes the\ \fB\-b\fR, \fB-f\fR and
  333. X.I subtree
  334. Xarguments of
  335. X.B pt
  336. Xand passes them to
  337. X.BR pt .
  338. XFollowing arguments are taken to be references to hosts.
  339. XArguments of the form\ \fB//\fIhost\fR are taken to be Apollo hosts,
  340. Xand passed directly to
  341. X.BR pt .
  342. XOther arguments are presumed to be internet host names
  343. Xor internet numeric addresses\ (\fIn\fB.\fIn\fB.\fIn\fB.\fIn\fR),
  344. Xand a connection to that host's
  345. X.B ps_ppid
  346. Xport is made and the output passed to
  347. X.BR pt .
  348. X
  349. X.B tkill
  350. Xsends the specified
  351. X.I signal
  352. Xto the process in the tree whose root is
  353. X.IR subtree .
  354. XIf the
  355. X.B -v
  356. Xoption is supplied,
  357. Xthe generated kill command is printed just before execution.
  358. X.I subtree
  359. Xand any following arguments
  360. Xare passed to
  361. X.B pt
  362. Xinternally when generating the process list.
  363. X
  364. X.B ps_ppid
  365. Xgenerates nine column tab-separated output suitable for feeding to
  366. X.BR pt .
  367. XThese columns are:
  368. X.IR USER ,
  369. X.IR PID ,
  370. X.IR PPID ,
  371. X.IR TTY ,
  372. X.IR SZ ,
  373. X.IR RSS ,
  374. X.IR STAT ,
  375. X.IR TIME ,
  376. Xand
  377. X.IR COMMAND .
  378. XThe
  379. X.I USER
  380. Xcolumn is either a login name or a numeric uid.
  381. XAs this is accomplished by filtering the output of the local
  382. X.B ps
  383. Xcommand, any arguments supplied are passed to the ps command.
  384. X
  385. X.B ps_bsd2ppid
  386. Xis a filter which converts input of the same format
  387. Xas that output by the Apollo
  388. X.B "ps lagx"
  389. Xcommand into output as produced by the
  390. X.B ps_ppid
  391. Xcommand.
  392. X
  393. X.B ps_bsdw2ppid
  394. Xis a filter which converts input of the same format
  395. Xas that output by the BSD
  396. X.B "ps lagx"
  397. Xcommand into output as produced by the
  398. X.B ps_ppid
  399. Xcommand.
  400. XThe input format differs from that of the Apollo
  401. X.B ps
  402. Xcommand through the addition of the WCHAN column.
  403. X
  404. X.B ps_sysv2ppid
  405. Xis a filter which converts input of the same format
  406. Xas that output by the System\ V
  407. X.B "ps -elf"
  408. Xcommand into output as produced by the
  409. X.B ps_ppid
  410. Xcommand.
  411. X.SH BUGS
  412. XThere should a way to control the degree of indent produced by
  413. X.BR pt .
  414. X
  415. XThe various \fBps_\fItype\fB2ppid\fR filters can be confused
  416. Xif various columns of the ps listing input overflow,
  417. Xthus running into each other.
  418. XThis is more properly a bug in various vendors' ps commands,
  419. Xwhich should ensure at least one space between columns
  420. Xto keep them machine parsable.
  421. XTh filters at least recognise and accomodates the most common overlaps.
  422. X.SH AUTHOR
  423. XCameron Simpson
  424. X.SH SEE ALSO
  425. Xps(1), kill(1), tcpio(1)
  426. EOF-pt.1
  427.  
  428. sed 's/^X//' > 'pt.pl' <<'EOF-pt.pl'
  429. X#!/usr/local/bin/perl
  430. X#
  431. X# pt - print process tree
  432. X#
  433. X# Munges ps_ppid listing into indented process tree.
  434. X# We expect
  435. X#    USER PID PPID TTY SZ RSS STAT TIME COMMAND
  436. X# separated by tabs.
  437. X#    - Cameron Simpson, 27aug92
  438. X#
  439. X
  440. X($cmd=$0) =~ s:.*/::;
  441. X$usage="Usage: $cmd [-b] [-f] [-] [subtree...] [--] [psargs]
  442. X    -b    Take the basename of the command (default).
  443. X    -f    Take the full name of the command.
  444. X    -    Read ps_ppid input from stdin rather than running ps_ppid.
  445. X    subtree    Print process tree only from the specified pid downward.
  446. X    psargs    Passed to ps_ppid.
  447. X";
  448. X
  449. X$badopts=0;
  450. X$use_stdin=0;
  451. X$basenames=1;
  452. X@subtree=();
  453. Xwhile ($#ARGV >= $[)
  454. X    { $_=shift;
  455. X      if ($_ eq '-b')    { $basenames=1; }
  456. X      if ($_ eq '-f')    { $basenames=0; }
  457. X      elsif ($_ eq '-')    { $use_stdin=1; }
  458. X      elsif ($_ eq '--')    { last; }
  459. X      elsif ($_ eq '-?')    { $badopts=1; }
  460. X      elsif (/^\d+$/)    { push(@subtree,$_+0); }
  461. X      else            { unshift(@ARGV,$_); last; }
  462. X    }
  463. X
  464. Xif ($badopts)
  465. X    { print STDERR $usage;
  466. X      exit 2;
  467. X    }
  468. X
  469. X$use_stdin || open(STDIN,"ps_ppid @ARGV|")
  470. X       || die "can't get ps_ppid output: $!\n";
  471. X
  472. X$xit=0;
  473. X$nprocs=0;
  474. X@pids=();
  475. X@info=();
  476. X@pid=();    undef %ndx;    # inverse of @pid
  477. X@ppid=();
  478. X@child=();
  479. X@sibling=();
  480. X
  481. Xundef %printed;
  482. X
  483. X$first=1;
  484. Xwhile (<STDIN>)
  485. X    { @fields=split("\t",$_,9);
  486. X      if ($#fields != 8)
  487. X        { print STDERR $_;
  488. X          next;
  489. X        }
  490. X
  491. X      if ($first)    # swallow title line
  492. X        { $first=0;
  493. X          next;
  494. X        }
  495. X
  496. X      chop($argv=pop @fields);
  497. X      for (@fields)
  498. X        { s/^\s+//o;
  499. X          s/\s+$//o;
  500. X          s/\s/./g;
  501. X        }
  502. X      push(@fields,$argv);
  503. X
  504. X      ($uid,$pid,$ppid,$tty,$sz,$rss,$stat,$time,$argv)=@fields;
  505. X
  506. X      if ($uid =~ /^\d/o)
  507. X        { $user=&namof($uid);
  508. X        }
  509. X      else
  510. X      { $user=$uid;
  511. X        $uid=&uidof($user);
  512. X      }
  513. X
  514. X      shift @fields;
  515. X      unshift(@fields,$user,$uid);
  516. X
  517. X      # all info
  518. X      push(@info,join("\t",@fields));
  519. X
  520. X      # topology info
  521. X      $ndx{$pid}=$nprocs++;
  522. X      push(@pids,$pid+0);
  523. X      push(@pid,$pid+0);
  524. X      push(@ppid,$ppid+0);
  525. X      push(@child,-1);
  526. X      push(@sibling,-1);
  527. X    }
  528. X
  529. Xclose(STDIN);
  530. X
  531. X@pids=sort { ($a+0) <=> ($b+0); } @pids;
  532. Xfor $pid (@pids)
  533. X    { $npid=$ndx{$pid};
  534. X      $nppid=$ndx{$ppid[$npid]};
  535. X      $sibling[$npid]=$child[$nppid];
  536. X      $child[$nppid]=$pid;
  537. X    }
  538. X
  539. Xif ($#subtree >= $[)
  540. X    { for $subtree (@subtree)
  541. X        { if (!defined($ndx{$subtree}))
  542. X            { print STDERR "$cmd: no subtree for pid $subtree\n";
  543. X                $xit=1;
  544. X            }
  545. X            else
  546. X            { &tprint($subtree,0);
  547. X            }
  548. X        }
  549. X    }
  550. Xelse
  551. X{ for (@pids)
  552. X    { &tprint($_,0);
  553. X    }
  554. X}
  555. X
  556. Xexit $xit;
  557. X
  558. Xsub tprint    # (pid,level)
  559. X    { local($pid,$level)=@_;
  560. X
  561. X      return if $pid < 0 || $printed{$pid};
  562. X
  563. X      $printed{$pid}=1;
  564. X
  565. X      local($n)=$ndx{$pid};
  566. X      local($user,$uid,$pid,$ppid,$tty,$sz,$rss,$stat,$time,$argv)=split("\t",$info[$n]);
  567. X      $uid+=0;
  568. X
  569. X      if ($basenames)
  570. X        { $argv =~ s:^\S+/([^/]):\1:; }
  571. X
  572. X      if (!$had_tprint)
  573. X        { print "USER     UID   PID  PPID    SZ  RSS TTY    STAT TIME COMMAND\n";
  574. X          $had_tprint=1;
  575. X        }
  576. X
  577. X      local($_);
  578. X
  579. X                      $_="$user ";
  580. X      &padto($_,12-length($uid));    $_.="$uid ";
  581. X      &padto($_,18-length($pid));    $_.="$pid ";
  582. X      &padto($_,24-length($ppid));    $_.="$ppid ";
  583. X      &padto($_,30-length($sz));    $_.="$sz ";
  584. X      &padto($_,35-length($rss));    $_.="$rss $tty ";
  585. X      &padto($_,43);        $_.="$stat ";
  586. X      &padto($_,52-length($time));    $_.="$time ";
  587. X      &padto($_,53+$level*2);    $_.=$argv;
  588. X
  589. X      print $_, "\n";
  590. X
  591. X      &subtprint($child[$n],$level+1);
  592. X    }
  593. X
  594. Xsub padto    # ($str,$len) -> padded str
  595. X    { if (length($_[0]) < $_[1])
  596. X        { $_[0].=(' ' x ($_[1]-length($_[0])));
  597. X        }
  598. X
  599. X      $_[0];
  600. X    }
  601. X
  602. Xsub subtprint
  603. X    { local($pid,$level)=@_;
  604. X
  605. X      return if $pid < 0 || $subprinted{$pid};
  606. X
  607. X      $subprinted{$pid}=1;
  608. X
  609. X      &subtprint($sibling[$ndx{$pid}],$level);
  610. X      &tprint($pid,$level);
  611. X    }
  612. X
  613. Xsub uidof
  614. X    { if (!defined($uidof{$_[0]}))
  615. X        { &saveuser($_[0],'?',getpwnam($_[0]));
  616. X        }
  617. X
  618. X      $uidof{$_[0]};
  619. X    }
  620. X
  621. Xsub namof
  622. X    { if (!defined($namof{$_[0]}))
  623. X        { &saveuser('?',$_[0],getpwuid($_[0]+0));
  624. X        }
  625. X
  626. X      $namof{$_[0]+0};
  627. X    }
  628. X
  629. Xsub saveuser
  630. X    { local($defnam,$defuid,$nam,$pwd,$uid,@etc)=@_;
  631. X
  632. X      $nam=(defined($nam) ? $nam : $defnam);
  633. X      $uid=(defined($uid) ? $uid : $defuid);
  634. X
  635. X      $uidof{$nam}=$uid;
  636. X      $namof{$uid}=$nam;
  637. X    }
  638. EOF-pt.pl
  639.  
  640. sed 's/^X//' > 'rpt.sh' <<'EOF-rpt.sh'
  641. X#!/bin/sh
  642. X#
  643. X# Do remote ps.
  644. X#
  645. X# Usage: rps [pt-arguments] machines...
  646. X#
  647. X
  648. Xptargs=
  649. Xwhile :
  650. Xdo
  651. X    case $1 in
  652. X    -[bf])    ptargs="$ptargs $1" ;;
  653. X    *.*)    break ;;        # hack for numeric addresses
  654. X    [0-9]*)    ptargs="$ptargs $1" ;;
  655. X    *)    break ;;
  656. X    esac
  657. X    shift
  658. Xdone
  659. X
  660. Xfor machine
  661. Xdo
  662. X    case $# in 1) ;; *) echo "$machine ..." ;; esac
  663. X    case $machine in
  664. X    # apollo direct
  665. X    //*)    pt $ptargs "$machine" ;;
  666. X    # use the ps_ppid internet port
  667. X    *)    tcpio -i "$machine" ps_ppid | pt - $ptargs ;;
  668. X    esac
  669. Xdone
  670. EOF-rpt.sh
  671.  
  672. sed 's/^X//' > 'tkill.sh' <<'EOF-tkill.sh'
  673. X#!/bin/sh
  674. X#
  675. X# Kill a process tree.
  676. X#
  677. X
  678. Xcmd=`basename "$0"`
  679. Xusage="Usage: $cmd [-v] [-signal] subtree [ptargs]"
  680. X
  681. Xbadopts=
  682. Xsig=
  683. Xv=
  684. Xcase $1 in
  685. X    -v)    v=1; shift ;;
  686. Xesac
  687. Xcase $1 in
  688. X    -?*)    sig=$1; shift ;;
  689. Xesac
  690. Xcase $1 in
  691. X    [0-9]*)    subtree=$1; shift ;;
  692. X    *)        echo "$cmd: missing subtree" >&2
  693. X        badopts=1
  694. X        ;;
  695. Xesac
  696. X
  697. X[ $badopts ] && { echo "$usage" >&2; exit 2; }
  698. X
  699. Xpids=`pt "$subtree" ${1+"$@"} | awk '$3 ~ /^[0-9][0-9]*$/ { print $3; }'`
  700. X
  701. X[ $v ] && set -x
  702. Xexec kill $sig $pids
  703. EOF-tkill.sh
  704.  
  705. exit 0
  706.