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