xref: /plan9-contrib/sys/src/ape/lib/ap/plan9/_exit.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1 #include "lib.h"
2 #include "sys9.h"
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 
7 
8 int _finishing = 0;
9 int _sessleader = 0;
10 
11 #define CPIDMAX		100	/* for keeping track of child pids */
12 static int cpids[CPIDMAX+1];
13 static int ncpid = 0;
14 static char exitstatus[ERRLEN];
15 
16 static void killcpids(int);
17 
18 void
19 _exit(int status)
20 {
21 	_finish(status, 0);
22 }
23 
24 void
25 _finish(int status, char *term)
26 {
27 	int i, nalive;
28 	char *cp;
29 
30 	if(_finishing)
31 		_EXITS(exitstatus);
32 	_finishing = 1;
33 	if(status){
34 		cp = _ultoa(exitstatus, status & 0xFF);
35 		*cp = 0;
36 	}else if(term){
37 		strncpy(exitstatus, term, ERRLEN);
38 	}
39 	if(_sessleader) {
40 		for(i = 0, nalive=0; i < ncpid; i++)
41 			if(cpids[i])
42 				nalive++;
43 		if(nalive)
44 			killcpids(nalive);
45 	}
46 	_EXITS(exitstatus);
47 }
48 
49 /*
50  * register a child pid; will be hup'd on exit or termination
51  * if pid < 0, just clear the table (done on fork)
52  */
53 
54 void
55 _newcpid(int pid)
56 {
57 	int i;
58 
59 	if(pid < 0){
60 		ncpid = 0;
61 	}else{
62 		for(i = 0; i < ncpid; i++)
63 			if(cpids[i] == 0) {
64 				cpids[i] = pid;
65 				return;
66 			}
67 		if(ncpid < CPIDMAX)
68 			cpids[ncpid++] = pid;
69 	}
70 }
71 
72 void
73 _delcpid(int pid)
74 {
75 	int i;
76 
77 	for(i = 0; i < ncpid; i++)
78 		if(cpids[i] == pid) {
79 			cpids[i] = 0;
80 			if(i == ncpid-1)
81 				ncpid--;
82 			return;
83 		}
84 }
85 
86 /*
87  * What a pain this is.  Children might not die because
88  * we're still here.  So fork to get an independent
89  * child, and use it to kill everyone
90  */
91 static void
92 killcpids(int nalive)
93 {
94 	int i, p, fd, niters, wpid;
95 	Waitmsg w;
96 	char buf[100];
97 	char *cp;
98 
99 	for(i = 0; i<OPEN_MAX; i++)
100 		_CLOSE(i);
101 	cpids[ncpid++] = getpid();	/* kill ourselves, too */
102 	nalive++;
103 	i = _RFORK(FORKPCS|FORKFDG|FORKNOW);
104 	if(i > 0)
105 		return;
106 
107 	for(niters=0; nalive > 0 && niters < 5; niters++){
108 		for(i = 0; i < ncpid; i++){
109 			if(!cpids[i])
110 				continue;
111 			strcpy(buf, "/proc/");
112 			cp = _ultoa(buf+6, cpids[i]);
113 			strcpy(cp, "/note");
114 			fd = _OPEN(buf, 1);
115 			if(fd >= 0){
116 				if(_WRITE(fd, "hangup", 6) < 0){
117 					cpids[i] = 0;
118 					nalive--;
119 				}
120 				_CLOSE(fd);
121 			}else{
122 				cpids[i] = 0;
123 				nalive--;
124 			}
125 		}
126 	}
127 }
128 
129 /* emulate: return p+sprintf(p, "%uld", v) */
130 #define IDIGIT 15
131 char *
132 _ultoa(char *p, unsigned long v)
133 {
134 	char s[IDIGIT];
135 	int n, i;
136 
137 	s[IDIGIT-1] = 0;
138 	for(i = IDIGIT-2; i; i--){
139 		n = v % 10;
140 		s[i] = n + '0';
141 		v = v / 10;
142 		if(v == 0)
143 			break;
144 	}
145 	strcpy(p, s+i);
146 	return p + (IDIGIT-1-i);
147 }
148