typedef unsigned short int sa_family_t;
//Linux includes
#include <sys/types.h>
#define _LINUX_TIME_H
#include <linux/connector.h>
#include <linux/cn_proc.h>
#include <linux/netlink.h>
#include <sys/socket.h>
#include <stdio.h>

//Theses magics come from connector.txt, I will maybe check includes if it's not already in
#define NETLINK_ADD_MEMBERSHIP 1
//#define NETLINK_DROP_MEMBERSHIP 0

#define SOL_NETLINK 270

void show_event(struct proc_event *ev) {
        //This function displays the action of the struct proc_event in argument
        switch(ev->what) {
                case PROC_EVENT_NONE:
                        return;
                        break;
                case PROC_EVENT_FORK:
                        printf("fork(from = %d)=%d\n"ev->event_data.fork.parent_pidev->event_data.fork.child_pid);
                        break;
                case PROC_EVENT_EXEC:
                        printf("exec()\n");
                        break;
                case PROC_EVENT_UID:
                case PROC_EVENT_GID:
                        printf("UID/GID\n");
                        break;
                case PROC_EVENT_EXIT:
                        printf("exit()\n");
                        break;
        }


}

int main(int argcchar **argvchar **envp) {
        //All this code is only to open a NetLink socket...
        //Isn't it easy?
        int s,on;
        struct sockaddr_nl l_local;

        s = socket(PF_NETLINKSOCK_DGRAMNETLINK_CONNECTOR);
        if(!s) {
                perror("Couldn't open socket for NETLINK_CONNECTOR");
                exit(1);
        }

        l_local.nl_family=AF_NETLINK;
        l_local.nl_groups=0x123456;
        l_local.nl_pid = 0;

        if (bind(s, (struct sockaddr *)&l_localsizeof(struct sockaddr_nl)) == -1) {
                perror("bind");
                close(s);
                return -1;
        }

        //On linux > 2.6.14 wee need this to write on a netlink multicast according to connector.txt
        on=l_local.nl_groups;
        setsockopt(sSOL_NETLINKNETLINK_ADD_MEMBERSHIP, &onsizeof(on));

        struct cn_msg message;
        //Fullfil the ID of the kernel side
        message.id.idx=CN_IDX_PROC;
        message.id.val=CN_VAL_PROC;
        message.seq=0;
        message.ack=15000;
        message.len=sizeof(enum proc_cn_mcast_op);
        message.flags=0;
        //message.data=PROC_CN_MCAST_LISTEN;
        *((enum proc_cn_mcast_op*)(message.data))=PROC_CN_MCAST_LISTEN;
        send(s, &messagesizeof(message) + sizeof(enum proc_cn_mcast_op), 0);

        struct cn_msg *buffer=malloc(sizeof(struct cn_msg)+sizeof(struct proc_event));
        int buflen;
        //In this program we only get one event, to demonstrate the use of cn we don't need more.
        buflen=recv(sbuffersizeof(buffer), 0);
        if (buflen<0) {
                return -1;
        }
        //let's show the result.
        struct proc_event *event=buffer->data;
        show_event(event);
}