mcabber/src/fifo.c
changeset 1426 a64778f5f26b
child 1427 a8eb9aba2ed2
equal deleted inserted replaced
1425:b0cfd9ab4b9f 1426:a64778f5f26b
       
     1 /*
       
     2  * fifo.c       -- Read commands from a named pipe
       
     3  *
       
     4  * Copyright (C) 2008 Mikael Berthe <mikael@lilotux.net>
       
     5  *
       
     6  * This program is free software; you can redistribute it and/or modify
       
     7  * it under the terms of the GNU General Public License as published by
       
     8  * the Free Software Foundation; either version 2 of the License, or (at
       
     9  * your option) any later version.
       
    10  *
       
    11  * This program is distributed in the hope that it will be useful, but
       
    12  * WITHOUT ANY WARRANTY; without even the implied warranty of
       
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    14  * General Public License for more details.
       
    15  *
       
    16  * You should have received a copy of the GNU General Public License
       
    17  * along with this program; if not, write to the Free Software
       
    18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
       
    19  * USA
       
    20  */
       
    21 
       
    22 #include <stdio.h>
       
    23 #include <glib.h>
       
    24 #include <sys/types.h>
       
    25 #include <sys/stat.h>
       
    26 #include <fcntl.h>
       
    27 #include <unistd.h>
       
    28 #include <sys/time.h>
       
    29 #include <errno.h>
       
    30 #include <fcntl.h>
       
    31 
       
    32 #include "commands.h"
       
    33 #include "logprint.h"
       
    34 #include "utils.h"
       
    35 
       
    36 #include "hbuf.h"   // For HBB_BLOCKSIZE
       
    37 
       
    38 static FILE *sfd;
       
    39 static char *fifo_name;
       
    40 
       
    41 
       
    42 //  fifo_init(fifo_path)
       
    43 // Create and open the FIFO file.
       
    44 // If fifo_path is NULL, reopen the current pipe.
       
    45 // Return 0 (success) or -1 (failure).
       
    46 int fifo_init(const char *fifo_path)
       
    47 {
       
    48   struct stat buf;
       
    49   int fd;
       
    50   char *fifo_path_xp;
       
    51 
       
    52   if (!sfd && !fifo_path)
       
    53     return -1;  // Nothing to do...
       
    54 
       
    55   if (sfd && !fifo_path) {  // We want to reinitialize the pipe
       
    56     fclose(sfd);
       
    57     sfd = NULL;
       
    58     if (fifo_name)
       
    59       goto fifo_init_open;
       
    60   }
       
    61   sfd = NULL;
       
    62 
       
    63   fifo_path_xp = expand_filename(fifo_path);
       
    64 
       
    65   if (!stat(fifo_path_xp, &buf)) {
       
    66     if (!S_ISFIFO(buf.st_mode)) {
       
    67       scr_LogPrint(LPRINT_LOGNORM, "WARNING: Cannot create the FIFO. "
       
    68                    "%s already exists and is not a pipe", fifo_path_xp);
       
    69       g_free(fifo_path_xp);
       
    70       return -1;
       
    71     }
       
    72 
       
    73     if (unlink(fifo_path_xp)) {
       
    74       scr_LogPrint(LPRINT_LOGNORM, "WARNING: Unable to unlink FIFO %s [%s]",
       
    75                    fifo_path_xp, g_strerror(errno));
       
    76       g_free(fifo_path_xp);
       
    77       return -1;
       
    78     }
       
    79   }
       
    80 
       
    81   if (mkfifo(fifo_path_xp, S_IWUSR | S_IRUSR)) {
       
    82     scr_LogPrint(LPRINT_LOGNORM, "WARNING: Cannot create the FIFO [%s]",
       
    83                  g_strerror(errno));
       
    84     g_free(fifo_path_xp);
       
    85     return -1;
       
    86   }
       
    87 
       
    88   fifo_name = fifo_path_xp;
       
    89 
       
    90 fifo_init_open:
       
    91   fd = open(fifo_name, O_RDONLY | O_NONBLOCK);
       
    92   if (!fd)
       
    93     return -1;
       
    94 
       
    95   sfd = fdopen(fd, "r");
       
    96   if (fifo_path)
       
    97     scr_LogPrint(LPRINT_LOGNORM, "FIFO initialized (%s)", fifo_name);
       
    98   return 0;
       
    99 }
       
   100 
       
   101 //  fifo_deinit()
       
   102 // Close the current FIFO pipe and delete it.
       
   103 void fifo_deinit(void)
       
   104 {
       
   105   if (sfd) {
       
   106     fclose(sfd);
       
   107     sfd = NULL;
       
   108   }
       
   109   if (fifo_name) {
       
   110     unlink(fifo_name);
       
   111     g_free(fifo_name);
       
   112     fifo_name = NULL;
       
   113   }
       
   114 }
       
   115 
       
   116 //  fifo_read()
       
   117 // Read a line from the FIFO pipe (if available), and execute it.
       
   118 void fifo_read(void)
       
   119 {
       
   120   struct timeval tv;
       
   121   fd_set fds;
       
   122   char *getbuf;
       
   123   char buf[HBB_BLOCKSIZE+1];
       
   124   int fd;
       
   125 
       
   126   if (!sfd) {
       
   127     return;
       
   128   }
       
   129 
       
   130   tv.tv_sec = 0;
       
   131   tv.tv_usec = 0;
       
   132 
       
   133   fd = fileno(sfd);
       
   134 
       
   135   FD_ZERO(&fds);
       
   136   FD_SET(fd, &fds);
       
   137 
       
   138   select(fd + 1, &fds, NULL, NULL, &tv);
       
   139 
       
   140   if (!FD_ISSET(fd, &fds)) {
       
   141     return;
       
   142   }
       
   143 
       
   144   getbuf = fgets(buf, HBB_BLOCKSIZE, sfd);
       
   145   if (getbuf) {
       
   146     char *eol = buf;
       
   147 
       
   148     // Strip trailing newlines
       
   149     for ( ; *eol ; eol++)
       
   150       ;
       
   151     if (eol > buf)
       
   152       eol--;
       
   153     while (eol > buf && *eol == '\n')
       
   154       *eol-- = 0;
       
   155 
       
   156     scr_LogPrint(LPRINT_LOGNORM, "Executing FIFO command: %s", buf);
       
   157     if (process_command(buf, TRUE) == 255)
       
   158       mcabber_set_terminate_ui();
       
   159   } else {
       
   160     if (feof(sfd))
       
   161       fifo_init(NULL);  // Reopen the FIFO on EOF
       
   162   }
       
   163 }
       
   164 
       
   165 //  fifo_get_fd()
       
   166 // Return the FIFO file descriptor (-1 if none).
       
   167 int fifo_get_fd(void)
       
   168 {
       
   169   if (sfd)
       
   170     return fileno(sfd);
       
   171   return -1;
       
   172 }
       
   173 
       
   174 /* vim: set expandtab cindent cinoptions=>2\:2(0:  For Vim users... */