diff --git a/android-receiver.c b/android-receiver.c index cbdd64e..d20e313 100644 --- a/android-receiver.c +++ b/android-receiver.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -10,17 +11,13 @@ #include #include -#define DEBUG 0 -#define MAXBUF 1024 -#define TOK "/" -#define FMTCALL " -!- Call from %s" -#define FMTOTHER " -!- %s" +#define MAXBUF 1024 +#define SEP "/" -#define STREQ(a, b) strcmp((a),(b)) == 0 -#define STRDUP(a, b) if ((b)) a = strdup((b)) +#define STREQ(a, b) strcmp((a),(b)) == 0 +#define STRDUP(a, b) if ((b)) a = strdup((b)) -static int portno = 10600; -static char *handler; +static int portno = 10600; enum etype { Ring, @@ -40,71 +37,47 @@ struct message_t { char * event_contents; }; -static void error(char *msg) { /* {{{ */ - perror(msg); - exit(EXIT_FAILURE); -} -/* }}} */ - -static void help_message() { /* {{{ */ - fprintf(stderr, "usage: android-receiver [ -p ] -h \n" - " -p, --port the port to listen on. optional, defaults to 10600. \n" - " -h, --handler an executable to handle the message. will be called with \n" - " the formatted message as its first and only argument. \n"); - - exit(EXIT_FAILURE); -} -/* }}} */ - -static int handle_options(int argc, char *argv[]) { /* {{{ */ +static void parse_options(int argc, char *argv[]) { int opt, option_index = 0; char *token; static struct option opts[] = { { "port" , required_argument, 0, 'p'}, - { "handler", required_argument, 0, 'h'}, + { "help" , no_argument, 0, 'h'}, { 0 , 0 , 0, 0 } }; - while ((opt = getopt_long(argc, argv, "p:h:", opts, &option_index)) != -1) { - switch(opt) { + while ((opt = getopt_long(argc, argv, "hp:", opts, &option_index)) != -1) { + switch (opt) { case 'p': portno = strtol(optarg, &token, 10); if (*token != '\0' || portno <= 0 || portno > 65535) { - fprintf(stderr, "error: invalid port number\n\n"); - return 1; + fprintf(stderr, "invalid port number\n"); + exit(EXIT_FAILURE); } break; case 'h': - handler = optarg; - break; + printf("usage: android-receiver [ -p ]\n"); + exit(EXIT_SUCCESS); default: - return 1; + fprintf(stderr, "invalid option, try -h or --help\n"); + exit(EXIT_FAILURE); } } - - if (!handler) { - fprintf(stderr, "error: handler is required\n\n"); - return 1; - } - - return 0; } -/* }}} */ -static struct message_t *parse_message(char *msg) { /* {{{ */ +static struct message_t *parse_message(char *msg) { struct message_t *message; - char *tmp; - char *tok; + char *tmp, *tok; int field = 0; message = malloc(sizeof *message); /* v1: device_id / notification_id / event_type / event_contents */ /* v2: "v2" / device_id / notification_id / event_type / data / event_contents */ - for (tok = strsep(&msg, TOK); ++field <= 5; tok = strsep(&msg, TOK)) { + for (tok = strsep(&msg, SEP); ++field <= 5; tok = strsep(&msg, SEP)) { switch (field) { case 1: if (tok && STREQ(tok, "v2")) @@ -113,7 +86,7 @@ static struct message_t *parse_message(char *msg) { /* {{{ */ /* rebuild a v1 msg to start parsing at field 2 */ message->version = 1; tmp = strdup(msg); - strcat(tok, TOK); + strcat(tok, SEP); strcat(tok, tmp); msg = tok; } @@ -133,6 +106,7 @@ static struct message_t *parse_message(char *msg) { /* {{{ */ if (message->version == 1) { /* for v1, grab everything else and return */ STRDUP(message->event_contents, msg); + message->data = ""; return message; } break; @@ -146,48 +120,67 @@ static struct message_t *parse_message(char *msg) { /* {{{ */ return message; } -/* }}} */ -static void handle_message(struct message_t *message) { /* {{{ */ - char *msg; +static void handle_message(char *msg) { /* {{{ */ + printf("message received: %s\n", msg); + + struct message_t *message; + char *title, *body; + + message = parse_message(msg); switch (message->event_type) { case Ring: - asprintf(&msg, FMTCALL, message->event_contents); + asprintf(&title, "Call: %s", message->data); break; - case SMS: + asprintf(&title, "SMS: %s", message->data); + break; case MMS: + asprintf(&title, "MMS: %s", message->data); + break; case Battery: - case Ping: /* todo: other type-specific formats */ - asprintf(&msg, FMTOTHER, message->event_contents); + asprintf(&title, "Battery: %s", message->data); + break; + case Ping: + title = "Ping"; break; - default: msg = NULL; + default: + return; } - if (!msg) - return; + asprintf(&body, "%s", message->event_contents); + + char *flags[] = { "notify-send", title, body, (char *)NULL }; + + /* double-fork taken from dzen2/util.c; avoids zombie processes + * without requiring a signal handler. */ + if (fork() == 0) { + if (fork() == 0) { + execvp("notify-send", flags); + exit(EXIT_SUCCESS); + } + exit(EXIT_SUCCESS); + } - char *flags[] = { handler, msg, (char *)NULL }; - execvp(handler, flags); + wait(0); } -/* }}} */ -int main(int argc, char *argv[]) { /* {{{ */ +int main(int argc, char *argv[]) { char buf[MAXBUF]; - struct message_t *message; - struct sockaddr_in server, from; + struct sockaddr_in server, from; int sock, n; unsigned int fromlen = sizeof from; - if (handle_options(argc, argv) != 0) - help_message(); + parse_options(argc, argv); - if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - error("error opening socket"); + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("error opening socket"); + exit(EXIT_FAILURE); + } memset(&server, '\0', sizeof server); @@ -195,30 +188,20 @@ int main(int argc, char *argv[]) { /* {{{ */ server.sin_port = htons(portno); server.sin_addr.s_addr = INADDR_ANY; - if (bind(sock, (struct sockaddr *)&server, sizeof server) < 0) - error("error binding to socket"); + if (bind(sock, (struct sockaddr *)&server, sizeof server) < 0) { + perror("error binding to socket"); + exit(EXIT_FAILURE); + } while (1) { while ((n = recvfrom(sock, buf, 1024, 0, (struct sockaddr *)&from, &fromlen)) < 0 && errno == EINTR) ; - if (n < 0) - error("error receiving from socket"); - - if (DEBUG) - printf("message received: %s\n", buf); - - /* double-fork taken from dzen2/util.c; avoids zombie processes - * without requiring a signal handler. */ - if (fork() == 0) { - if (fork() == 0) { - message = parse_message(buf); - handle_message(message); - exit(EXIT_SUCCESS); - } - exit(EXIT_SUCCESS); + if (n < 0) { + perror("error receiving from socket"); + exit(EXIT_FAILURE); } - wait(0); + + handle_message(buf); } } -/* }}} */