ipcrm.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * ipcrm.c - utility to allow removal of IPC objects and data structures.
  4. *
  5. * 01 Sept 2004 - Rodney Radford <rradford@mindspring.com>
  6. * Adapted for busybox from util-linux-2.12a.
  7. *
  8. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  9. */
  10. //config:config IPCRM
  11. //config: bool "ipcrm (2.9 kb)"
  12. //config: default y
  13. //config: help
  14. //config: The ipcrm utility allows the removal of System V interprocess
  15. //config: communication (IPC) objects and the associated data structures
  16. //config: from the system.
  17. //applet:IF_IPCRM(APPLET_NOEXEC(ipcrm, ipcrm, BB_DIR_USR_BIN, BB_SUID_DROP, ipcrm))
  18. //kbuild:lib-$(CONFIG_IPCRM) += ipcrm.o
  19. #include "libbb.h"
  20. /* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
  21. /* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
  22. #include <sys/ipc.h>
  23. #include <sys/shm.h>
  24. #include <sys/msg.h>
  25. #include <sys/sem.h>
  26. #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
  27. /* union semun is defined by including <sys/sem.h> */
  28. #else
  29. /* according to X/OPEN we have to define it ourselves */
  30. union semun {
  31. int val;
  32. struct semid_ds *buf;
  33. unsigned short *array;
  34. struct seminfo *__buf;
  35. };
  36. #endif
  37. #define IPCRM_LEGACY 1
  38. #if IPCRM_LEGACY
  39. typedef enum type_id {
  40. SHM,
  41. SEM,
  42. MSG
  43. } type_id;
  44. static int remove_ids(type_id type, char **argv)
  45. {
  46. unsigned long id;
  47. int nb_errors = 0;
  48. union semun arg;
  49. arg.val = 0;
  50. while (argv[0]) {
  51. id = bb_strtoul(argv[0], NULL, 10);
  52. if (errno || id > INT_MAX) {
  53. bb_error_msg("invalid id: %s", argv[0]);
  54. nb_errors++;
  55. } else {
  56. int ret = 0;
  57. if (type == SEM)
  58. ret = semctl(id, 0, IPC_RMID, arg);
  59. else if (type == MSG)
  60. ret = msgctl(id, IPC_RMID, NULL);
  61. else if (type == SHM)
  62. ret = shmctl(id, IPC_RMID, NULL);
  63. if (ret) {
  64. bb_perror_msg("can't remove id %s", argv[0]);
  65. nb_errors++;
  66. }
  67. }
  68. argv++;
  69. }
  70. return nb_errors;
  71. }
  72. #endif /* IPCRM_LEGACY */
  73. //usage:#define ipcrm_trivial_usage
  74. //usage: "[-MQS key] [-mqs id]"
  75. //usage:#define ipcrm_full_usage "\n\n"
  76. //usage: "Upper-case options MQS remove an object by shmkey value.\n"
  77. //usage: "Lower-case options remove an object by shmid value.\n"
  78. //usage: "\n -mM Remove memory segment after last detach"
  79. //usage: "\n -qQ Remove message queue"
  80. //usage: "\n -sS Remove semaphore"
  81. int ipcrm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  82. int ipcrm_main(int argc, char **argv)
  83. {
  84. int c;
  85. int error = 0;
  86. /* if the command is executed without parameters, do nothing */
  87. if (argc == 1)
  88. return 0;
  89. #if IPCRM_LEGACY
  90. /* check to see if the command is being invoked in the old way if so
  91. then run the old code. Valid commands are msg, shm, sem. */
  92. {
  93. type_id what = 0; /* silence gcc */
  94. char w;
  95. w = argv[1][0];
  96. if ( ((w == 'm' && argv[1][1] == 's' && argv[1][2] == 'g')
  97. || (argv[1][0] == 's'
  98. && ((w = argv[1][1]) == 'h' || w == 'e')
  99. && argv[1][2] == 'm')
  100. ) && argv[1][3] == '\0'
  101. ) {
  102. if (argc < 3)
  103. bb_show_usage();
  104. if (w == 'h')
  105. what = SHM;
  106. else if (w == 'm')
  107. what = MSG;
  108. else if (w == 'e')
  109. what = SEM;
  110. if (remove_ids(what, &argv[2]))
  111. fflush_stdout_and_exit(EXIT_FAILURE);
  112. puts("resource(s) deleted");
  113. return 0;
  114. }
  115. }
  116. #endif /* IPCRM_LEGACY */
  117. /* process new syntax to conform with SYSV ipcrm */
  118. while ((c = getopt(argc, argv, "q:m:s:Q:M:S:")) != -1) {
  119. int result;
  120. int id;
  121. int iskey;
  122. /* needed to delete semaphores */
  123. union semun arg;
  124. if (c == '?') /* option not in the string */
  125. bb_show_usage();
  126. id = 0;
  127. arg.val = 0;
  128. iskey = !(c & 0x20); /* uppercase? */
  129. if (iskey) {
  130. /* keys are in hex or decimal */
  131. key_t key = xstrtoul(optarg, 0);
  132. if (key == IPC_PRIVATE) {
  133. error++;
  134. bb_error_msg("illegal key (%s)", optarg);
  135. continue;
  136. }
  137. c |= 0x20; /* lowercase. c is 'q', 'm' or 's' now */
  138. /* convert key to id */
  139. id = ((c == 'q') ? msgget(key, 0) :
  140. (c == 'm') ? shmget(key, 0, 0) : semget(key, 0, 0));
  141. if (id < 0) {
  142. const char *errmsg;
  143. error++;
  144. switch (errno) {
  145. case EACCES:
  146. errmsg = "permission denied for";
  147. break;
  148. case EIDRM:
  149. errmsg = "already removed";
  150. break;
  151. case ENOENT:
  152. errmsg = "invalid";
  153. break;
  154. default:
  155. errmsg = "unknown error in";
  156. break;
  157. }
  158. bb_error_msg("%s %s (%s)", errmsg, "key", optarg);
  159. continue;
  160. }
  161. } else {
  162. /* ids are in decimal */
  163. id = xatoul(optarg);
  164. }
  165. result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) :
  166. (c == 'm') ? shmctl(id, IPC_RMID, NULL) :
  167. semctl(id, 0, IPC_RMID, arg));
  168. if (result) {
  169. const char *errmsg;
  170. const char *const what = iskey ? "key" : "id";
  171. error++;
  172. switch (errno) {
  173. case EACCES:
  174. case EPERM:
  175. errmsg = "permission denied for";
  176. break;
  177. case EINVAL:
  178. errmsg = "invalid";
  179. break;
  180. case EIDRM:
  181. errmsg = "already removed";
  182. break;
  183. default:
  184. errmsg = "unknown error in";
  185. break;
  186. }
  187. bb_error_msg("%s %s (%s)", errmsg, what, optarg);
  188. continue;
  189. }
  190. }
  191. /* print usage if we still have some arguments left over */
  192. if (optind != argc) {
  193. bb_show_usage();
  194. }
  195. /* exit value reflects the number of errors encountered */
  196. return error;
  197. }