shithub: front

Download patch

ref: 493bac79b63f1949a29aeec8270fab4a599a6ee3
parent: 5969b872bb244f6f9083fd06779a50cf68078455
author: qwx <qwx@sciops.net>
date: Wed Oct 30 19:43:47 EDT 2024

pstree: reimplement in awk, optionally restrict to a given process

--- /dev/null
+++ b/rc/bin/pstree
@@ -1,0 +1,49 @@
+#!/bin/rc
+p=0
+if(! ~ $#* 0)
+	p=$1
+cd /proc || exit
+ls -d [0-9]* | sort -n | awk -v 'this='^$p '
+function cat(f,	v){
+	getline v < f
+	close(f)
+	return v
+}
+BEGIN{
+	OFS="\t"
+}
+{
+	s = cat($1"/args")
+	if(s == ""){
+		s = cat($1"/status")
+		s = substr(s, 1, 27)
+		gsub(" *", "", s)
+	}
+	p = int(cat($1"/ppid"))
+	child[p,++nchild[p]] = $1
+	proc[$1] = s
+	ppid[$1] = p
+	pid[NR] = $1
+}
+function out(p, sep, k,	m,	i, n, c, s){
+	n = nchild[p]
+	if(p != 0 && proc[p] != "")
+		printf "%-11s%s%s%s\n", p, sep, k, proc[p]
+	s = m > 0 ? "│" : " "
+	k = "├"
+	for(i=1; i<=n; i++){
+		c = child[p,i]
+		if(i == n)
+			k = "└"
+		out(c, sep s, k, n - i)
+	}
+}
+END{
+	for(i=1; i<=length(pid); i++){
+		p = pid[i]
+		if(!(ppid[p] in proc) && ppid[p] != 0)
+			child[0,++nchild[0]] = p
+	}
+	out(this, "", "", 0)
+}
+'
--- a/sys/man/1/ps
+++ b/sys/man/1/ps
@@ -16,6 +16,9 @@
 ]
 .PP
 .B pstree
+[
+.I pid
+]
 .SH DESCRIPTION
 .I Ps
 prints information about processes.
@@ -113,6 +116,9 @@
 the first column being the process id and second column
 the program name and arguments indented and prefixed with
 line drawing runes to reflect the nesting in the hierarchy.
+It optionally accepts an argument
+.I pid
+to only print a tree for the corresponding process.
 .SH FILES
 .B /proc/*/status
 .SH SOURCE
@@ -120,7 +126,7 @@
 .br
 .B /rc/bin/psu
 .br
-.B /sys/src/cmd/pstree.c
+.B /rc/bin/pstree
 .SH "SEE ALSO"
 .IR acid (1),
 .IR db (1),
--- a/sys/src/cmd/pstree.c
+++ /dev/null
@@ -1,184 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-typedef struct Proc Proc;
-struct Proc {
-	int pid;
-	Proc *first, *parent, *next;
-	Proc *hash;
-};
-
-Proc	*hash[1024];
-Rune	buf[512];
-Biobuf	bout;
-
-Proc *
-getproc(int pid)
-{
-	Proc *p;
-
-	for(p = hash[pid % nelem(hash)]; p; p = p->hash)
-		if(p->pid == pid)
-			return p;
-	return nil;
-}
-
-void
-addproc(int pid)
-{
-	Proc *p;
-	
-	p = mallocz(sizeof(*p), 1);
-	if(p == nil)
-		sysfatal("malloc: %r");
-	p->pid = pid;
-	p->hash = hash[pid % nelem(hash)];
-	hash[pid % nelem(hash)] = p;
-}
-
-int
-theppid(int pid)
-{
-	char b[128];
-	int fd, ppid;
-	
-	ppid = 0;
-	snprint(b, sizeof(b), "%d/ppid", pid);
-	fd = open(b, OREAD);
-	if(fd >= 0){
-		memset(b, 0, sizeof b);
-		if(read(fd, b, sizeof b-1) >= 0){
-			ppid = atoi(b);
-			if(ppid < 0)
-				ppid = 0;
-		}
-		close(fd);
-	}
-	return ppid;
-}
-
-void
-addppid(int pid)
-{
-	Proc *p, *par, **l;
-	
-	p = getproc(pid);
-	par = getproc(theppid(pid));
-	if(par == nil)
-		par = getproc(0);
-	p->parent = par;
-	for(l = &par->first; *l; l = &((*l)->next))
-		if((*l)->pid > pid)
-			break;
-	p->next = *l;
-	*l = p;
-}
-
-void
-addprocs(void)
-{
-	int fd, rc, i;
-	Dir *d;
-	
-	fd = open(".", OREAD);
-	if(fd < 0)
-		sysfatal("open: %r");
-	rc = dirreadall(fd, &d);
-	if(rc < 0)
-		sysfatal("dirreadall: %r");
-	close(fd);
-	for(i = 0; i < rc; i++)
-		if(d[i].mode & DMDIR)
-			addproc(atoi(d[i].name));
-	for(i = 0; i < rc; i++)
-		if(d[i].mode & DMDIR)
-			addppid(atoi(d[i].name));
-	free(d);
-}
-
-int
-readout(char *file)
-{
-	int fd, rc, i, n;
-	char b[512];
-
-	fd = open(file, OREAD);
-	if(fd < 0)
-		return -1;
-	n = 0;
-	while((rc = read(fd, b, sizeof b)) > 0){
-		for(i=0; i<rc; i++)
-			if(b[i] == '\n')
-				b[i] = ' ';
-		n += Bwrite(&bout, b, rc);
-	}
-	close(fd);
-	return n;
-}
-
-void
-printargs(int pid)
-{
-	char b[128], *p;
-	int fd;
-
-	snprint(b, sizeof(b), "%d/args", pid);
-	if(readout(b) > 0)
-		return;
-	snprint(b, sizeof(b), "%d/status", pid);
-	fd = open(b, OREAD);
-	if(fd >= 0){
-		memset(b, 0, sizeof b);
-		if(read(fd, b, 27) > 0){
-			p = b + strlen(b);
-			while(p > b && p[-1] == ' ')
-				*--p = 0;
-			Bprint(&bout, "%s", b);
-		}
-		close(fd);
-	}
-}
-
-void
-descend(Proc *p, Rune *r)
-{
-	Rune last;
-	Proc *q;
-	
-	last = *--r;
-	*r = last == L' ' ? L'└' : L'├';
-	if(p->pid != 0){
-		Bprint(&bout, "%-11d %S", p->pid, buf);
-		printargs(p->pid);
-		Bprint(&bout, "\n");
-	}
-	*r = last;
-	*++r = L'│';
-	for(q = p->first; q; q = q->next) {
-		if(q->next == nil)
-			*r = L' ';
-		descend(q, r + 1);
-	}
-	*r = 0;
-}
-
-void
-printprocs(void)
-{
-	descend(getproc(0), buf);
-}
-
-void
-main()
-{
-	Binit(&bout, 1, OWRITE);
-	if(chdir("/proc")==-1)
-		sysfatal("chdir: %r");
-
-	addproc(0);
-	addprocs();
-	printprocs();
-
-	exits(0);
-}
--