From 5a1ff0323cf3a64358c65c01e69f3ecb9fac8ccd Mon Sep 17 00:00:00 2001 From: Daniel Jones Date: Tue, 26 Mar 2019 18:23:40 +1030 Subject: first code commit --- xbell.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 xbell.c (limited to 'xbell.c') diff --git a/xbell.c b/xbell.c new file mode 100644 index 0000000..70ca37a --- /dev/null +++ b/xbell.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * maximum number of arguemnts we will try and call when + * launching the usder defined program + */ +#define ARG_LIMIT 20 + +#define BUFF_SIZE 512 + +char *program = "sh -c /home/daniel_j/programming/bash/beep.sh"; + +Display *display; +XEvent xevent; +XkbEvent *xkbevent; +int xkbeventcode; /* stores the event code for the xkb extension */ + +int +forkexecute() +{ + pid_t pid = fork(); + if (pid == 0) + { + // child process, we don't want to ignore signals + signal(SIGCHLD, SIG_DFL); + /* + * we don't want std{out,err} to be associated with the terminal, + * but we also don't want to close it to avoid the file descriptors + * being re-used potentially leading to problems, so reopen them to /dev/null + */ + freopen("/dev/null", "w", stdout); + freopen("/dev/null", "w", stderr); + char *args[ARG_LIMIT]; + char *buff = malloc(BUFF_SIZE); + if (buff == NULL) + { + perror("malloc"); + return -1; + } + /* + * the program we're calling might have arguments, + * so we tokenise the string and add each part to an array + * that we will use in execvp + */ + strncpy(buff, program, BUFF_SIZE-1); + char *t = strtok(buff, " "); + int z = 0; + while (t != NULL && z < ARG_LIMIT-1) // save a position for NULL + { + args[z] = t; + t = strtok(NULL, " "); + z++; + } + args[z+1] = (char *)0; + execvp(args[0], args); + _exit(1); + } + else if (pid == -1) + { + perror("fork"); + return -1; + } + return 1; +} + +void +bellevent(void) +{ + /* + * a bell event was caught, execute the user defined program + */ + int ret = forkexecute(); + if (ret != 1) + fprintf(stderr, "forkexecute() failed"); +} + +int +main(void) +{ + // ignore child processes + signal(SIGCHLD, SIG_IGN); + // ignore return values for now + display = XkbOpenDisplay(NULL, &xkbeventcode, NULL, NULL, NULL, NULL); + if (!display) + { + fprintf(stderr, "Cannot open display.\n"); + exit(1); + } + + XkbSelectEvents(display, XkbUseCoreKbd, XkbBellNotifyMask, XkbBellNotifyMask); + + + while (1) + { + XNextEvent(display, &xevent); + if (xevent.type == xkbeventcode) + { + xkbevent = (XkbEvent *)&xevent; + if (xkbevent->any.xkb_type == XkbBellNotify) + { + bellevent(); + } + } + } + return 0; +} -- cgit v1.2.3