Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- a simple c notification handler
- by mjheagle
- */
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <sys/socket.h>
- #include <sys/un.h>
- #include <stdio.h>
- #include <string.h>
- #include <time.h>
- #include <fcntl.h>
- #include <signal.h>
- #include "config.h"
- /* struct definitions */
- struct msg
- {
- char *id; /* id of message, to allow overwriting */
- int tstart; /* time of message sending */
- int dur; /* duration time of the message */
- char *body; /* body of the message */
- };
- /* function declarations */
- void cleanup();
- void daemonize();
- void errorout(const char *);
- void log_message(const char *);
- void notify_daemon();
- void notify_send(struct msg *);
- void signal_handler(int);
- /* main */
- int
- main(int argc, char *argv[])
- {
- /* assign default values */
- struct msg message;
- message.id = (char *)malloc(sizeof('a')*IDLEN);
- sprintf(message.id, "%d", (int)time(NULL));
- message.tstart = (int)time(NULL);
- message.dur = 10;
- /* parse arguments */
- int c, mode;
- while ((c = getopt(argc, argv, "ds:qi:l:")) != -1)
- {
- switch (c)
- {
- case 'd':
- printf("daemon mode\n");
- mode = 0;
- break;
- case 's':
- printf("send new message mode\n");
- message.body = optarg;
- mode = 1;
- break;
- case 'q':
- printf("query current messages mode\n");
- mode = 2;
- break;
- case 'i':
- message.id = optarg;
- break;
- case 'l':
- message.dur = atoi(optarg);
- break;
- case '?':
- break;
- default:
- return 1;
- }
- }
- /* take action based on arguments */
- switch (mode)
- {
- case 0:
- notify_daemon();
- break;
- case 1:
- notify_send(&message);
- break;
- case 2:
- break;
- default:
- printf("error: parsing options\n");
- return 1;
- }
- return 0;
- }
- /* function definitions */
- /* cleanup {{{ */
- void
- cleanup()
- {
- /* remove files after run complete */
- unlink(SOCKET);
- unlink(LOCKFILE);
- }
- /* }}} */
- /* daemonize {{{ */
- void
- daemonize()
- {
- /* fork process to background and disassociate with terminal */
- int i, lfp;
- char str[10];
- i = fork();
- if (i<0)
- errorout("forking");
- if (i>0) /* exit parent */
- exit(0);
- setsid(); /* get new process group */
- /* handle stdio */
- /*
- i = open("/dev/null", O_RDWR);
- dup(i);
- dup(i);
- */
- /* catch signals */
- signal(SIGCHLD, SIG_IGN);
- signal(SIGHUP, signal_handler);
- signal(SIGTERM, signal_handler);
- chdir(WORKDIR); /* change to working directory */
- /* TODO check if lock file exists and die */
- lfp = open(LOCKFILE, O_RDWR|O_CREAT, 0640);
- if (lfp < 0)
- errorout("opening lockfile");
- if (lockf(lfp, F_TLOCK, 0)<0)
- errorout("locking");
- sprintf(str, "%d\n", getpid());
- write(lfp, str, strlen(str));
- }
- /* }}} */
- /* signal_handler {{{ */
- void
- signal_handler(int sig)
- {
- switch(sig)
- {
- case SIGHUP:
- log_message("restarting: hangup signal caught");
- cleanup();
- exit(0);
- break;
- case SIGTERM:
- log_message("exiting: terminate signal caught");
- cleanup();
- exit(0);
- break;
- }
- }
- /* }}} */
- /* log_message {{{ */
- void
- log_message(const char *message)
- {
- /* log a message from the daemon */
- FILE *fp;
- fp = fopen(LOGFILE, "a");
- fprintf(fp, "%s\n", message);
- fclose(fp);
- }
- /* }}} */
- /* notify_daemon {{{ */
- void
- notify_daemon()
- {
- int sockfd, newsockfd, servlen, n;
- socklen_t clilen;
- struct sockaddr_un cli_addr, serv_addr;
- char buffer[80], buf2[128];
- daemonize();
- if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
- errorout("creating socket");
- bzero((char *) &serv_addr, sizeof(serv_addr));
- serv_addr.sun_family = AF_UNIX;
- strcpy(serv_addr.sun_path, SOCKET);
- servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family);
- if(bind(sockfd,(struct sockaddr *)&serv_addr, servlen)<0)
- errorout("binding socket");
- log_message("daemon started, socket listening");
- while (1)
- {
- struct msg message;
- listen(sockfd, 5);
- clilen = sizeof(cli_addr);
- newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
- if (newsockfd < 0)
- errorout("accepting");
- log_message("accepted");
- n = read(newsockfd, buffer, 80);
- if (n<0)
- errorout("Reading socket");
- log_message("socket read");
- message.body = (char *)malloc(sizeof(char)*BODYLEN);
- message.id = (char *)malloc(sizeof(char)*IDLEN);
- sscanf(buffer, "%[^|]|%[^|]|%d|%d", message.body, message.id, &message.dur, &message.tstart); /* this is failing */
- sprintf(buf2, "message successfully recieved: body=%s, id=%s, raw=%s", message.body, message.id, buffer);
- log_message(buf2);
- write(newsockfd, "ACK", 3);
- close(newsockfd);
- }
- close(sockfd);
- }
- /* }}} */
- /* notify_send {{{ */
- void
- notify_send(struct msg *message)
- {
- //printf("message: %s\nid: %s\nduration: %d\n", message->body, message->id, message->dur);
- int sockfd, servlen, n;
- struct sockaddr_un serv_addr;
- char buffer[82], msgbuf[IDLEN+BODYLEN];
- chdir(WORKDIR); /* change to working directory */
- bzero((char *) &serv_addr, sizeof(serv_addr));
- serv_addr.sun_family = AF_UNIX;
- strcpy(serv_addr.sun_path, SOCKET);
- servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family);
- if ((sockfd = socket(AF_UNIX, SOCK_STREAM,0)) < 0)
- errorout("Creating socket");
- if (connect(sockfd, (struct sockaddr *) &serv_addr, servlen) < 0)
- errorout("Connecting");
- bzero(buffer, 82);
- bzero(msgbuf, IDLEN+BODYLEN);
- sprintf(msgbuf, "%s|%s|%d|%d", message->body, message->id, message->dur, message->tstart);
- printf("%s\n", msgbuf);
- write(sockfd, message->body, strlen(message->body));
- n = read(sockfd, msgbuf, IDLEN+BODYLEN);
- if (n<0)
- errorout("Reading socket");
- if (strcmp(buffer, "ACK") == 0)
- printf("transmission successful.\n");
- close(sockfd);
- }
- /* }}} */
- /* errorout {{{ */
- void
- errorout(const char *msg)
- {
- char buffer[80];
- sprintf(buffer, "error: %s", msg);
- log_message(buffer);
- perror(msg);
- exit(0);
- }
- /* }}} */
Advertisement
Add Comment
Please, Sign In to add comment