Guest User

notify.c

a guest
Jun 25th, 2011
285
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.98 KB | None | 0 0
  1. /*
  2. a simple c notification handler
  3. by mjheagle
  4. */
  5. #include <sys/types.h>
  6. #include <unistd.h>
  7. #include <stdlib.h>
  8. #include <sys/socket.h>
  9. #include <sys/un.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <time.h>
  13. #include <fcntl.h>
  14. #include <signal.h>
  15. #include "config.h"
  16.  
  17. /* struct definitions */
  18. struct msg
  19. {
  20.         char *id;               /* id of message, to allow overwriting */
  21.         int tstart;             /* time of message sending */
  22.         int dur;                /* duration time of the message */
  23.         char *body;             /* body of the message */
  24. };
  25.  
  26. /* function declarations */
  27. void cleanup();
  28. void daemonize();
  29. void errorout(const char *);
  30. void log_message(const char *);
  31. void notify_daemon();
  32. void notify_send(struct msg *);
  33. void signal_handler(int);
  34.  
  35. /* main */
  36. int
  37. main(int argc, char *argv[])
  38. {
  39.         /* assign default values */
  40.         struct msg message;
  41.         message.id = (char *)malloc(sizeof('a')*IDLEN);
  42.         sprintf(message.id, "%d", (int)time(NULL));
  43.         message.tstart = (int)time(NULL);
  44.         message.dur = 10;
  45.  
  46.         /* parse arguments */
  47.         int c, mode;
  48.         while ((c = getopt(argc, argv, "ds:qi:l:")) != -1)
  49.         {
  50.                 switch (c)
  51.                 {
  52.                         case 'd':
  53.                                 printf("daemon mode\n");
  54.                                 mode = 0;
  55.                                 break;
  56.                         case 's':
  57.                                 printf("send new message mode\n");
  58.                                 message.body = optarg;
  59.                                 mode = 1;
  60.                                 break;
  61.                         case 'q':
  62.                                 printf("query current messages mode\n");
  63.                                 mode = 2;
  64.                                 break;
  65.                         case 'i':
  66.                                 message.id = optarg;
  67.                                 break;
  68.                         case 'l':
  69.                                 message.dur = atoi(optarg);
  70.                                 break;
  71.                         case '?':
  72.                                 break;
  73.                         default:
  74.                                 return 1;
  75.                 }
  76.         }
  77.  
  78.         /* take action based on arguments */
  79.         switch (mode)
  80.         {
  81.                 case 0:
  82.                         notify_daemon();
  83.                         break;
  84.                 case 1:
  85.                         notify_send(&message);
  86.                         break;
  87.                 case 2:
  88.                         break;
  89.                 default:
  90.                         printf("error: parsing options\n");
  91.                         return 1;
  92.         }
  93.  
  94.         return 0;
  95. }
  96.  
  97. /* function definitions */
  98. /* cleanup {{{ */
  99. void
  100. cleanup()
  101. {
  102.         /* remove files after run complete */
  103.         unlink(SOCKET);
  104.         unlink(LOCKFILE);
  105. }
  106. /* }}} */
  107.  
  108. /* daemonize {{{ */
  109. void
  110. daemonize()
  111. {
  112.         /* fork process to background and disassociate with terminal */
  113.         int i, lfp;
  114.         char str[10];
  115.  
  116.         i = fork();
  117.         if (i<0)
  118.                 errorout("forking");
  119.         if (i>0) /* exit parent */
  120.                 exit(0);
  121.         setsid(); /* get new process group */
  122.  
  123.         /* handle stdio */
  124.         /*
  125.         i = open("/dev/null", O_RDWR);
  126.         dup(i);
  127.         dup(i);
  128.         */
  129.  
  130.         /* catch signals */
  131.         signal(SIGCHLD, SIG_IGN);
  132.         signal(SIGHUP, signal_handler);
  133.         signal(SIGTERM, signal_handler);
  134.  
  135.         chdir(WORKDIR); /* change to working directory */
  136.         /* TODO check if lock file exists and die */
  137.         lfp = open(LOCKFILE, O_RDWR|O_CREAT, 0640);
  138.         if (lfp < 0)
  139.                 errorout("opening lockfile");
  140.         if (lockf(lfp, F_TLOCK, 0)<0)
  141.                 errorout("locking");
  142.         sprintf(str, "%d\n", getpid());
  143.         write(lfp, str, strlen(str));
  144. }
  145. /* }}} */
  146.  
  147. /* signal_handler {{{ */
  148. void
  149. signal_handler(int sig)
  150. {
  151.         switch(sig)
  152.         {
  153.                 case SIGHUP:
  154.                         log_message("restarting: hangup signal caught");
  155.                         cleanup();
  156.                         exit(0);
  157.                         break;
  158.                 case SIGTERM:
  159.                         log_message("exiting: terminate signal caught");
  160.                         cleanup();
  161.                         exit(0);
  162.                         break;
  163.         }
  164. }
  165. /* }}} */
  166.  
  167. /* log_message {{{ */
  168. void
  169. log_message(const char *message)
  170. {
  171.         /* log a message from the daemon */
  172.         FILE *fp;
  173.         fp = fopen(LOGFILE, "a");
  174.         fprintf(fp, "%s\n", message);
  175.         fclose(fp);
  176. }
  177. /* }}} */
  178.  
  179. /* notify_daemon {{{ */
  180. void
  181. notify_daemon()
  182. {
  183.         int sockfd, newsockfd, servlen, n;
  184.         socklen_t clilen;
  185.         struct sockaddr_un cli_addr, serv_addr;
  186.         char buffer[80], buf2[128];
  187.  
  188.         daemonize();
  189.  
  190.         if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
  191.                 errorout("creating socket");
  192.         bzero((char *) &serv_addr, sizeof(serv_addr));
  193.         serv_addr.sun_family = AF_UNIX;
  194.         strcpy(serv_addr.sun_path, SOCKET);
  195.         servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family);
  196.         if(bind(sockfd,(struct sockaddr *)&serv_addr, servlen)<0)
  197.                 errorout("binding socket");
  198.         log_message("daemon started, socket listening");
  199.         while (1)
  200.         {
  201.                 struct msg message;
  202.                 listen(sockfd, 5);
  203.                 clilen = sizeof(cli_addr);
  204.                 newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
  205.                 if (newsockfd < 0)
  206.                         errorout("accepting");
  207.                 log_message("accepted");
  208.                 n = read(newsockfd, buffer, 80);
  209.                 if (n<0)
  210.                         errorout("Reading socket");
  211.                 log_message("socket read");
  212.                 message.body = (char *)malloc(sizeof(char)*BODYLEN);
  213.                 message.id = (char *)malloc(sizeof(char)*IDLEN);
  214.                 sscanf(buffer, "%[^|]|%[^|]|%d|%d", message.body, message.id, &message.dur, &message.tstart); /* this is failing */
  215.                 sprintf(buf2, "message successfully recieved: body=%s, id=%s, raw=%s", message.body, message.id, buffer);
  216.                 log_message(buf2);
  217.                 write(newsockfd, "ACK", 3);
  218.                 close(newsockfd);
  219.         }
  220.         close(sockfd);
  221. }
  222. /* }}} */
  223.  
  224. /* notify_send {{{ */
  225. void
  226. notify_send(struct msg *message)
  227. {
  228.         //printf("message: %s\nid: %s\nduration: %d\n", message->body, message->id, message->dur);
  229.         int sockfd, servlen, n;
  230.         struct sockaddr_un  serv_addr;
  231.         char buffer[82], msgbuf[IDLEN+BODYLEN];
  232.  
  233.         chdir(WORKDIR); /* change to working directory */
  234.         bzero((char *) &serv_addr, sizeof(serv_addr));
  235.         serv_addr.sun_family = AF_UNIX;
  236.         strcpy(serv_addr.sun_path, SOCKET);
  237.         servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family);
  238.         if ((sockfd = socket(AF_UNIX, SOCK_STREAM,0)) < 0)
  239.                 errorout("Creating socket");
  240.         if (connect(sockfd, (struct sockaddr *) &serv_addr, servlen) < 0)
  241.                 errorout("Connecting");
  242.         bzero(buffer, 82);
  243.         bzero(msgbuf, IDLEN+BODYLEN);
  244.         sprintf(msgbuf, "%s|%s|%d|%d", message->body, message->id, message->dur, message->tstart);
  245.         printf("%s\n", msgbuf);
  246.         write(sockfd, message->body, strlen(message->body));
  247.         n = read(sockfd, msgbuf, IDLEN+BODYLEN);
  248.         if (n<0)
  249.                 errorout("Reading socket");
  250.         if (strcmp(buffer, "ACK") == 0)
  251.                 printf("transmission successful.\n");
  252.         close(sockfd);
  253. }
  254. /* }}} */
  255.  
  256. /* errorout {{{ */
  257. void
  258. errorout(const char *msg)
  259. {
  260.         char buffer[80];
  261.         sprintf(buffer, "error: %s", msg);
  262.         log_message(buffer);
  263.         perror(msg);
  264.         exit(0);
  265. }
  266. /* }}} */
Advertisement
Add Comment
Please, Sign In to add comment