comparison mcabber/src/fifo.c @ 1426:a64778f5f26b

Implement FIFO named command pipe
author Mikael Berthe <mikael@lilotux.net>
date Mon, 18 Feb 2008 22:59:37 +0100
parents
children a8eb9aba2ed2
comparison
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... */