10 #include "kernel/menu.h"
11 #include "kernel/event.h"
13 static char *PLUGIN_NAME = "fifo_menu";
15 typedef struct Fifo_Menu_Data {
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 */
21 event_fd_handler *handler;
24 #define FIFO_MENU(m) ((ObMenu *)m)
25 #define FIFO_MENU_DATA(m) ((Fifo_Menu_Data *)((ObMenu *)m)->plugin_data)
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;
35 if (FIFO_MENU_DATA(m)->fd != -1) {
36 close(FIFO_MENU_DATA(m)->fd);
37 FIFO_MENU_DATA(m)->fd = -1;
41 void plugin_setup_config() { }
44 void plugin_shutdown() { }
46 void fifo_menu_handler(int fd, void *d) {
49 unsigned long num_read;
51 /* because gdb is dumb */
53 Fifo_Menu_Data *d = FIFO_MENU_DATA(menu);
57 /* if the menu is shown this will go into busy loop :(
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) <
66 tmpbuf = g_try_realloc(FIFO_MENU_DATA(menu)->buf,
67 FIFO_MENU_DATA(menu)->buflen + num_realloc);
70 g_warning("Unable to allocate memory for read()");
74 FIFO_MENU_DATA(menu)->buf = tmpbuf;
77 FIFO_MENU_DATA(menu)->buf +
78 FIFO_MENU_DATA(menu)->buflen,
81 if (num_read == 0) { /* eof */
85 FIFO_MENU_DATA(menu)->buf[FIFO_MENU_DATA(menu)->buflen] = '\0';
87 xmlDocPtr doc = xmlParseMemory(FIFO_MENU_DATA(menu)->buf,
88 FIFO_MENU_DATA(menu)->buflen);
90 xmlNodePtr node = xmlDocGetRootElement(doc);
93 !xmlStrcasecmp(node->name, (const xmlChar*) "fifo_menu")) {
94 if ((node = parse_find_node("item", node->xmlChildrenNode)))
95 parse_menu_full(doc, node, menu, FALSE);
98 fifo_menu_clean_up(menu);
100 event_remove_fd(FIFO_MENU_DATA(menu)->handler->fd);
102 if ((FIFO_MENU_DATA(menu)->fd =
103 open(FIFO_MENU_DATA(menu)->fifo,
104 O_NONBLOCK | O_RDONLY)) == -1) {
105 g_warning("Can't reopen FIFO");
106 fifo_menu_clean_up(menu);
110 FIFO_MENU_DATA(menu)->handler->fd = FIFO_MENU_DATA(menu)->fd;
112 event_add_fd_handler(FIFO_MENU_DATA(menu)->handler);
113 } else if (num_read > 0) {
114 FIFO_MENU_DATA(menu)->buflen += num_read;
115 FIFO_MENU_DATA(menu)->buf[FIFO_MENU_DATA(menu)->buflen] = '\0';
120 void plugin_destroy (ObMenu *m)
122 fifo_menu_clean_up(m);
123 if (FIFO_MENU_DATA(m)->handler != NULL) {
124 g_free(FIFO_MENU_DATA(m)->handler);
125 FIFO_MENU_DATA(m)->handler = NULL;
128 if (FIFO_MENU_DATA(m)->fifo != NULL) {
129 g_free(FIFO_MENU_DATA(m)->fifo);
130 FIFO_MENU_DATA(m)->fifo = NULL;
133 g_free(m->plugin_data);
138 void *plugin_create(PluginMenuCreateData *data)
145 char *label = NULL, *id = NULL;
146 char *attr_pid = NULL;
148 d = g_new(Fifo_Menu_Data, 1);
150 parse_attr_string("id", data->node, &id);
151 parse_attr_string("label", data->node, &label);
153 if (parse_attr_string("pid", data->node, &attr_pid) &&
154 g_strcasecmp(attr_pid, "true") == 0) {
159 m = menu_new( (label != NULL ? label : ""),
160 (id != NULL ? id : PLUGIN_NAME),
162 menu_add_entry(data->parent, menu_entry_new_submenu(
163 (label != NULL ? label : ""),
173 m->plugin = PLUGIN_NAME;
177 m->plugin_data = (void *)d;
180 dir = g_build_filename(g_get_home_dir(), ".openbox",
183 if (mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO) == -1 && errno != EEXIST) {
184 /* technically, if ~/.openbox/fifo_menu exists and isn't a directory
185 this will fail, but we don't care because mkfifo will fail and warn
187 g_warning("Can't create %s: %s", dir, strerror(errno));
195 char *pid = g_strdup_printf("%s.%d", m->name, getpid());
196 fifo = g_build_filename(g_get_home_dir(), ".openbox",
201 fifo = g_build_filename(g_get_home_dir(), ".openbox",
206 if (mkfifo(fifo, S_IRUSR | S_IWUSR |
207 S_IRGRP | S_IWGRP | /* let umask do its thing */
208 S_IROTH | S_IWOTH) == -1 && errno != EEXIST) {
209 g_warning("Can't create FIFO %s: %s", fifo, strerror(errno));
216 /* open in non-blocking mode so we don't wait for a process to open FIFO
218 if ((d->fd = open(fifo, O_NONBLOCK | O_RDONLY)) == -1) {
219 g_warning("Can't open FIFO %s: %s", fifo, strerror(errno));
228 h = g_new(event_fd_handler, 1);
231 g_warning("Out of memory");
241 h->handler = fifo_menu_handler;
244 event_add_fd_handler(h);