12736Sdfr/*
22736Sdfr * Copyright (c) 1994 Adam Glass
32736Sdfr * All rights reserved.
42736Sdfr *
52736Sdfr * Redistribution and use in source and binary forms, with or without
62736Sdfr * modification, are permitted provided that the following conditions
72736Sdfr * are met:
82736Sdfr * 1. Redistributions of source code must retain the above copyright
92736Sdfr *    notice, this list of conditions and the following disclaimer.
102736Sdfr * 2. Redistributions in binary form must reproduce the above copyright
112736Sdfr *    notice, this list of conditions and the following disclaimer in the
122736Sdfr *    documentation and/or other materials provided with the distribution.
132736Sdfr * 3. All advertising materials mentioning features or use of this software
142736Sdfr *    must display the following acknowledgement:
152736Sdfr *	This product includes software developed by Adam Glass.
162736Sdfr * 4. The name of the Author may not be used to endorse or promote products
172736Sdfr *    derived from this software without specific prior written permission.
182736Sdfr *
192736Sdfr * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND
202736Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
212736Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
222736Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL Adam Glass BE LIABLE
232736Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
242736Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
252736Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
262736Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
272736Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
282736Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
292736Sdfr * SUCH DAMAGE.
30174891Sedwin *
312736Sdfr */
322736Sdfr
3399112Sobrien#include <sys/cdefs.h>
3499112Sobrien__FBSDID("$FreeBSD$");
3527420Scharnier
36174891Sedwin#include <sys/param.h>
37174891Sedwin#define _KERNEL
38174750Sedwin#include <sys/sem.h>
39174750Sedwin#include <sys/shm.h>
40174891Sedwin#include <sys/msg.h>
41174891Sedwin#undef _KERNEL
42174750Sedwin
4327420Scharnier#include <ctype.h>
4427420Scharnier#include <err.h>
45174891Sedwin#include <grp.h>
46174891Sedwin#include <kvm.h>
472736Sdfr#include <stdio.h>
482736Sdfr#include <stdlib.h>
492736Sdfr#include <unistd.h>
502736Sdfr
51174891Sedwin#include "ipc.h"
522736Sdfr
53174891Sedwinint	signaled;
54174891Sedwinint	errflg;
55174891Sedwinint	rmverbose = 0;
562736Sdfr
57174891Sedwinvoid	usage(void);
5887285Sdwmalone
59174891Sedwinint	msgrm(key_t, int);
60174891Sedwinint	shmrm(key_t, int);
61174891Sedwinint	semrm(key_t, int);
62174891Sedwinvoid	not_configured(int);
63174891Sedwin
64174750Sedwinvoid
65174750Sedwinusage(void)
662736Sdfr{
67174750Sedwin
68174750Sedwin	fprintf(stderr,
69174891Sedwin	    "usage: ipcrm [-W] [-v[v]]\n"
70174891Sedwin	    "             [-q msqid] [-m shmid] [-s semid]\n"
71174750Sedwin	    "             [-Q msgkey] [-M shmkey] [-S semkey] ...\n");
722736Sdfr	exit(1);
732736Sdfr}
742736Sdfr
75174750Sedwinint
76174750Sedwinmsgrm(key_t key, int id)
772736Sdfr{
78174750Sedwin
79174891Sedwin	if (key == -1 || id == -1) {
80174891Sedwin		struct msqid_kernel *kxmsqids;
81174891Sedwin		size_t kxmsqids_len;
82174891Sedwin		int num;
83174891Sedwin
84174891Sedwin		kget(X_MSGINFO, &msginfo, sizeof(msginfo));
85174891Sedwin		kxmsqids_len = sizeof(struct msqid_kernel) * msginfo.msgmni;
86174891Sedwin		kxmsqids = malloc(kxmsqids_len);
87174891Sedwin		kget(X_MSQIDS, kxmsqids, kxmsqids_len);
88174891Sedwin		num = msginfo.msgmni;
89174891Sedwin		while (num-- && !signaled)
90174891Sedwin			if (kxmsqids[num].u.msg_qbytes != 0) {
91174891Sedwin				id = IXSEQ_TO_IPCID(num,
92174891Sedwin					kxmsqids[num].u.msg_perm);
93174891Sedwin				if (msgctl(id, IPC_RMID, NULL) < 0) {
94174891Sedwin					if (rmverbose > 1)
95174891Sedwin						warn("msqid(%d): ", id);
96174891Sedwin					errflg++;
97174891Sedwin				} else
98174891Sedwin					if (rmverbose)
99174891Sedwin						printf(
100174891Sedwin						    "Removed %s %d\n",
101174891Sedwin						    IPC_TO_STRING('Q'),
102174891Sedwin						    id);
103174891Sedwin			}
104174891Sedwin		return signaled ? -1 : 0;       /* errors maybe handled above */
105174891Sedwin	}
106174891Sedwin
107174750Sedwin	if (key) {
108174750Sedwin		id = msgget(key, 0);
109174750Sedwin		if (id == -1)
110174750Sedwin			return -1;
111174750Sedwin	}
112174891Sedwin
113174750Sedwin	return msgctl(id, IPC_RMID, NULL);
1142736Sdfr}
1152736Sdfr
116174750Sedwinint
117174750Sedwinshmrm(key_t key, int id)
1182736Sdfr{
119174750Sedwin
120174891Sedwin	if (key == -1 || id == -1) {
121174891Sedwin		struct shmid_kernel *kxshmids;
122174891Sedwin		size_t kxshmids_len;
123174891Sedwin		int num;
124174891Sedwin
125174891Sedwin		kget(X_SHMINFO, &shminfo, sizeof(shminfo));
126174891Sedwin		kxshmids_len = sizeof(struct shmid_kernel) * shminfo.shmmni;
127174891Sedwin		kxshmids = malloc(kxshmids_len);
128174891Sedwin		kget(X_SHMSEGS, kxshmids, kxshmids_len);
129174891Sedwin		num = shminfo.shmmni;
130174891Sedwin		while (num-- && !signaled)
131174891Sedwin			if (kxshmids[num].u.shm_perm.mode & 0x0800) {
132174891Sedwin				id = IXSEQ_TO_IPCID(num,
133174891Sedwin					kxshmids[num].u.shm_perm);
134174891Sedwin				if (shmctl(id, IPC_RMID, NULL) < 0) {
135174891Sedwin					if (rmverbose > 1)
136174891Sedwin						warn("shmid(%d): ", id);
137174891Sedwin					errflg++;
138174891Sedwin				} else
139174891Sedwin					if (rmverbose)
140174891Sedwin						printf(
141174891Sedwin						    "Removed %s %d\n",
142174891Sedwin						    IPC_TO_STRING('M'),
143174891Sedwin						    id);
144174891Sedwin			}
145174891Sedwin		return signaled ? -1 : 0;       /* errors maybe handled above */
146174891Sedwin	}
147174891Sedwin
148174750Sedwin	if (key) {
149174750Sedwin		id = shmget(key, 0, 0);
150174750Sedwin		if (id == -1)
151174750Sedwin			return -1;
152174750Sedwin	}
153174891Sedwin
154174750Sedwin	return shmctl(id, IPC_RMID, NULL);
1552736Sdfr}
1562736Sdfr
157174750Sedwinint
158174750Sedwinsemrm(key_t key, int id)
1592736Sdfr{
160174750Sedwin	union semun arg;
1612736Sdfr
162174891Sedwin	if (key == -1 || id == -1) {
163174891Sedwin		struct semid_kernel *kxsema;
164174891Sedwin		size_t kxsema_len;
165174891Sedwin		int num;
166174891Sedwin
167174891Sedwin		kget(X_SEMINFO, &seminfo, sizeof(seminfo));
168174891Sedwin		kxsema_len = sizeof(struct semid_kernel) * seminfo.semmni;
169174891Sedwin		kxsema = malloc(kxsema_len);
170174891Sedwin		kget(X_SEMA, kxsema, kxsema_len);
171174891Sedwin		num = seminfo.semmni;
172174891Sedwin		while (num-- && !signaled)
173174891Sedwin			if ((kxsema[num].u.sem_perm.mode & SEM_ALLOC) != 0) {
174174891Sedwin				id = IXSEQ_TO_IPCID(num,
175174891Sedwin					kxsema[num].u.sem_perm);
176174891Sedwin				if (semctl(id, IPC_RMID, NULL) < 0) {
177174891Sedwin					if (rmverbose > 1)
178174891Sedwin						warn("semid(%d): ", id);
179174891Sedwin					errflg++;
180174891Sedwin				} else
181174891Sedwin					if (rmverbose)
182174891Sedwin						printf(
183174891Sedwin						    "Removed %s %d\n",
184174891Sedwin						    IPC_TO_STRING('S'),
185174891Sedwin						    id);
186174891Sedwin			}
187174891Sedwin		return signaled ? -1 : 0;       /* errors maybe handled above */
188174891Sedwin	}
189174891Sedwin
190174750Sedwin	if (key) {
191174750Sedwin		id = semget(key, 0, 0);
192174750Sedwin		if (id == -1)
193174750Sedwin			return -1;
194174750Sedwin	}
195174891Sedwin
196174750Sedwin	return semctl(id, 0, IPC_RMID, arg);
1972736Sdfr}
1982736Sdfr
199174750Sedwinvoid
200174750Sedwinnot_configured(int signo __unused)
2012736Sdfr{
202174750Sedwin
203174750Sedwin	signaled++;
2042736Sdfr}
2058874Srgrimes
206174750Sedwinint
207174750Sedwinmain(int argc, char *argv[])
2082736Sdfr{
209174891Sedwin	int c, result, target_id;
210174750Sedwin	key_t target_key;
2112736Sdfr
212174891Sedwin	while ((c = getopt(argc, argv, "q:m:s:Q:M:S:vWy")) != -1) {
213174891Sedwin
214174891Sedwin		signaled = 0;
215174891Sedwin		switch (c) {
216174891Sedwin		case 'v':
217174891Sedwin			rmverbose++;
218174891Sedwin			break;
219174891Sedwin		case 'y':
220174891Sedwin			use_sysctl = 0;
221174891Sedwin			break;
222174891Sedwin		}
223174891Sedwin	}
224174891Sedwin
225174891Sedwin	optind = 1;
226174750Sedwin	errflg = 0;
227174750Sedwin	signal(SIGSYS, not_configured);
228174891Sedwin	while ((c = getopt(argc, argv, "q:m:s:Q:M:S:vWy")) != -1) {
2292736Sdfr
230174750Sedwin		signaled = 0;
231174750Sedwin		switch (c) {
232174750Sedwin		case 'q':
233174750Sedwin		case 'm':
234174750Sedwin		case 's':
235174750Sedwin			target_id = atoi(optarg);
236174750Sedwin			if (c == 'q')
237174750Sedwin				result = msgrm(0, target_id);
238174750Sedwin			else if (c == 'm')
239174750Sedwin				result = shmrm(0, target_id);
240174750Sedwin			else
241174750Sedwin				result = semrm(0, target_id);
242174750Sedwin			if (result < 0) {
243174750Sedwin				errflg++;
244174750Sedwin				if (!signaled)
245174750Sedwin					warn("%sid(%d): ",
246174750Sedwin					    IPC_TO_STR(toupper(c)), target_id);
247174750Sedwin				else
248174750Sedwin					warnx(
249174750Sedwin					    "%ss are not configured "
250174750Sedwin					    "in the running kernel",
251174750Sedwin					    IPC_TO_STRING(toupper(c)));
252174750Sedwin			}
253174750Sedwin			break;
254174750Sedwin		case 'Q':
255174750Sedwin		case 'M':
256174750Sedwin		case 'S':
257174750Sedwin			target_key = atol(optarg);
258174750Sedwin			if (target_key == IPC_PRIVATE) {
259174750Sedwin				warnx("can't remove private %ss",
260174750Sedwin				    IPC_TO_STRING(c));
261174750Sedwin				continue;
262174750Sedwin			}
263174750Sedwin			if (c == 'Q')
264174750Sedwin				result = msgrm(target_key, 0);
265174750Sedwin			else if (c == 'M')
266174750Sedwin				result = shmrm(target_key, 0);
267174750Sedwin			else
268174750Sedwin				result = semrm(target_key, 0);
269174750Sedwin			if (result < 0) {
270174750Sedwin				errflg++;
271174750Sedwin				if (!signaled)
272174750Sedwin					warn("%ss(%ld): ",
273174750Sedwin					    IPC_TO_STR(c), target_key);
274174750Sedwin				else
275174750Sedwin					warnx("%ss are not configured "
276174750Sedwin					    "in the running kernel",
277174750Sedwin					    IPC_TO_STRING(c));
278174750Sedwin			}
279174750Sedwin			break;
280174891Sedwin		case 'v':
281174891Sedwin		case 'y':
282174891Sedwin			/* Handled in other getopt() loop */
283174891Sedwin			break;
284174891Sedwin		case 'W':
285174891Sedwin			msgrm(-1, 0);
286174891Sedwin			shmrm(-1, 0);
287174891Sedwin			semrm(-1, 0);
288174891Sedwin			break;
289174750Sedwin		case ':':
290174750Sedwin			fprintf(stderr,
291174750Sedwin			    "option -%c requires an argument\n", optopt);
292174750Sedwin			usage();
293174750Sedwin		case '?':
294174750Sedwin			fprintf(stderr, "unrecognized option: -%c\n", optopt);
295174750Sedwin			usage();
296174750Sedwin		}
2972736Sdfr	}
2982736Sdfr
299174750Sedwin	if (optind != argc) {
300174750Sedwin		fprintf(stderr, "unknown argument: %s\n", argv[optind]);
301174750Sedwin		usage();
302174750Sedwin	}
303174750Sedwin	exit(errflg);
3042736Sdfr}
305