semctl.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /* Copyright (C) 1995-2019 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <http://www.gnu.org/licenses/>. */
  15. #include <sys/sem.h>
  16. #include <stdarg.h>
  17. #include <ipc_priv.h>
  18. #include <sysdep.h>
  19. #include <shlib-compat.h>
  20. #include <errno.h>
  21. /* Define a `union semun' suitable for Linux here. */
  22. union semun
  23. {
  24. int val; /* value for SETVAL */
  25. struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
  26. unsigned short int *array; /* array for GETALL & SETALL */
  27. struct seminfo *__buf; /* buffer for IPC_INFO */
  28. };
  29. #ifndef DEFAULT_VERSION
  30. # define DEFAULT_VERSION GLIBC_2_2
  31. #endif
  32. int
  33. __new_semctl (int semid, int semnum, int cmd, ...)
  34. {
  35. union semun arg = { 0 };
  36. va_list ap;
  37. /* Get the argument only if required. */
  38. switch (cmd)
  39. {
  40. case SETVAL: /* arg.val */
  41. case GETALL: /* arg.array */
  42. case SETALL:
  43. case IPC_STAT: /* arg.buf */
  44. case IPC_SET:
  45. case SEM_STAT:
  46. case IPC_INFO: /* arg.__buf */
  47. case SEM_INFO:
  48. va_start (ap, cmd);
  49. arg = va_arg (ap, union semun);
  50. va_end (ap);
  51. break;
  52. }
  53. #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
  54. return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
  55. arg.array);
  56. #else
  57. return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
  58. SEMCTL_ARG_ADDRESS (arg));
  59. #endif
  60. }
  61. versioned_symbol (libc, __new_semctl, semctl, DEFAULT_VERSION);
  62. #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
  63. /* Since semctl use a variadic argument for semid_ds there is not need to
  64. define and tie the compatibility symbol to the old 'union semun'
  65. definition. */
  66. int
  67. attribute_compat_text_section
  68. __old_semctl (int semid, int semnum, int cmd, ...)
  69. {
  70. union semun arg = { 0 };
  71. va_list ap;
  72. /* Get the argument only if required. */
  73. switch (cmd)
  74. {
  75. case SETVAL: /* arg.val */
  76. case GETALL: /* arg.array */
  77. case SETALL:
  78. case IPC_STAT: /* arg.buf */
  79. case IPC_SET:
  80. case SEM_STAT:
  81. case IPC_INFO: /* arg.__buf */
  82. case SEM_INFO:
  83. va_start (ap, cmd);
  84. arg = va_arg (ap, union semun);
  85. va_end (ap);
  86. break;
  87. }
  88. # ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
  89. return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd, arg.array);
  90. # else
  91. return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd,
  92. SEMCTL_ARG_ADDRESS (arg));
  93. # endif
  94. }
  95. compat_symbol (libc, __old_semctl, semctl, GLIBC_2_0);
  96. #endif