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;
 | |
| }
 | 
