]> Dogcows Code - chaz/openbox/blob - plugins/menu/fifo_menu.c
71326225974ec18d5a49ea54cc13f78ccce96226
[chaz/openbox] / plugins / menu / fifo_menu.c
1 #include <glib.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <string.h>
8 #include <stdio.h>
9
10 #include "kernel/menu.h"
11 #include "kernel/event.h"
12
13 static char *PLUGIN_NAME = "fifo_menu";
14
15 typedef struct Fifo_Menu_Data {
16 char *fifo;
17 char *buf; /* buffer to hold partially read menu */
18 unsigned long buflen; /* how many bytes are in the buffer */
19 int fd; /* file descriptor to read menu from */
20 gboolean use_pid;
21 event_fd_handler *handler;
22 } Fifo_Menu_Data;
23
24 #define FIFO_MENU(m) ((ObMenu *)m)
25 #define FIFO_MENU_DATA(m) ((Fifo_Menu_Data *)((ObMenu *)m)->plugin_data)
26
27
28 void fifo_menu_clean_up(ObMenu *m) {
29 if (FIFO_MENU_DATA(m)->buf != NULL) {
30 g_free(FIFO_MENU_DATA(m)->buf);
31 FIFO_MENU_DATA(m)->buf = NULL;
32 FIFO_MENU_DATA(m)->buflen = 0;
33 }
34
35 if (FIFO_MENU_DATA(m)->fd != -1) {
36 close(FIFO_MENU_DATA(m)->fd);
37 FIFO_MENU_DATA(m)->fd = -1;
38 }
39 }
40
41 void plugin_setup_config() { }
42 void plugin_startup()
43 { }
44 void plugin_shutdown() { }
45
46 void fifo_menu_handler(int fd, void *d) {
47 ObMenu *menu = d;
48 char *tmpbuf = NULL;
49 unsigned long num_read;
50 #ifdef DEBUG
51 /* because gdb is dumb */
52 #if 0
53 Fifo_Menu_Data *d = FIFO_MENU_DATA(menu);
54 #endif
55 #endif
56
57 /* if the menu is shown this will go into busy loop :(
58 fix me*/
59 if (!menu->shown) {
60 unsigned long num_realloc;
61 /* if we have less than a quarter BUFSIZ left, allocate more */
62 num_realloc = (BUFSIZ - (FIFO_MENU_DATA(menu)->buflen % BUFSIZ) <
63 BUFSIZ >> 2) ?
64 0 : BUFSIZ;
65
66 tmpbuf = g_try_realloc(FIFO_MENU_DATA(menu)->buf,
67 FIFO_MENU_DATA(menu)->buflen + num_realloc);
68
69 if (tmpbuf == NULL) {
70 g_warning("Unable to allocate memory for read()");
71 return;
72 }
73
74 FIFO_MENU_DATA(menu)->buf = tmpbuf;
75
76 num_read = read(fd,
77 FIFO_MENU_DATA(menu)->buf +
78 FIFO_MENU_DATA(menu)->buflen,
79 num_realloc);
80
81 if (num_read == 0) { /* eof */
82 xmlDocPtr doc;
83 xmlNodePtr node;
84
85 menu->invalid = TRUE;
86 menu_clear(menu);
87
88 FIFO_MENU_DATA(menu)->buf[FIFO_MENU_DATA(menu)->buflen] = '\0';
89
90 doc = xmlParseMemory(FIFO_MENU_DATA(menu)->buf,
91 FIFO_MENU_DATA(menu)->buflen);
92
93 node = xmlDocGetRootElement(doc);
94
95 if (node &&
96 !xmlStrcasecmp(node->name, (const xmlChar*) "fifo_menu")) {
97 if ((node = parse_find_node("item", node->xmlChildrenNode)))
98 parse_menu_full(doc, node, menu, FALSE);
99 }
100
101 fifo_menu_clean_up(menu);
102
103 event_remove_fd(FIFO_MENU_DATA(menu)->handler->fd);
104
105 if ((FIFO_MENU_DATA(menu)->fd =
106 open(FIFO_MENU_DATA(menu)->fifo,
107 O_NONBLOCK | O_RDONLY)) == -1) {
108 g_warning("Can't reopen FIFO");
109 fifo_menu_clean_up(menu);
110 return;
111 }
112
113 FIFO_MENU_DATA(menu)->handler->fd = FIFO_MENU_DATA(menu)->fd;
114
115 event_add_fd_handler(FIFO_MENU_DATA(menu)->handler);
116 } else if (num_read > 0) {
117 FIFO_MENU_DATA(menu)->buflen += num_read;
118 FIFO_MENU_DATA(menu)->buf[FIFO_MENU_DATA(menu)->buflen] = '\0';
119 }
120 }
121 }
122
123 void plugin_destroy (ObMenu *m)
124 {
125 fifo_menu_clean_up(m);
126 if (FIFO_MENU_DATA(m)->handler != NULL) {
127 g_free(FIFO_MENU_DATA(m)->handler);
128 FIFO_MENU_DATA(m)->handler = NULL;
129 }
130
131 if (FIFO_MENU_DATA(m)->fifo != NULL) {
132 g_free(FIFO_MENU_DATA(m)->fifo);
133 FIFO_MENU_DATA(m)->fifo = NULL;
134 }
135
136 g_free(m->plugin_data);
137
138 menu_free(m->name);
139 }
140
141 void *plugin_create(PluginMenuCreateData *data)
142 {
143 char *fifo;
144 char *dir;
145 event_fd_handler *h;
146 Fifo_Menu_Data *d;
147 ObMenu *m;
148 char *label = NULL, *id = NULL;
149 char *attr_pid = NULL;
150
151 d = g_new(Fifo_Menu_Data, 1);
152
153 parse_attr_string("id", data->node, &id);
154 parse_attr_string("label", data->node, &label);
155
156 if (parse_attr_string("pid", data->node, &attr_pid) &&
157 g_strcasecmp(attr_pid, "true") == 0) {
158 d->use_pid = TRUE;
159 } else
160 d->use_pid = FALSE;
161
162 m = menu_new( (label != NULL ? label : ""),
163 (id != NULL ? id : PLUGIN_NAME),
164 data->parent);
165 menu_add_entry(data->parent, menu_entry_new_submenu(
166 (label != NULL ? label : ""),
167 m));
168
169 g_free(label);
170 g_free(id);
171 d->fd = -1;
172 d->buf = NULL;
173 d->buflen = 0;
174 d->handler = NULL;
175
176 m->plugin = PLUGIN_NAME;
177
178 d->fd = -1;
179
180 m->plugin_data = (void *)d;
181
182
183 dir = g_build_filename(g_get_home_dir(), ".openbox",
184 PLUGIN_NAME, NULL);
185
186 if (mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO) == -1 && errno != EEXIST) {
187 /* technically, if ~/.openbox/fifo_menu exists and isn't a directory
188 this will fail, but we don't care because mkfifo will fail and warn
189 anyway */
190 g_warning("Can't create %s: %s", dir, strerror(errno));
191 g_free(dir);
192 plugin_destroy(m);
193 return NULL;
194 }
195
196 if (d->use_pid)
197 {
198 char *pid = g_strdup_printf("%s.%d", m->name, getpid());
199 fifo = g_build_filename(g_get_home_dir(), ".openbox",
200 PLUGIN_NAME,
201 pid, NULL);
202 g_free(pid);
203 } else {
204 fifo = g_build_filename(g_get_home_dir(), ".openbox",
205 PLUGIN_NAME,
206 m->name, NULL);
207 }
208
209 if (mkfifo(fifo, S_IRUSR | S_IWUSR |
210 S_IRGRP | S_IWGRP | /* let umask do its thing */
211 S_IROTH | S_IWOTH) == -1 && errno != EEXIST) {
212 g_warning("Can't create FIFO %s: %s", fifo, strerror(errno));
213 g_free(fifo);
214 g_free(d);
215 menu_free(m->name);
216 return NULL;
217 }
218
219 /* open in non-blocking mode so we don't wait for a process to open FIFO
220 for writing */
221 if ((d->fd = open(fifo, O_NONBLOCK | O_RDONLY)) == -1) {
222 g_warning("Can't open FIFO %s: %s", fifo, strerror(errno));
223 g_free(fifo);
224 g_free(d);
225 menu_free(m->name);
226 return NULL;
227 }
228
229 d->fifo = fifo;
230
231 h = g_new(event_fd_handler, 1);
232
233 if (h == NULL) {
234 g_warning("Out of memory");
235 close(d->fd);
236 g_free(fifo);
237 g_free(d);
238 menu_free(m->name);
239 return NULL;
240 }
241
242 h->fd = d->fd;
243 h->data = m;
244 h->handler = fifo_menu_handler;
245 d->handler = h;
246
247 event_add_fd_handler(h);
248
249 g_free(dir);
250 return (void *)m;
251 }
This page took 0.043138 seconds and 3 git commands to generate.