283 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			283 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * krishna balasubramanian 1993
 | 
						|
 *
 | 
						|
 * 1999-02-22 Arkadiusz Mi秌iewicz <misiek@pld.ORG.PL>
 | 
						|
 * - added Native Language Support
 | 
						|
 *
 | 
						|
 * 1999-04-02 frank zago
 | 
						|
 * - can now remove several id's in the same call
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <errno.h>
 | 
						|
 | 
						|
#include <sys/types.h>
 | 
						|
#include <sys/ipc.h>
 | 
						|
#include <sys/shm.h>
 | 
						|
#include <sys/sem.h>
 | 
						|
 | 
						|
/* for getopt */
 | 
						|
#include <unistd.h>
 | 
						|
/* for tolower and isupper */
 | 
						|
#include <ctype.h>
 | 
						|
 | 
						|
#define _(a) a
 | 
						|
 | 
						|
#if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
 | 
						|
/* union semun is defined by including <sys/sem.h> */
 | 
						|
#else
 | 
						|
/* according to X/OPEN we have to define it ourselves */
 | 
						|
union semun {
 | 
						|
	int val;
 | 
						|
	struct semid_ds *buf;
 | 
						|
	unsigned short int *array;
 | 
						|
	struct seminfo *__buf;
 | 
						|
};
 | 
						|
#endif
 | 
						|
 | 
						|
static void usage(char *);
 | 
						|
 | 
						|
char *execname;
 | 
						|
 | 
						|
typedef enum type_id {
 | 
						|
	SHM,
 | 
						|
	SEM,
 | 
						|
	MSG
 | 
						|
} type_id;
 | 
						|
 | 
						|
static int
 | 
						|
remove_ids(type_id type, int argc, char **argv) {
 | 
						|
	int id;
 | 
						|
	int ret = 0;		/* for gcc */
 | 
						|
	char *end;
 | 
						|
	int nb_errors = 0;
 | 
						|
	union semun arg;
 | 
						|
 | 
						|
	arg.val = 0;
 | 
						|
 | 
						|
	while(argc) {
 | 
						|
 | 
						|
		id = strtoul(argv[0], &end, 10);
 | 
						|
 | 
						|
		if (*end != 0) {
 | 
						|
			printf (_("invalid id: %s\n"), argv[0]);
 | 
						|
			nb_errors ++;
 | 
						|
		} else {
 | 
						|
			switch(type) {
 | 
						|
			case SEM:
 | 
						|
#if 0
 | 
						|
				ret = semctl (id, 0, IPC_RMID, arg);
 | 
						|
#endif
 | 
						|
				break;
 | 
						|
 | 
						|
			case MSG:
 | 
						|
#if 0
 | 
						|
				ret = msgctl (id, IPC_RMID, NULL);
 | 
						|
#endif
 | 
						|
				break;
 | 
						|
				
 | 
						|
			case SHM:
 | 
						|
				ret = shmctl (id, IPC_RMID, NULL);
 | 
						|
				break;
 | 
						|
			}
 | 
						|
 | 
						|
			if (ret) {
 | 
						|
				printf (_("cannot remove id %s (%s)\n"),
 | 
						|
					argv[0], strerror(errno));
 | 
						|
				nb_errors ++;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		argc--;
 | 
						|
		argv++;
 | 
						|
	}
 | 
						|
	
 | 
						|
	return(nb_errors);
 | 
						|
}
 | 
						|
 | 
						|
static void deprecate_display_usage(void)
 | 
						|
{
 | 
						|
	usage(execname);
 | 
						|
	printf (_("deprecated usage: %s {shm | msg | sem} id ...\n"),
 | 
						|
		execname);
 | 
						|
}
 | 
						|
 | 
						|
static int deprecated_main(int argc, char **argv)
 | 
						|
{
 | 
						|
	execname = argv[0];
 | 
						|
 | 
						|
	if (argc < 3) {
 | 
						|
		deprecate_display_usage();
 | 
						|
		exit(1);
 | 
						|
	}
 | 
						|
	
 | 
						|
	if (!strcmp(argv[1], "shm")) {
 | 
						|
		if (remove_ids(SHM, argc-2, &argv[2]))
 | 
						|
			exit(1);
 | 
						|
	}
 | 
						|
	else if (!strcmp(argv[1], "msg")) {
 | 
						|
		if (remove_ids(MSG, argc-2, &argv[2]))
 | 
						|
			exit(1);
 | 
						|
	} 
 | 
						|
	else if (!strcmp(argv[1], "sem")) {
 | 
						|
		if (remove_ids(SEM, argc-2, &argv[2]))
 | 
						|
			exit(1);
 | 
						|
	}
 | 
						|
	else {
 | 
						|
		deprecate_display_usage();
 | 
						|
		printf (_("unknown resource type: %s\n"), argv[1]);
 | 
						|
		exit(1);
 | 
						|
	}
 | 
						|
 | 
						|
	printf (_("resource(s) deleted\n"));
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* print the new usage */
 | 
						|
static void
 | 
						|
usage(char *progname)
 | 
						|
{
 | 
						|
	fprintf(stderr,
 | 
						|
		_("usage: %s [ [-q msqid] [-m shmid] [-s semid]\n"
 | 
						|
		  "          [-Q msgkey] [-M shmkey] [-S semkey] ... ]\n"),
 | 
						|
		progname);
 | 
						|
}
 | 
						|
 | 
						|
int main(int argc, char **argv)
 | 
						|
{
 | 
						|
	int   c;
 | 
						|
	int   error = 0;
 | 
						|
	char *prog = argv[0];
 | 
						|
 | 
						|
	/* if the command is executed without parameters, do nothing */
 | 
						|
	if (argc == 1)
 | 
						|
		return 0;
 | 
						|
 | 
						|
	/* check to see if the command is being invoked in the old way if so
 | 
						|
	   then run the old code */
 | 
						|
	if (strcmp(argv[1], "shm") == 0 ||
 | 
						|
	    strcmp(argv[1], "msg") == 0 ||
 | 
						|
	    strcmp(argv[1], "sem") == 0)
 | 
						|
		return deprecated_main(argc, argv);
 | 
						|
 | 
						|
	/* process new syntax to conform with SYSV ipcrm */
 | 
						|
	while ((c = getopt(argc, argv, "q:m:s:Q:M:S:")) != -1) {
 | 
						|
		int result;
 | 
						|
		int id = 0;
 | 
						|
		int iskey = isupper(c);
 | 
						|
 | 
						|
		/* needed to delete semaphores */
 | 
						|
		union semun arg;
 | 
						|
		arg.val = 0;
 | 
						|
 | 
						|
		/* we don't need case information any more */
 | 
						|
		c = tolower(c);
 | 
						|
 | 
						|
		/* make sure the option is in range */
 | 
						|
		if (c != 'q' && c != 'm' && c != 's') {
 | 
						|
			fprintf(stderr, _("%s: illegal option -- %c\n"),
 | 
						|
				prog, c);
 | 
						|
			usage(prog);
 | 
						|
			error++;
 | 
						|
			return error;
 | 
						|
		}
 | 
						|
 | 
						|
		if (iskey) {
 | 
						|
			/* keys are in hex or decimal */
 | 
						|
			key_t key = strtoul(optarg, NULL, 0);
 | 
						|
			if (key == IPC_PRIVATE) {
 | 
						|
				error++;
 | 
						|
				fprintf(stderr, _("%s: illegal key (%s)\n"),
 | 
						|
					prog, optarg);
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
 | 
						|
			/* convert key to id */
 | 
						|
#if 0
 | 
						|
			id = ((c == 'q') ? msgget(key, 0) :
 | 
						|
			      (c == 'm') ? shmget(key, 0, 0) :
 | 
						|
			      semget(key, 0, 0));
 | 
						|
#endif
 | 
						|
			id = (c == 'm') ? shmget(key, 0, 0) :
 | 
						|
				((c == 's') ? semget(key, 0, 0) : -1);
 | 
						|
 | 
						|
			if (id < 0) {
 | 
						|
				char *errmsg;
 | 
						|
				error++;
 | 
						|
				switch(errno) {
 | 
						|
				case EACCES:
 | 
						|
					errmsg = _("permission denied for key");
 | 
						|
					break;
 | 
						|
				case EIDRM:
 | 
						|
					errmsg = _("already removed key");
 | 
						|
					break;
 | 
						|
				case ENOENT:
 | 
						|
					errmsg = _("invalid key");
 | 
						|
					break;
 | 
						|
				default:
 | 
						|
					errmsg = _("unknown error in key");
 | 
						|
					break;
 | 
						|
				}
 | 
						|
				fprintf(stderr, "%s: %s (%s)\n",
 | 
						|
					prog, errmsg, optarg);
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			/* ids are in decimal */
 | 
						|
			id = strtoul(optarg, NULL, 10);
 | 
						|
		}
 | 
						|
 | 
						|
#if 0
 | 
						|
		result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) :
 | 
						|
			  (c == 'm') ? shmctl(id, IPC_RMID, NULL) : 
 | 
						|
			  semctl(id, 0, IPC_RMID, arg));
 | 
						|
#endif
 | 
						|
		result = (c == 'm') ? shmctl(id, IPC_RMID, NULL) :
 | 
						|
				((c == 's') ? semctl(id, 0, IPC_RMID) : -1);
 | 
						|
 | 
						|
		if (result < 0) {
 | 
						|
			char *errmsg;
 | 
						|
			error++;
 | 
						|
			switch(errno) {
 | 
						|
			case EACCES:
 | 
						|
			case EPERM:
 | 
						|
				errmsg = iskey
 | 
						|
					? _("permission denied for key")
 | 
						|
					: _("permission denied for id");
 | 
						|
				break;
 | 
						|
			case EINVAL:
 | 
						|
				errmsg = iskey
 | 
						|
					? _("invalid key")
 | 
						|
					: _("invalid id");
 | 
						|
				break;
 | 
						|
			case EIDRM:
 | 
						|
				errmsg = iskey
 | 
						|
					? _("already removed key")
 | 
						|
					: _("already removed id");
 | 
						|
				break;
 | 
						|
			default:
 | 
						|
				errmsg = iskey
 | 
						|
					? _("unknown error in key")
 | 
						|
					: _("unknown error in id");
 | 
						|
				break;
 | 
						|
			}
 | 
						|
			fprintf(stderr, _("%s: %s (%s)\n"),
 | 
						|
				prog, errmsg, optarg);
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* print usage if we still have some arguments left over */
 | 
						|
	if (optind != argc) {
 | 
						|
		fprintf(stderr, _("%s: unknown argument: %s\n"),
 | 
						|
			prog, argv[optind]);
 | 
						|
		usage(prog);
 | 
						|
	}
 | 
						|
 | 
						|
	/* exit value reflects the number of errors encountered */
 | 
						|
	return error;
 | 
						|
}
 |