Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Dec 1995 16:25:10 -0500
From:      tsingle@sunland.gsfc.nasa.gov (Tim Singletary)
To:        hackers@freebsd.org
Subject:   semctl() portability issue and fix
Message-ID:  <199512212125.QAA10262@sunward.gsfc.nasa.gov.gsfc743>

next in thread | raw e-mail | index | archive | help
FreeBSD 2.1, in /usr/include/sys/sem.h declares

     int semctl __P((int, int, int, union semun));

Note that the fourth argument to semctl() is required.  Other unix
systems (SunOS, Solaris, HPUX, and OSF1, to name a few) treat the
fourth argument as optional unless the third argument is SETVAL,
GETALL, SETALL, IPC_STAT, or IPC_SET.  The SunOS manual
_Porting_Software_to_SPARC_ even says:

    Programs that call semctl() with these subcommands [those
    requiring a fourth argument] must pass the union itself, rather
    than an element of the union, or a constant such as 0 (zero).
    Programs that call semctl() with other subcommands should omit the
    fourth argument, rather than pass a constant such as 0 (zero).

So there's a portability issue:  code which compiles and runs just
fine on other systems won't compile on FreeBSD!

I've `fixed' things so that the fourth argument is optional on my
system.  My fix ignores the ``#if __STDC__'' wrapper in the original
semctl.c -- won't it always get compiled in a `__STDC__'
environment?

Anyway, here's what I've done:


1:  I changed line 164 of /usr/include/sys/sem.h from

int semctl __P((int, int, int, union semun));

    to

int semctl __P((int, int, int, ...));


2:  I replaced /usr/src/lib/libc/gen/semctl.c with

-begin--------------
#include <stdarg.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
    
int semctl(int semid, int semnum, int cmd, ...)
{
    va_list ap;
    union semun fourth_arg;
    union semun *fourth_arg_ptr;

    va_start(ap,cmd);
    if (cmd == IPC_SET || cmd == IPC_STAT || cmd == GETALL
                                    || cmd == SETVAL || cmd == SETALL) {
        fourth_arg = va_arg(ap, union semun);
        fourth_arg_ptr = &fourth_arg;
    }
    fourth_arg_ptr = NULL;
    va_end(ap);

    return (semsys(0, semid, semnum, cmd, fourth_arg_ptr));
}
-end----------------

Anyway, I'd appreciate all comments!  Naturally, I'd like to see this
(or some other fix) make its way into the FreeBSD source tree.

tim



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199512212125.QAA10262>