aboutsummaryrefslogtreecommitdiff
path: root/src/pidlist.c
blob: 1dc5893cfafc0a305df32062d671027a46fc4206 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* This file is part of genrc
Copyryght (C) 2018 Sergey Poznyakoff
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
*/
#include "genrc.h"

void *
x2nrealloc(void *p, size_t *pn, size_t s)
{
	size_t n = *pn;
  
	if (!p) {
		if (!n) {
			/* The approximate size to use for initial small
			   allocation requests, when the invoking code
			   specifies an old size of zero.  64 bytes is
			   the largest "small" request for the
			   GNU C library malloc.  */
			enum { DEFAULT_MXFAST = 64 };

			n = DEFAULT_MXFAST / s;
			n += !n;
		}
	} else {
		/* Set N = ceil (1.5 * N) so that progress is made if N == 1.
		   Check for overflow, so that N * S stays in size_t range.
		   The check is slightly conservative, but an exact check isn't
		   worth the trouble.  */
		if ((size_t) -1 / 3 * 2 / s <= n)
			grecs_alloc_die();
		n += (n + 1) / 2;
	}

	*pn = n;
	return grecs_realloc(p, n * s);
}

void
pidlist_init(PIDLIST *plist)
{
	plist->pidv = NULL;
	plist->pidc = 0;
	plist->pidn = 0;
}

void
pidlist_free(PIDLIST *plist)
{
	free(plist->pidv);
}

void
pidlist_clear(PIDLIST *plist)
{
	plist->pidc = 0;
}

void
pidlist_add(PIDLIST *plist, pid_t p)
{
	if (p <= 0)
		return;
	if (plist->pidc == plist->pidn) {
		plist->pidv = x2nrealloc(plist->pidv, &plist->pidn,
					 sizeof(plist->pidv[0]));
	}
	plist->pidv[plist->pidc++] = p;
}

ssize_t
pidlist_index(PIDLIST *plist, pid_t p)
{
	size_t i;
	for (i = 0; i < plist->pidc; i++) {
		if (plist->pidv[i] == p)
			return i;
	}
	return -1;
}

int
pidlist_member(PIDLIST *plist, pid_t p)
{
	return pidlist_index(plist, p) != -1;
}

int
pidlist_remove(PIDLIST *plist, size_t i)
{
	if (i == -1)
		return 0;

	if (i < plist->pidc - 1) {
		memmove(plist->pidv + i, plist->pidv + i + 1,
			(plist->pidc - i - 1) * sizeof(plist->pidv[0]));
	}
	plist->pidc--;
	return 1;
}

void
pidlist_kill(PIDLIST *plist, int sig)
{
	size_t i;

	for (i = 0; i < plist->pidc; i++) {
		if (kill(plist->pidv[i], sig)) {
			if (errno != ESRCH)
				system_error(errno, "kill %lu",
					     (unsigned long) plist->pidv[i]);
		}
	}
}

int
pid_is_running(pid_t pid)
{
	if (kill(pid, 0)) {
		if (errno == ESRCH)
			return 0;
		system_error(errno, "kill %lu", (unsigned long)pid);
		exit(1);
	}
	return 1;
}

Return to:

Send suggestions and report system problems to the System administrator.