afh.h: Minor documentation improvements.
[paraslash.git] / dbadm.c
1 /*
2  * Copyright (C) 2004-2006 Andre Noll <maan@systemlinux.org>
3  *
4  * Licensed under the GPL v2. For licencing details see COPYING.
5  */
6
7 /** \file dbadm.c simple attribute setting utility for the mysql selector */
8
9 #include "para.h"
10 #include <menu.h>
11 #include "string.h"
12
13 //#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
14 #define MAXLINE 255
15
16 #define OFFSET 4
17 static int att_win_lines, att_win_cols;
18 static int att_format_lines, att_format_cols;
19 static int atts_modified, refresh_file = 1;
20 static int n_choices, choice_len;
21 static char *atts;
22 ITEM **my_items;
23 WINDOW *att_win;
24
25 static char **choices;
26
27 /* no looging */
28 void para_log(__a_unused int ll, __a_unused const char *fmt,...)
29 {
30 }
31
32 static int client_cmd(const char *cmd)
33 {
34         pid_t pid;
35         int ret, fds[3] = {0, 1, 0};
36         char *cmdline = make_message(BINDIR "/para_client %s", cmd);
37         ret = para_exec_cmdline_pid(&pid, cmdline, fds);
38         free(cmdline);
39         if (ret < 0)
40                 return -1;
41         return fds[1];
42 }
43
44 static char **get_all_atts(int *num_atts)
45 {
46         int fd = client_cmd("laa");
47         FILE *f;
48         char **ret = NULL, *buf;
49
50         if (fd < 0)
51                 return NULL;
52         f = fdopen(fd, "r");
53         if (!f) {
54                 close(fd);
55                 return NULL;
56         }
57         *num_atts = 0;
58         buf = para_malloc(MAXLINE * sizeof(char));
59         while (fgets(buf, MAXLINE - 1, f) && *buf) {
60                 size_t n = strlen(buf);
61                 buf[n - 1] = '\0';
62                 if (choice_len < n - 1)
63                         choice_len = n - 1;
64                 ret = para_realloc(ret, (*num_atts + 1) * sizeof(char*));
65                 ret[*num_atts] = para_strdup(buf);
66                 *num_atts += 1;
67         }
68         free(buf);
69         return ret;
70 }
71
72 static char *get_atts(char *filename)
73 {
74         int n, fd, bufsize = (n_choices * (choice_len + 1) + 10) * sizeof(char);
75         char *cmd = make_message("la %s", filename), *buf;
76
77         fd = client_cmd(cmd);
78         free(cmd);
79         if (fd < 0)
80                 return NULL;
81         buf = para_malloc(bufsize * sizeof(char));
82         n = read(fd, buf, bufsize - 1);
83         if (n <= 0 ||strstr(buf, "Not contained in database")) {
84                 free(buf);
85                 return NULL;
86         };
87         return buf;
88 }
89
90 static void _item_init(__a_unused MENU* menu)
91 {
92 //      static int subsequent_run;
93         int i, n;
94         char *p = atts;
95         char att[MAXLINE];
96
97         if (!refresh_file)
98                 return;
99         refresh_file = 0;
100         for (i = 0; i < n_choices; i++)
101                 set_item_value(my_items[i], FALSE);
102         while (sscanf(p, "%s%n", att, &n) > 0) {
103                 //mvprintw(LINES - 4, 0, "aaaitem.");
104                 p += n + 1;
105                 for (i = 0; i < n_choices; i++) {
106                         if (!strcmp(item_name(my_items[i]), att)) {
107                                 set_item_value(my_items[i], TRUE);
108                                 break;
109                         }
110                 }
111         }
112 }
113
114 struct color_pair {
115         int bg;
116         int fg;
117 };
118
119 enum {
120         COLOR_DUMMY,
121         COLOR_FRAME,
122         COLOR_FILENAME,
123         COLOR_ACTIVE_ITEM,
124         COLOR_INACTIVE_ITEM
125 };
126
127 static void init_colors(void)
128 {
129         start_color();
130         init_pair(COLOR_FRAME, COLOR_BLUE, COLOR_BLACK);
131         init_pair(COLOR_FILENAME, COLOR_MAGENTA, COLOR_BLACK);
132         init_pair(COLOR_ACTIVE_ITEM, COLOR_RED, COLOR_WHITE);
133         init_pair(COLOR_INACTIVE_ITEM, COLOR_WHITE, COLOR_BLACK);
134 }
135
136 static int commit_changes(char *filename)
137 {
138 //      ITEM **items;
139         int i;
140         char buf[MAXLINE] = "para_client sa ";
141         int fds[3] = {0, 0, 0};
142         pid_t pid;
143
144         for (i = 0; i < n_choices; ++i) {
145                 strcat(buf, item_name(my_items[i]));
146                 if (item_value(my_items[i])) {
147         //              printf("%s\n", item_name(my_items[i]));
148                         strcat(buf, "+ ");
149                 } else
150                         strcat(buf, "- ");
151         }
152         strcat(buf, filename);
153         //printf("old atts: %s\n", atts);
154         //printf("%s\n", buf);
155         return para_exec_cmdline_pid(&pid, buf, fds);
156 }
157
158 static char *get_current_filename(void)
159 {
160         char *bn = NULL, *buf = para_malloc(MAXLINE * sizeof(char));
161         int ret, fd;
162
163         fd = client_cmd("sc 1");
164         if (fd < 0)
165                 return NULL;
166         ret = read(fd, buf, MAXLINE - 1);
167         if (ret <= 0)
168                 goto out;
169         buf[ret] = '\0';
170         bn = para_basename(buf);
171         free(buf);
172 out:
173         close(fd);
174         return bn;
175 }
176
177 static void print_filename(char *filename)
178 {
179         char *tmp = strdup(filename);
180         int maxlen = att_win_cols - 2;
181
182         wattron(att_win, COLOR_PAIR(COLOR_FILENAME));
183         if (strlen(filename) > maxlen)
184                 tmp[maxlen] = '\0';
185         wmove(att_win, 1, 1);
186         clrtoeol();
187         mvwprintw(att_win, 1, 1, "%s", tmp);
188         wattron(att_win, COLOR_PAIR(COLOR_FRAME));
189         mvwaddch(att_win, 2, att_win_cols - 1, ACS_RTEE);
190         free(tmp);
191 }
192
193 static int com_refresh_file(char *filename) {
194
195
196         filename = get_current_filename();
197         if (!filename)
198                 return -1;
199         atts = get_atts(filename);
200         if (!atts)
201                 return -1;
202         print_filename(filename);
203         return 1;
204 }
205
206 static int init_curses(void)
207 {
208         /* Initialize curses */
209         initscr();
210
211         if (LINES <= OFFSET + 4)
212                 return -1;
213
214         att_format_cols = (COLS - 2 * OFFSET - 3) / (choice_len + 1);
215                 if (att_format_cols < 1)
216                         return -1;
217         att_format_lines = (n_choices - 1) / att_format_cols + 1;
218         if (att_format_lines + OFFSET + 4 > LINES)
219                 att_format_lines = LINES - OFFSET - 4;
220
221         att_win_lines = att_format_lines + 4;
222         att_win_cols = (choice_len + 1) * att_format_cols + 1;
223         if (att_win_lines + OFFSET > LINES)
224                 att_win_lines = LINES - OFFSET - 1;
225         if (att_win_cols + 2 * OFFSET > COLS)
226                 att_win_cols = COLS - 2 * OFFSET + 1;
227         //printf ("%i:%i, %i:%i\n", att_format_lines, att_format_cols, att_win_lines, att_win_cols); fflush(stdout); sleep(2);
228
229         cbreak();
230         noecho();
231         keypad(stdscr, TRUE);
232         init_colors();
233         return 1;
234 }
235
236 int main(int argc, char *argv[])
237 {
238         int c, i, ret = EXIT_FAILURE;
239         MENU *my_menu = NULL;
240         char *filename;
241
242         choices = get_all_atts(&n_choices);
243         if (!choices ||  n_choices <= 0)
244                 exit(EXIT_FAILURE);
245         if (argc < 2) {
246                 filename = get_current_filename();
247                 if (!filename)
248                         exit(EXIT_FAILURE);
249         } else
250                 filename = strdup(argv[1]);
251         atts = get_atts(filename);
252         if (!atts)
253                 goto out;
254         if (init_curses() < 0)
255                 goto out;
256
257         /* Initialize items */
258         my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
259         for (i = 0; i < n_choices; ++i)
260                 my_items[i] = new_item(choices[i], "");
261
262         my_menu = new_menu(my_items);
263         set_item_init(my_menu, _item_init);
264         /* Make the menu multi valued */
265         menu_opts_off(my_menu, O_ONEVALUE);
266         /* Set menu option not to show the description */
267         menu_opts_off(my_menu, O_SHOWDESC);
268
269         /* Create the window to be associated with the menu */
270         att_win = newwin(att_win_lines, att_win_cols, OFFSET, OFFSET);
271         keypad(att_win, TRUE);
272         /* Set main window and sub window */
273         set_menu_win(my_menu, att_win);
274         set_menu_sub(my_menu, derwin(att_win, att_win_lines - 4,
275                 att_win_cols - 2, 3, 1));
276         set_menu_format(my_menu, att_format_lines, att_format_cols);
277         //set_menu_format(my_menu, 5, 1);
278         set_menu_mark(my_menu, "");
279
280         /* Print a border around the main window and print a title */
281         wattron(att_win, COLOR_PAIR(COLOR_FRAME));
282         box(att_win, 0, 0);
283         mvwhline(att_win, 2, 1, ACS_HLINE , att_win_cols - 2);
284         mvwaddch(att_win, 2, 0, ACS_LTEE);
285         print_filename(filename);
286         set_menu_fore(my_menu, COLOR_PAIR(COLOR_ACTIVE_ITEM) | A_REVERSE);
287         set_menu_back(my_menu, COLOR_PAIR(COLOR_INACTIVE_ITEM));
288         refresh();
289         post_menu(my_menu);
290
291 repeat:
292         wrefresh(att_win);
293         c = getch();
294         switch(c) {
295                 case KEY_DOWN:
296                         menu_driver(my_menu, REQ_DOWN_ITEM);
297                         goto repeat;
298                 case KEY_UP:
299                         menu_driver(my_menu, REQ_UP_ITEM);
300                         goto repeat;
301                 case KEY_LEFT:
302                         menu_driver(my_menu, REQ_LEFT_ITEM);
303                         goto repeat;
304                 case KEY_RIGHT:
305                         menu_driver(my_menu, REQ_RIGHT_ITEM);
306                         goto repeat;
307
308                 case 'q':
309                         ret = EXIT_SUCCESS;
310                         goto out;
311                 case 'r':
312                         com_refresh_file(filename);
313                         refresh_file = 1;
314                         _item_init(NULL);
315                         goto repeat;
316
317                 case ' ':
318                         menu_driver(my_menu, REQ_TOGGLE_ITEM);
319                         atts_modified = 1;
320                         goto repeat;
321                 /* Enter */
322                 case 10:
323                         if (atts_modified)
324                                 commit_changes(filename);
325                         goto out;
326                 default:
327                         goto repeat;
328         }
329 out:
330         if (my_items) {
331                 free_item(my_items[0]);
332                 free_item(my_items[1]);
333         }
334         for (i = 0; i < n_choices; i++)
335                 free(choices[i]);
336         free(choices);
337         if (my_menu)
338                 free_menu(my_menu);
339         if (atts)
340                 free(atts);
341         if (filename)
342                 free(filename);
343         endwin();
344         exit(ret);
345 }
346