#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>

#define READ	0
#define WRITE	1

#define P	-1
#define V	1


union semun {
	int              val;    
	struct semid_ds *buf;    
	unsigned short  *array;  
	struct seminfo  *__buf;
};
int init_sem(int semid, int s[], int n)
{
	int i, ret;
	union semun myun;
	for(i = 0; i < n; i++){
		myun.val = s[i];
		ret = semctl(semid, i, SETVAL, myun);
		if(ret < 0){
			perror("semctl");
			return -1;
		}
	}
	return 0;
}

int sem_pv(int semid, int num, int op)
{
	struct sembuf buf;
	buf.sem_num	= num;
	buf.sem_op	= op;
	buf.sem_flg	= 0;
	int ret = semop(semid, &buf, 1);
	if(ret < 0){..
		perror("semop");
		return -1;
	}
	return 0;
}

void sig_handler(int sig)
{
	if(sig == SIGCHLD){
		waitpid(-1, NULL, WNOHANG);
		exit(0);
	}
}

int main()
{
	int s[] = {0, 1};
	key_t key = ftok(".", 'a');
	if(key < 0){
		perror("ftok");
		return -1;
	}

	/*1. create share memory*/
	int shmid = shmget(key, 512, IPC_CREAT | 0666);
	if(shmid < 0){
		perror("shmget");
		return -1;
	}

	/*2. shm mmap*/
	char *shmaddr = shmat(shmid, NULL, 0);
	if(shmaddr == (void *)-1){
		perror("shmat");
		goto _error1;
	}

	/*3. create sem*/
	int semid = semget(key, 2, IPC_CREAT | 0666);
	if(semid < 0){
		perror("semget");
		goto _error1;
	}

	/*4. init sem*/
	int ret = init_sem(semid, s, 2);
	if(ret < 0)
		goto _error2;

	pid_t pid = fork();
	if(pid < 0){
		perror("fork");
		goto _error2;
	}else if(pid == 0){
		//child -- function : delete space
		char *p, *q;
		while(1){
			//P - read
			sem_pv(semid, READ, P);
			p = q = shmaddr;
			while(*p != '\0'){
				if(*p != ' ')
					*q++ = *p;
				p++;
			}
			*q = '\0';
			printf("result : %s", shmaddr);
			if(strncasecmp(shmaddr, "quit\n", 5) == 0)
				goto _error2;
			//V - write
			sem_pv(semid, WRITE, V);
		}

	}else{
		//parent -- function: fgets strings
		signal(SIGCHLD, sig_handler);
		while(1){
			//P - write
			sem_pv(semid, WRITE, P);
			fgets(shmaddr, 256, stdin);
			//V - read
			sem_pv(semid, READ, V);
		}
	}
_error2:
	semctl(semid, 0, IPC_RMID);

_error1:
	shmctl(shmid, IPC_RMID, NULL);
}