Mercurial > ~mikael > mcabber > hg
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... */ |