This change really is:
Jarkko Hietaniemi [Sun, 24 May 1998 16:13:21 +0000 (19:13 +0300)]
Subject: [PATCH] 5.004_65: the infamous semctl()
Date: Sun, 24 May 1998 16:13:21 +0300 (EET DST)

Change 1041 claimed to be this patch but was really:
Subject: [PATCH] 5.004_65: t/op/ipc*.t
Date: Sat, 16 May 1998 00:52:39 +0300 (EET DST)
From: Jarkko Hietaniemi <jhi@iki.fi>

p4raw-id: //depot/perl@1043

Configure
config_h.SH
doio.c
perl.h

index 79b7a5d..04ab73c 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -408,6 +408,9 @@ d_sem=''
 d_semctl=''
 d_semget=''
 d_semop=''
+d_union_semun=''
+d_semctl_semun=''
+d_semctl_semid_ds=''
 d_setegid=''
 d_seteuid=''
 d_setgrps=''
@@ -7945,6 +7948,162 @@ fi
 set d_sem
 eval $setvar
 
+: see how to do semctl IPC_STAT
+case "$h_sem$d_sem$d_semctl" in
+true$define$define)
+    : see whether sys/sem.h defines union semun
+    $cat > try.c <<'END'
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+int main () { union semun semun; semun.buf = 0; }
+END
+    if $cc $ccflags -o try try.c > /dev/null 2>&1; then
+       echo "You have union semun in <sys/sem.h>." >&4
+       val="$define"
+    else
+        echo "You do not have union semun in <sys/sem.h>." >&4
+        val="$undef"
+    fi
+    $rm -f try try.c
+    set d_union_semun
+    eval $setvar
+
+    : see whether semctl IPC_STAT can use union semun
+    $cat > try.c <<END
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+#$d_union_semun HAS_UNION_SEMUN
+int main() {
+  union semun
+#ifndef HAS_UNION_SEMUN
+  {
+    int val;
+    struct semid_ds *buf;
+    unsigned short *array;
+  }
+#endif
+    arg;
+  int sem, st;
+
+#if defined(IPC_PRIVATE) && defined(S_IRWXU) && defined(S_IRWXG) && \
+    defined(S_IRWXO) && defined(IPC_CREAT)
+  sem = semget(IPC_PRIVATE, 1, S_IRWXU|S_IRWXG|S_IRWXO|IPC_CREAT);
+  if (sem > -1) {
+    struct semid_ds argbuf;
+    arg.buf = &argbuf;
+#   ifdef IPC_STAT
+    st = semctl(sem, 0, IPC_STAT, arg);
+    if (st == 0)
+      printf("semun\n");
+    else
+#   endif /* IPC_STAT */
+      printf("semctl IPC_STAT failed: errno = %d\n", errno);
+#   ifdef IPC_RMID
+    if (semctl(sem, 0, IPC_RMID, arg) != 0)
+#   endif /* IPC_RMID */
+      printf("semctl IPC_RMID failed: errno = %d\n", errno);
+  } else
+#endif /* IPC_PRIVATE && ... */
+    printf("semget failed: errno = %d\n", errno);
+
+  return 0;
+}
+END
+    val="$undef"
+    if $cc $ccflags -o try try.c > /dev/null 2>&1; then
+        d_semctl_semun=`./try`
+        case "$d_semctl_semun" in
+        semun) val="$define" ;;
+        esac
+    fi
+    $rm -f try try.c
+    set d_semctl_semun
+    eval $setvar
+    case "$d_semctl_semun" in
+    $define|true)
+        echo "You can use union semun for semctl IPC_STAT." >&4
+        ;;
+    *)  echo "You cannot use union semun for semctl IPC_STAT." >&4
+        ;;
+    esac
+
+    : see whether semctl IPC_STAT can use struct semid_ds pointer
+
+    $cat > try.c <<'END'
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+int main() {
+  struct semid_ds arg;
+  int sem, st;
+
+#if defined(IPC_PRIVATE) && defined(S_IRWXU) && defined(S_IRWXG) && \
+    defined(S_IRWXO) && defined(IPC_CREAT)
+  sem = semget(IPC_PRIVATE, 1, S_IRWXU|S_IRWXG|S_IRWXO|IPC_CREAT);
+  if (sem > -1) {
+#   ifdef IPC_STAT
+    st = semctl(sem, 0, IPC_STAT, &arg);
+    if (st == 0)
+      printf("semid_ds\n");
+    else
+#   endif /* IPC_STAT */
+      printf("semctl IPC_STAT failed: errno = %d\n", errno);
+#   ifdef IPC_RMID
+    if (semctl(sem, 0, IPC_RMID, &arg) != 0)
+#   endif /* IPC_RMID */
+      printf("semctl IPC_RMID failed: errno = %d\n", errno);
+  } else
+#endif /* IPC_PRIVATE && ... */
+      printf("semget failed: errno = %d\n", errno);
+
+  return 0;
+}
+END
+    val="$undef"
+    if $cc $ccflags -o try try.c > /dev/null 2>&1; then
+        d_semctl_semid_ds=`./try`
+        case "$d_semctl_semid_ds" in
+        semid_ds) val="$define" ;;
+        esac
+    fi
+    $rm -f try try.c
+    set d_semctl_semid_ds
+    eval $setvar
+    case "$d_semctl_semid_ds" in
+    $define|true)
+        echo "You can use struct semid_ds * for semctl IPC_STAT." >&4
+        ;;
+    *)  echo "You cannot use struct semid_ds * for semctl IPC_STAT." >&4
+        ;;
+    esac
+    ;;
+*)  val="$undef"
+
+    set d_union_semun
+    eval $setvar
+
+    set d_semctl_semun
+    eval $setvar
+
+    set d_semctl_semid_ds
+    eval $setvar
+    ;;
+esac
+
 : see if setegid exists
 set setegid d_setegid
 eval $inlibc
@@ -11134,6 +11293,9 @@ d_sem='$d_sem'
 d_semctl='$d_semctl'
 d_semget='$d_semget'
 d_semop='$d_semop'
+d_union_semun='$d_union_semun'
+d_semctl_semun='$d_semctl_semun'
+d_semctl_semid_ds='$d_semctl_semid_ds'
 d_setegid='$d_setegid'
 d_seteuid='$d_seteuid'
 d_setgrps='$d_setgrps'
index 78486ba..ab532e5 100644 (file)
@@ -536,6 +536,30 @@ sed <<!GROK!THIS! >config.h -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un-
  */
 #$d_sem HAS_SEM                /**/
 
+/* HAS_UNION_SEMUN:
+ *     This symbol, if defined, indicates that the union semun
+ *     is defined in <sys/sem.h>.  If not, the user code probably
+ *      needs to define it as:
+ * union semun {
+ *    int val;
+ *    struct semid_ds *buf;
+ *    unsigned short *array;
+ * }
+ */
+#$d_union_semun HAS_UNION_SEMUN                /**/
+
+/* USE_SEMCTL_SEMUN:
+ *     This symbol, if defined, indicates that union semun is
+ *     used for semctl IPC_STAT.
+ */
+#$d_semctl_semun USE_SEMCTL_SEMUN      /**/
+
+/* USE_SEMCTL_SEMID_DS:
+ *     This symbol, if defined, indicates that struct semid_ds * is
+ *     used for semctl IPC_STAT.
+ */
+#$d_semctl_semid_ds USE_SEMCTL_SEMID_DS        /**/
+
 /* HAS_SETEGID:
  *     This symbol, if defined, indicates that the setegid routine is available
  *     to change the effective gid of the current program.
diff --git a/doio.c b/doio.c
index bbf3837..37d6167 100644 (file)
--- a/doio.c
+++ b/doio.c
@@ -1389,21 +1389,6 @@ do_ipcget(I32 optype, SV **mark, SV **sp)
     return -1;                 /* should never happen */
 }
 
-#if defined(__sun) && defined(__svr4__) /* XXX Need metaconfig test */
-/* Solaris manpage says that it uses (like linux)
-   int semctl (int semid, int semnum, int cmd, union semun arg)
-   but the system include files do not define union semun !!!!
-   Note: Linux/glibc *does* declare union semun in <sys/sem_buf.h>
-   but, unlike the older Linux libc and Solaris, it has an extra
-   struct seminfo * on the end.
-*/
-union semun {
-     int val;
-     struct semid_ds *buf;
-     ushort *array;
-};
-#endif
-
 I32
 do_ipcctl(I32 optype, SV **mark, SV **sp)
 {
@@ -1412,26 +1397,6 @@ do_ipcctl(I32 optype, SV **mark, SV **sp)
     char *a;
     I32 id, n, cmd, infosize, getinfo;
     I32 ret = -1;
-/* XXX REALLY need metaconfig test */
-/* linux and Solaris2 use:
-   int semctl (int semid, int semnum, int cmd, union semun arg)
-   instead of:
-   int semctl (int semid, int semnum, int cmd, struct semid_ds *arg);
-   Solaris and Linux (pre-glibc) use
-       union semun {
-            int val;
-            struct semid_ds *buf;
-            ushort *array;
-       };
-   but Solaris doesn't declare it in a header file (we declared it
-   explicitly earlier). Linux/glibc declares a *different* union semun
-   so we just refer to "union semun" here.
-    
-*/
-#if defined(__linux__) || (defined(__sun__) && defined(__svr4__))
-#   define SEMCTL_SEMUN
-    union semun unsemds, semun;
-#endif
 
     id = SvIVx(*++mark);
     n = (optype == OP_SEMCTL) ? SvIVx(*++mark) : 0;
@@ -1461,13 +1426,9 @@ do_ipcctl(I32 optype, SV **mark, SV **sp)
        else if (cmd == GETALL || cmd == SETALL)
        {
            struct semid_ds semds;
-#ifdef SEMCTL_SEMUN
+           union semun semun;
+
             semun.buf = &semds;
-           if (semctl(id, 0, IPC_STAT, semun) == -1)
-#else
-           if (semctl(id, 0, IPC_STAT, &semds) == -1)
-#endif
-               return -1;
            getinfo = (cmd == GETALL);
            infosize = semds.sem_nsems * sizeof(short);
                /* "short" is technically wrong but much more portable
@@ -1511,14 +1472,12 @@ do_ipcctl(I32 optype, SV **mark, SV **sp)
        break;
 #endif
 #ifdef HAS_SEM
-    case OP_SEMCTL:
-#ifdef SEMCTL_SEMUN
-       /* XXX Need metaconfig test */
-        unsemds.buf = (struct semid_ds *)a;
-       ret = semctl(id, n, cmd, unsemds);
-#else
-       ret = semctl(id, n, cmd, (struct semid_ds *)a);
-#endif
+    case OP_SEMCTL: {
+            union semun unsemds;
+
+            unsemds.buf = (struct semid_ds *)a;
+           ret = Semctl(id, n, cmd, unsemds);
+        }
        break;
 #endif
 #ifdef HAS_SHM
diff --git a/perl.h b/perl.h
index fc96064..8645c39 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -2090,6 +2090,26 @@ enum {
        UNLOCK_SV_MUTEX;                                \
     } while (0)
 
+#ifdef HAS_SEM
+#   include <sys/ipc.h>
+#   include <sys/sem.h>
+#   ifndef HAS_UNION_SEMUN     /* Provide the union semun. */
+    union semun {
+       int val;
+       struct semid_ds *buf;
+       unsigned short *array;
+    };
+#   endif
+#   ifdef USE_SEMCTL_SEMUN
+#       define Semctl(id, num, cmd, semun) semctl(id, num, cmd, semun)
+#   else
+#       ifdef USE_SEMCTL_SEMID_DS
+#           define Semctl(id, num, cmd, semun) semctl(id, num, cmd, semun.buf)
+#       endif
+#   endif
+#   ifndef Semctl      /* Place our bets on the semun horse. */
+#       define Semctl(id, num, cmd, semun) semctl(id, num, cmd, semun)
+#   endif
+#endif
 
 #endif /* Include guard */
-