//my_pxsem_svsem/sem_open.c
#include	"unpipc.h"
#include	"semaphore.h"

#include	<stdarg.h>		/*      */
#define		MAX_TRIES	10	/*    */

mysem_t	*
mysem_open(const char *pathname, int oflag, ... )
{
	int		i, fd, semflag, semid, save_errno;
	key_t	key;
	mode_t	mode;
	va_list	ap;
	mysem_t	*sem;
	union semun	arg;
	unsigned int	value;
	struct semid_ds	seminfo;
	struct sembuf	initop;

		/*    sem_open()  O_CREAT  ;  */
	semflag = SVSEM_MODE;
	semid = -1;

	if (oflag & O_CREAT) {
		va_start(ap, oflag);		/*  ap     */
		mode = va_arg(ap, va_mode_t);
		value = va_arg(ap, unsigned int);
		va_end(ap);

			/*   ,     System V */
		if ( (fd = open(pathname, oflag, mode)) == -1)
			return(SEM_FAILED);
		close(fd);
		if ( (key = ftok(pathname, 0)) == (key_t) -1)
			return(SEM_FAILED);

		semflag = IPC_CREAT | (mode & 0777);
		if (oflag & O_EXCL)
			semflag |= IPC_EXCL;

			/*   System V   IPC_EXCL */
		if ( (semid = semget(key, 1, semflag | IPC_EXCL)) >= 0) {
				/* ,   ,    */
			arg.val = 0;
			if (semctl(semid, 0, SETVAL, arg) == -1)
				goto err;
				/*  ,  sem_otime   */
			if (value > SEMVMX) {
				errno = EINVAL;
				goto err;
			}
        	initop.sem_num = 0;
        	initop.sem_op  = value;
        	initop.sem_flg = 0;
			if (semop(semid, &initop, 1) == -1)
				goto err;
			goto finish;

		} else if (errno != EEXIST || (semflag & IPC_EXCL) != 0)
			goto err;
		/*    */
	}
