]> Dogcows Code - chaz/openbox/blob - plugins/menu/fifo_menu.c
layers submenu on client
[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
8 #include "kernel/menu.h"
9 #include "kernel/event.h"
10
11 static char *PLUGIN_NAME = "fifo_menu";
12
13 typedef struct Fifo_Menu_Data{
14 char *fifo;
15 char *buf; /* buffer to hold partially read menu */
16 unsigned long buflen; /* how many bytes are in the buffer */
17 int fd; /* file descriptor to read menu from */
18 event_fd_handler *handler;
19 } Fifo_Menu_Data;
20
21 #define FIFO_MENU(m) ((Menu *)m)
22 #define FIFO_MENU_DATA(m) ((Fifo_Menu_Data *)((Menu *)m)->plugin_data)
23
24
25 void fifo_menu_clean_up(Menu *m) {
26 if (FIFO_MENU_DATA(m)->buf != NULL) {
27 g_free(FIFO_MENU_DATA(m)->buf);
28 FIFO_MENU_DATA(m)->buf = NULL;
29 FIFO_MENU_DATA(m)->buflen = 0;
30 }
31
32 if (FIFO_MENU_DATA(m)->fd != -1) {
33 close(FIFO_MENU_DATA(m)->fd);
34 FIFO_MENU_DATA(m)->fd = -1;
35 }
36 }
37
38 void plugin_setup_config() { }
39 void plugin_startup()
40 { }
41 void plugin_shutdown() { }
42
43 void fifo_menu_handler(int fd, Menu *menu) {
44 char *tmpbuf = NULL;
45 unsigned long num_read;
46 #ifdef DEBUG
47 /* because gdb is dumb */
48 Fifo_Menu_Data *d = FIFO_MENU_DATA(menu);
49 #endif
50
51 /* if the menu is shown this will go into busy loop :(
52 fix me*/
53 if (!menu->shown) {
54 unsigned long num_realloc;
55 /* if we have less than a quarter BUFSIZ left, allocate more */
56 num_realloc = (BUFSIZ - (FIFO_MENU_DATA(menu)->buflen % BUFSIZ) <
57 BUFSIZ >> 2) ?
58 0 : BUFSIZ;
59
60 tmpbuf = g_try_realloc(FIFO_MENU_DATA(menu)->buf,
61 FIFO_MENU_DATA(menu)->buflen + num_realloc);
62
63 if (tmpbuf == NULL) {
64 g_warning("Unable to allocate memory for read()");
65 return;
66 }
67
68 FIFO_MENU_DATA(menu)->buf = tmpbuf;
69
70 num_read = read(fd,
71 FIFO_MENU_DATA(menu)->buf + FIFO_MENU_DATA(menu)->buflen,
72 num_realloc);
73
74 if (num_read == 0) { /* eof */
75 unsigned long count = 0;
76 char *found = NULL;
77
78 menu->invalid = TRUE;
79 menu_clear(menu);
80
81 /* TEMP: list them */
82 while (NULL !=
83 (found = strchr(&FIFO_MENU_DATA(menu)->buf[count], '\n'))) {
84 FIFO_MENU_DATA(menu)->buf
85 [found - FIFO_MENU_DATA(menu)->buf] = '\0';
86 menu_add_entry(menu,
87 menu_entry_new_separator
88 (&FIFO_MENU_DATA(menu)->buf[count]));
89 count = found - FIFO_MENU_DATA(menu)->buf + 1;
90 }
91
92 FIFO_MENU_DATA(menu)->buf[FIFO_MENU_DATA(menu)->buflen] = '\0';
93 fifo_menu_clean_up(menu);
94
95 event_remove_fd(FIFO_MENU_DATA(menu)->handler->fd);
96
97 if ((FIFO_MENU_DATA(menu)->fd =
98 open(FIFO_MENU_DATA(menu)->fifo, O_NONBLOCK | O_RDONLY)) == -1) {
99 g_warning("Can't reopen FIFO");
100 fifo_menu_clean_up(menu);
101 return;
102 }
103
104 FIFO_MENU_DATA(menu)->handler->fd = FIFO_MENU_DATA(menu)->fd;
105
106 event_add_fd_handler(FIFO_MENU_DATA(menu)->handler);
107 } else if (num_read > 0) {
108 FIFO_MENU_DATA(menu)->buflen += num_read;
109 FIFO_MENU_DATA(menu)->buf[FIFO_MENU_DATA(menu)->buflen] = '\0';
110 }
111 }
112 }
113
114 void plugin_destroy (Menu *m)
115 {
116 fifo_menu_clean_up(m);
117 if (FIFO_MENU_DATA(m)->handler != NULL) {
118 g_free(FIFO_MENU_DATA(m)->handler);
119 FIFO_MENU_DATA(m)->handler = NULL;
120 }
121
122 if (FIFO_MENU_DATA(m)->fifo != NULL) {
123 g_free(FIFO_MENU_DATA(m)->fifo);
124 FIFO_MENU_DATA(m)->fifo = NULL;
125 }
126
127 g_free(m->plugin_data);
128
129 menu_free(m->name);
130 }
131
132 void *plugin_create() /* TODO: need config */
133 {
134 char *fifo;
135 char *dir;
136 event_fd_handler *h;
137
138 Fifo_Menu_Data *d = g_new(Fifo_Menu_Data, 1);
139 Menu *m = menu_new("", PLUGIN_NAME, NULL);
140
141 d->fd = -1;
142 d->buf = NULL;
143 d->buflen = 0;
144 d->handler = NULL;
145
146 m->plugin = PLUGIN_NAME;
147
148 d->fd = -1;
149
150 m->plugin_data = (void *)d;
151
152 dir = g_build_filename(g_get_home_dir(), ".openbox", PLUGIN_NAME, NULL);
153
154 if (mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO) == -1 && errno != EEXIST) {
155 /* technically, if ~/.openbox/fifo_menu exists and isn't a directory
156 this will fail, but we don't care because mkfifo will fail and warn
157 anyway */
158 g_warning("Can't create %s: %s", dir, strerror(errno));
159 g_free(dir);
160 plugin_destroy(m);
161 return NULL;
162 }
163
164 fifo = g_build_filename(g_get_home_dir(), ".openbox", PLUGIN_NAME,
165 m->name, NULL);
166 if (mkfifo(fifo, S_IRUSR | S_IWUSR |
167 S_IRGRP | S_IWGRP | /* let umask do its thing */
168 S_IROTH | S_IWOTH) == -1 && errno != EEXIST) {
169 g_warning("Can't create FIFO %s: %s", fifo, strerror(errno));
170 g_free(fifo);
171 g_free(d);
172 menu_free(m->name);
173 return NULL;
174 }
175
176 /* open in non-blocking mode so we don't wait for a process to open FIFO
177 for writing */
178 if ((d->fd = open(fifo, O_NONBLOCK | O_RDONLY)) == -1) {
179 g_warning("Can't open FIFO %s: %s", fifo, strerror(errno));
180 g_free(fifo);
181 g_free(d);
182 menu_free(m->name);
183 return NULL;
184 }
185
186 d->fifo = fifo;
187
188 h = g_new(event_fd_handler, 1);
189
190 if (h == NULL) {
191 g_warning("Out of memory");
192 close(d->fd);
193 g_free(fifo);
194 g_free(d);
195 menu_free(m->name);
196 return NULL;
197 }
198
199 h->fd = d->fd;
200 h->data = m;
201 h->handler = fifo_menu_handler;
202 d->handler = h;
203
204 event_add_fd_handler(h);
205
206 g_free(dir);
207 return (void *)m;
208 }
This page took 0.041096 seconds and 4 git commands to generate.