/*
* semex.c --- System V and Linux semaphore exerciser
*
- * by Eric S. Raymond <esr@snark.thyrsus.com>
+ * by Eric S. Raymond <esr@thyrsus.com>
+ *
+ * Written sometime in the dark and backward abysm of time back in the 1980s.
+ * The 1.2 release in 1994 moved the code to ANSI C with prototypes.
+ * The 1.3 release uses strerror(3) rather than its own array of error strings.
*/
#include <stdio.h>
#include <signal.h>
+#include <string.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
-extern int errno;
-extern void exit();
-extern char *strchr(), *strcat(), *ctime();
-extern unsigned sleep();
-
-/*
- * This will need to change if any future version changes the #define values
- * of any UNIX error types. The highest value currently recognized is
- * EIDRM; the code that uses it in errmsg() will issue a generic error type
- * for higher values.
- */
-static char *errtypes[] =
-{
- "?",
- "EPERM", /* Not super-user */
- "ENOENT", /* No such file or directory */
- "ESRCH", /* No such process */
- "EINTR", /* interrupted system call */
- "EIO", /* I/O error */
- "ENXIO", /* No such device or address */
- "E2BIG", /* Arg list too long */
- "ENOEXEC", /* Exec format error */
- "EBADF", /* Bad file number */
- "ECHILD", /* No children */
- "EAGAIN", /* No more processes */
- "ENOMEM", /* Not enough core */
- "EACCES", /* Permission denied */
- "EFAULT", /* Bad address */
- "ENOTBLK", /* Block device required */
- "EBUSY", /* Mount device busy */
- "EEXIST", /* File exists */
- "EXDEV", /* Cross-device link */
- "ENODEV", /* No such device */
- "ENOTDIR", /* Not a directory */
- "EISDIR", /* Is a directory */
- "EINVAL", /* Invalid argument */
- "ENFILE", /* File table overflow */
- "EMFILE", /* Too many open files */
- "ENOTTY", /* Not a typewriter */
- "ETXTBSY", /* Text file busy */
- "EFBIG", /* File too large */
- "ENOSPC", /* No space left on device */
- "ESPIPE", /* Illegal seek */
- "EROFS", /* Read only file system */
- "EMLINK", /* Too many links */
- "EPIPE", /* Broken pipe */
- "EDOM", /* Math arg out of domain of func */
- "ERANGE", /* Math result not representable */
- "ENOMSG", /* No message of desired type */
- "EIDRM", /* Identifier removed */
+#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; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
+ unsigned short *array; /* array for GETALL, SETALL */
+ /* Linux specific part: */
+ struct seminfo *__buf; /* buffer for IPC_INFO */
};
+#endif
static ushort parent;
static int tty;
exit(0);
}
-static char *errmsg(code)
-/* return the UNIX error message for a given errno code */
-int code;
-{
- extern int sys_nerr;
- extern char *sys_errlist[];
- static char ebuf[BUFSIZ];
-
- (void) sprintf(ebuf, "error %d", code);
-
- if (code < sizeof(errtypes) / sizeof(char *))
- {
- (void) strcat(ebuf, " (");
- (void) strcat(ebuf, errtypes[code]);
- (void) strcat(ebuf, ")");
- }
-
- if (code <= sys_nerr)
- {
- (void) strcat(ebuf, ", ");
- (void) strcat(ebuf, sys_errlist[code]);
- }
-
- return(ebuf);
-}
-
void shsemop(semid, sops, nops)
/* perform a semaphore op, announcing the specifics of the operation */
int semid;
if (nops == -1)
(void) printf("semop in process %d failed: %s\n",
- getpid(), errmsg(errno));
+ getpid(), strerror(errno));
else
(void) printf(
"semop in process %d succeeded, returning %d\n",
}
main(argc, argv)
-/* exercise the active file functions */
int argc;
char *argv[];
{
(void) printf( "The exerciser process pid is %d\n", parent);
}
- while ((!tty || fputs("> ", stdout) != EOF) && gets(cmdline))
+ while ((!tty || fputs("> ", stdout) != EOF) && fgets(cmdline, sizeof(cmdline)-1, stdin))
{
errno = 0;
{
(void) printf("semget(%ld, %d, %04o) ", key, nsems, semflg);
if (semid == -1)
- (void) printf("failed: %s\n", errmsg(errno));
+ (void) printf("failed: %s\n", strerror(errno));
else
(void) printf("succeeded, semid = %d\n", semid);
}
(void) printf("semctl(%d, %d, SETVAL, %d) ",
semid, semnum, semval);
if (rv == -1)
- (void) printf("failed: %s\n", errmsg(errno));
+ (void) printf("failed: %s\n", strerror(errno));
else
(void) printf("succeeded, returning %d\n", rv);
}
/* retrieve and show the existing modes */
(void) printf("semctl(%d, %d, IPC_STAT, &ds) ", semnum,semid);
if (rv == -1)
- (void) printf("failed: %s\n", errmsg(errno));
+ (void) printf("failed: %s\n", strerror(errno));
else
{
(void) printf("succeeded, returning %d\n", rv);
(void) printf("semctl(%d, %d, IPC_SET, &ds) ",
semnum, semid);
if (rv == -1)
- (void) printf("failed: %s\n", errmsg(errno));
+ (void) printf("failed: %s\n", strerror(errno));
else
(void) printf("succeeded, returning %d\n", rv);
}
{
(void) printf("semctl(%d, 0, IPC_RMID) ", semid);
if (rv == -1)
- (void) printf("failed: %s\n", errmsg(errno));
+ (void) printf("failed: %s\n", strerror(errno));
else
(void) printf("succeeded\n");
}