Main Page | Class List | File List | Class Members | File Members

rssbgr-conf.c

Go to the documentation of this file.
00001 /*
00002  *  $Id: rssbgr-conf.c,v 1.13 2006/04/17 22:45:19 ghost666 Exp $
00003  *
00004  *  rssbgr - RSS backgroud reader
00005  *  Copyright (C) 2005, 2006 Piotr 'GhosT' Wydrych
00006  *
00007  *  This program is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation; either version 2 of the License, or
00010  *  (at your option) any later version.
00011  *
00012  *  This program is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *  GNU General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU General Public License
00018  *  along with this program; if not, write to the Free Software
00019  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00022 #ifndef _RSSBGR_CONFIG_H
00023 #define _RSSBGR_CONFIG_H
00024 #include "config.h"
00025 #endif /* ifndef _RSSBGR_CONFIG_H */
00026 
00027 #include <signal.h>
00028 #include <curses.h>
00029 #include <menu.h>
00030 
00031 #include "share.h"
00032 #include "url.h"
00033 
00034 #ifndef HAVE_STRLCPY
00035 #include "compat/strlcpy.h"
00036 #endif /* ifndef HAVE_STRLCPY */
00037 
00038 struct config_item
00039 {
00040  char *url;
00041  unsigned int freq;
00042  char *action;
00043 };
00044 
00045 struct config_item *config = NULL;
00046 unsigned int config_items_count, menu_items_count;
00047 
00048 ITEM **config_menu_items;
00049 MENU *config_menu = NULL;
00050 WINDOW *config_menu_win, *edit_win = NULL, *err_url_win = NULL, *help_main_win = NULL, *help_edit_win = NULL;
00051 
00052 char *home, *directory, *lockfile, *configfile;
00053 char edit_buffer[3][BUFSIZ];
00054 unsigned short int edit_buffer_index;
00055 
00056 void repaint(short int reset);
00057 void repaint_menu(void);
00058 void repaint_edit(void);
00059 void repaint_err_url(void);
00060 void repaint_help_main(void);
00061 void repaint_help_edit(void);
00062 void rebuild_menu();
00063 void edit(void);
00064 void catch_signal(int sig);
00065 void set_signal_handlers(void);
00066 void readconfig(void);
00067 void kill_rssbgr(void);
00068 
00069 int main(void)
00070 {
00071  FILE *fd;
00072  char *url, *action;
00073  long int frequency;
00074  int i, c;
00075  directory = (char *)malloc(PATH_MAX);
00076  lockfile = (char *)malloc(PATH_MAX);
00077  configfile = (char *)malloc(PATH_MAX);
00078  home = (char *)getenv("HOME");
00079  if (home == NULL) DIE("HOME variable not set. Program will exit.")
00080  sprintf(directory, "%s/" DIRECTORY, home);   directory = (char *)realloc(directory, strlen(directory)+1);
00081  sprintf(lockfile, "%s/" LOCKFILE, home);     lockfile = (char *)realloc(lockfile, strlen(lockfile)+1);
00082  sprintf(configfile, "%s/" CONFIGFILE, home); configfile = (char *)realloc(configfile, strlen(configfile)+1);
00083  init_pair(1, COLOR_BLACK, COLOR_WHITE);
00084  init_pair(2, COLOR_WHITE, COLOR_BLACK);
00085  readconfig();
00086  rebuild_menu();
00087  initscr();
00088  repaint(0);
00089  set_signal_handlers();
00090  while ((c = wgetch(config_menu_win)) != 'q')
00091   switch (c)
00092   {
00093    /* move */
00094    case KEY_PPAGE:
00095     menu_driver(config_menu, REQ_SCR_UPAGE);
00096     break;
00097    case 'k':
00098    case KEY_UP:
00099     menu_driver(config_menu, REQ_UP_ITEM);
00100     break;
00101    case 'j':
00102    case KEY_DOWN:
00103     menu_driver(config_menu, REQ_DOWN_ITEM);
00104     break;
00105    case KEY_NPAGE:
00106     menu_driver(config_menu, REQ_SCR_DPAGE);
00107     break;
00108    /* act */
00109    case 'd':
00110    case KEY_DC:
00111     if (item_index(current_item(config_menu)))
00112     {
00113      free(config[item_index(current_item(config_menu))-1].url);
00114      free(config[item_index(current_item(config_menu))-1].action);
00115      for (i = item_index(current_item(config_menu)); i < config_items_count; ++i)
00116      {
00117       config[i-1].url = config[i].url;
00118       config[i-1].freq =  config[i].freq;
00119       config[i-1].action = config[i].action;
00120      }
00121      --config_items_count;
00122      config = (struct config_item *)realloc(config, config_items_count*sizeof(struct config_item));
00123      rebuild_menu();
00124      repaint(0);
00125     }
00126     break;
00127    case 10:
00128     edit();
00129     break;
00130    case 'K':
00131     kill_rssbgr();
00132     break;
00133    case 'h':
00134    case KEY_F(1):
00135     repaint_help_main();
00136     while(wgetch(help_main_win) != 10);
00137     delwin(help_main_win); help_main_win = NULL;
00138     repaint(0);
00139   }
00140  delwin(edit_win);
00141  delwin(config_menu_win);
00142  endwin();
00143  fprintf(stdout, "Writing new config... ");
00144  fd = fopen(configfile, "w");
00145  if (fd == NULL)
00146   fprintf(stdout, "cannot open %s for writing.\n", configfile);
00147  else
00148  {
00149   for (i = 0; i < config_items_count; ++i)
00150   {
00151    url = config[i].url;
00152    frequency = config[i].freq;
00153    action = config[i].action;
00154    fprintf(fd, CONFIGFILE_FORMAT "\n", CONFIGFILE_VARS_PRINT);
00155   }
00156   fclose(fd);
00157   fprintf(stdout, "OK.\n");
00158   unlink(lockfile);
00159  }
00160  return 0;
00161 }
00162 
00163 void repaint(short int reset)
00164 {
00165  int x, y, i;
00166  if (reset)
00167  {
00168   endwin();
00169   refresh();
00170  }
00171  else
00172  {
00173   wnoutrefresh(stdscr);
00174   wnoutrefresh(config_menu_win);
00175   if (edit_win != NULL) wnoutrefresh(edit_win);
00176  }
00177  getmaxyx(stdscr, y, x);
00178  wmove(stdscr, 0, 0);
00179  for (i = 0; i < x*y; i++) wprintw(stdscr, " "); 
00180  box(stdscr, 0, 0);
00181  mvwprintw(stdscr, 0, 2, " RSS Background Reader configuration ");
00182  mvwprintw(stdscr, LINES-1, 2, " q - save&quit ");
00183  getyx(stdscr, y, x);
00184  mvwprintw(stdscr, y, x+2, " h, F1 - help ");
00185  wmove(stdscr, 1, 1);
00186  wrefresh(stdscr);
00187  noecho();
00188  cbreak();
00189  repaint_menu();
00190  if (edit_win != NULL) repaint_edit();
00191  if ((edit_win != NULL) && (err_url_win != NULL)) repaint_err_url();
00192  if ((edit_win != NULL) && (err_url_win == NULL) && (help_edit_win != NULL)) repaint_help_edit();
00193  if ((edit_win == NULL) && (help_main_win != NULL)) repaint_help_main();
00194  if (!reset) doupdate();
00195 }
00196 
00197 void repaint_menu(void)
00198 {
00199  ITEM *current = current_item(config_menu);
00200  unpost_menu(config_menu);
00201  delwin(config_menu_win);
00202  config_menu_win = newwin(LINES-2, COLS-2, 1, 1);
00203  set_menu_win(config_menu, config_menu_win);
00204  set_menu_sub(config_menu, derwin(config_menu_win, LINES-4, COLS-4, 1, 1));
00205  set_menu_format(config_menu, LINES-4, 1);
00206  set_current_item(config_menu, current);
00207  post_menu(config_menu);
00208  keypad(config_menu_win, TRUE);
00209  wrefresh(config_menu_win);
00210 }
00211 
00212 void repaint_edit(void)
00213 {
00214  int x, y, i;
00215  delwin(edit_win);
00216  edit_win = newwin(12, COLS-2, (int)(LINES-12)/2, 1);
00217  box(edit_win, 0, 0);
00218  if (!item_index(current_item(config_menu)))
00219   mvwprintw(edit_win, 0, 2, " Add new RSS feed ");
00220  else
00221   mvwprintw(edit_win, 0, 2, (strlen(config[item_index(current_item(config_menu))-1].url) > 63)?(" Edit: %.60s... "):(" Edit: %.63s "), config[item_index(current_item(config_menu))-1].url);
00222  mvwprintw(edit_win, 11, 2, " Esc - cancel ");
00223  getyx(edit_win, y, x);
00224  mvwprintw(edit_win, y, x+2, " Enter - OK ");
00225  getyx(edit_win, y, x);
00226  mvwprintw(edit_win, y, x+2, " F1, ^F - help ");
00227  mvwprintw(edit_win, 2, 2, "URL:");
00228  wattron(edit_win, A_REVERSE);
00229  wmove(edit_win, 3, 2);
00230  for (i = 0; i < COLS-6; ++i) wprintw(edit_win, " ");
00231  mvwprintw(edit_win, 3, 2, "%s", (strlen(edit_buffer[0]) > COLS-7)?(edit_buffer[0]+strlen(edit_buffer[0])-COLS+7):(edit_buffer[0]));
00232  wattroff(edit_win, A_REVERSE);
00233  mvwprintw(edit_win, 5, 2, "Checking frequency (in seconds):");
00234  wattron(edit_win, A_REVERSE);
00235  wmove(edit_win, 6, 2);
00236  for (i = 0; i < COLS-6; ++i) wprintw(edit_win, " ");
00237  mvwprintw(edit_win, 6, 2, "%s", (strlen(edit_buffer[1]) > COLS-7)?(edit_buffer[1]+strlen(edit_buffer[1])-COLS+7):(edit_buffer[1]));
00238  wattroff(edit_win, A_REVERSE);
00239  mvwprintw(edit_win, 8, 2, "Command (see help (F1) for modifiers):");
00240  wattron(edit_win, A_REVERSE);
00241  wmove(edit_win, 9, 2);
00242  for (i = 0; i < COLS-6; ++i) wprintw(edit_win, " ");
00243  mvwprintw(edit_win, 9, 2, "%s", (strlen(edit_buffer[2]) > COLS-7)?(edit_buffer[2]+strlen(edit_buffer[2])-COLS+7):(edit_buffer[2]));
00244  wattroff(edit_win, A_REVERSE);
00245  wmove(edit_win, 3+3*edit_buffer_index, (strlen(edit_buffer[edit_buffer_index]) > COLS-7)?(COLS-5):(2+strlen(edit_buffer[edit_buffer_index])));
00246  keypad(edit_win, TRUE);
00247  wrefresh(edit_win);
00248 }
00249 
00250 void repaint_err_url(void)
00251 {
00252  if (err_url_win != NULL) delwin(err_url_win);
00253  err_url_win = newwin(5, 21, (LINES-5)/2, (COLS-21)/2);
00254  box(err_url_win, 0, 0);
00255  mvwprintw(err_url_win, 0, 2, " Error ");
00256  mvwprintw(err_url_win, 4, 2, " press Enter ");
00257  mvwprintw(err_url_win, 2, 2, "URL is not valid!");
00258  keypad(err_url_win, TRUE);
00259  wrefresh(err_url_win);
00260 }
00261 
00262 void repaint_help_main(void)
00263 {
00264  if (help_main_win != NULL) delwin(help_main_win);
00265  help_main_win = newwin(13, 27, (LINES-13)/2, (COLS-27)/2);
00266  box(help_main_win, 0, 0);
00267  mvwprintw(help_main_win, 0, 2, " Help ");
00268  mvwprintw(help_main_win, 11, 2, " press Enter ");
00269  mvwprintw(help_main_win, 2, 2, "UP, k   - previous item");
00270  mvwprintw(help_main_win, 3, 2, "DOWN, j - next item");
00271  mvwprintw(help_main_win, 4, 2, "PgUp    - scroll up");
00272  mvwprintw(help_main_win, 5, 2, "PgDn    - scroll down");
00273  mvwprintw(help_main_win, 6, 2, "Del, d  - delete item");
00274  mvwprintw(help_main_win, 7, 2, "F1, h   - help");
00275  mvwprintw(help_main_win, 8, 2, "Enter   - add/edit item");
00276  mvwprintw(help_main_win, 9, 2, "q       - save & quit");
00277  mvwprintw(help_main_win, 10, 2, "K       - kill RSSbgr");
00278  keypad(help_main_win, TRUE);
00279  wrefresh(help_main_win);
00280 }
00281 
00282 void repaint_help_edit(void)
00283 {
00284  if (help_edit_win != NULL) delwin(help_edit_win);
00285  help_edit_win = newwin(13, 37, (LINES-13)/2, (COLS-37)/2);
00286  box(help_edit_win, 0, 0);
00287  mvwprintw(help_edit_win, 0, 2, " Help ");
00288  mvwprintw(help_edit_win, 12, 2, " press Enter ");
00289  mvwprintw(help_edit_win, 2, 2, "Command modifiers:");
00290  mvwprintw(help_edit_win, 3, 2, "{T} - feed title");
00291  mvwprintw(help_edit_win, 4, 2, "{D} - feed description");
00292  mvwprintw(help_edit_win, 5, 2, "{L} - feed main link");
00293  mvwprintw(help_edit_win, 6, 2, "{t} - new information title");
00294  mvwprintw(help_edit_win, 7, 2, "{d} - new information description");
00295  mvwprintw(help_edit_win, 8, 2, "{l} - new information link");
00296  mvwprintw(help_edit_win, 9, 2, "\\}  - char }");
00297  mvwprintw(help_edit_win, 10, 2, "\\{ is leaved unchanged");
00298  keypad(help_edit_win, TRUE);
00299  wrefresh(help_edit_win);
00300 }
00301 void rebuild_menu(void)
00302 {
00303  int i;
00304  if (config_menu != NULL)
00305  {
00306   unpost_menu(config_menu);
00307   free_menu(config_menu);
00308   for (i = 0; i < menu_items_count; ++i)
00309    free_item(config_menu_items[i]);
00310   free(config_menu_items);
00311  }
00312  menu_items_count = config_items_count+2;
00313  config_menu_items = (ITEM **)calloc(menu_items_count, sizeof(ITEM *));
00314  config_menu_items[0] = new_item("<add new RSS feed>", "<add new RSS feed>");
00315  for (i = 1; i <= config_items_count; ++i)
00316   config_menu_items[i] = new_item(config[i-1].url, config[i-1].url);
00317  config_menu_items[config_items_count+1] = new_item(NULL, NULL);
00318  config_menu = new_menu(config_menu_items);
00319  menu_opts_off(config_menu, O_SHOWDESC | O_NONCYCLIC);
00320  set_menu_mark(config_menu, " > ");
00321 }
00322 
00323 void edit(void)
00324 {
00325  int c, p, i;
00326  long int frequency;
00327  char *host, *request;
00328  uint16_t port;
00329  
00330  if (item_index(current_item(config_menu)))
00331  {
00332   strcpy(edit_buffer[0], config[item_index(current_item(config_menu))-1].url);
00333   sprintf(edit_buffer[1], "%d", config[item_index(current_item(config_menu))-1].freq);
00334   strcpy(edit_buffer[2], config[item_index(current_item(config_menu))-1].action);
00335  }
00336  else
00337  {
00338   strcpy(edit_buffer[0], "");
00339   sprintf(edit_buffer[1], "%d", MIN_FREQUENCY);
00340   strcpy(edit_buffer[2], "");
00341  }
00342  edit_win = newwin(12, COLS-2, (int)(LINES-12)/2, 1);
00343 start:
00344  edit_buffer_index = 0;
00345  repaint(0);
00346  while(((c = wgetch(edit_win)) != 27) && (c != 10))
00347  {
00348   switch (c)
00349   {
00350    case KEY_UP:
00351     edit_buffer_index = (edit_buffer_index == 0)?(2):(edit_buffer_index-1);
00352     wmove(edit_win, 3+3*edit_buffer_index, (strlen(edit_buffer[edit_buffer_index]) > COLS-7)?(COLS-5):(2+strlen(edit_buffer[edit_buffer_index])));
00353     break;
00354    case 9:
00355    case KEY_DOWN:
00356     edit_buffer_index = (edit_buffer_index+1)%3;
00357     wmove(edit_win, 3+3*edit_buffer_index, (strlen(edit_buffer[edit_buffer_index]) > COLS-7)?(COLS-5):(2+strlen(edit_buffer[edit_buffer_index])));
00358     break;
00359    case KEY_BACKSPACE:
00360    case 127:
00361     p = strlen(edit_buffer[edit_buffer_index]);
00362     if (p) edit_buffer[edit_buffer_index][p-1] = '\0';
00363     wattron(edit_win, A_REVERSE);
00364     wmove(edit_win, 3+3*edit_buffer_index, 2);
00365     for (i = 0; i < COLS-6; ++i) wprintw(edit_win, " ");
00366     mvwprintw(edit_win, 3+3*edit_buffer_index, 2, "%s", (strlen(edit_buffer[edit_buffer_index]) > COLS-7)?(edit_buffer[edit_buffer_index]+strlen(edit_buffer[edit_buffer_index])-COLS+7):(edit_buffer[edit_buffer_index]));
00367     wattroff(edit_win, A_REVERSE);
00368     break;
00369    case 6:
00370    case KEY_F(1):
00371     repaint_help_edit();
00372     while(wgetch(help_edit_win) != 10);
00373     delwin(help_edit_win); help_edit_win = NULL;
00374     repaint(0);
00375     break;
00376    default:
00377     p = strlen(edit_buffer[edit_buffer_index]);
00378     if ((c < ' ') || (c > 255) || (p+1 >= BUFSIZ)) break;
00379     edit_buffer[edit_buffer_index][p] = (char)(c & 0x000000FF);
00380     edit_buffer[edit_buffer_index][p+1] = '\0';
00381     wattron(edit_win, A_REVERSE);
00382     mvwprintw(edit_win, 3+3*edit_buffer_index, 2, "%s", (strlen(edit_buffer[edit_buffer_index]) > COLS-7)?(edit_buffer[edit_buffer_index]+strlen(edit_buffer[edit_buffer_index])-COLS+7):(edit_buffer[edit_buffer_index]));
00383     wattroff(edit_win, A_REVERSE);
00384   }
00385   wrefresh(edit_win);
00386  }
00387  if (c == 10)
00388  {
00389   if (!strlen(edit_buffer[0]) || parse_url(edit_buffer[0], &host, &port, &request) == -1)
00390   {
00391    free(host); free(request);
00392    repaint_err_url();
00393    while(wgetch(err_url_win) != 10);
00394    delwin(err_url_win); err_url_win = NULL;
00395    goto start;
00396   }
00397   free(host); free(request);
00398   if (item_index(current_item(config_menu)))
00399   {
00400    config[item_index(current_item(config_menu))-1].url = (char *)realloc(config[item_index(current_item(config_menu))-1].url, strlen(edit_buffer[0])+1);
00401    strcpy(config[item_index(current_item(config_menu))-1].url, edit_buffer[0]);
00402    frequency = strtol(edit_buffer[1], (char **)NULL, 10);
00403    frequency = (frequency < 0)?(-frequency):(frequency);
00404    config[item_index(current_item(config_menu))-1].freq = ((frequency < MIN_FREQUENCY)?(MIN_FREQUENCY):(frequency));
00405    config[item_index(current_item(config_menu))-1].action = (char *)realloc(config[item_index(current_item(config_menu))-1].action, strlen(edit_buffer[2])+1);
00406    strcpy(config[item_index(current_item(config_menu))-1].action, edit_buffer[2]);
00407   }
00408   else
00409   {
00410    ++config_items_count;
00411    config = (struct config_item *)realloc(config, config_items_count*sizeof(struct config_item));
00412    config[config_items_count-1].url = (char *)malloc(strlen(edit_buffer[0])+1);
00413    strcpy(config[config_items_count-1].url, edit_buffer[0]);
00414    frequency = strtol(edit_buffer[1], (char **)NULL, 10);
00415    frequency = (frequency < 0)?(-frequency):(frequency);
00416    config[config_items_count-1].freq = ((frequency < MIN_FREQUENCY)?(MIN_FREQUENCY):(frequency));
00417    config[config_items_count-1].action = (char *)malloc(strlen(edit_buffer[2])+1);
00418    strcpy(config[config_items_count-1].action, edit_buffer[2]);
00419   }
00420   rebuild_menu();
00421  }
00422  delwin(edit_win); edit_win = NULL;
00423  repaint(0);
00424 }
00425 
00426 void catch_signal(int sig)
00427 {
00428  if (sig != SIGWINCH) return;
00429  repaint(1);
00430 }
00431 
00432 void set_signal_handlers(void)
00433 {
00434  struct sigaction sa;
00435  sa.sa_handler = catch_signal;
00436  sigemptyset(&sa.sa_mask);
00437  sa.sa_flags = 0;
00438  sigaction(SIGWINCH, &sa, NULL);
00439 }
00440 
00441 void readconfig(void)
00442 {
00443  FILE *fd;
00444  char *line, *url, *action, *a, *host, *request;
00445  long int frequency;
00446  uint16_t port;
00447 
00448  config_items_count = 0;
00449  config = (struct config_item *)malloc(config_items_count*sizeof(struct config_item));
00450  line = (char *)malloc(BUFSIZ);
00451  url = (char *)malloc(BUFSIZ);
00452  action = (char *)malloc(BUFSIZ);
00453  fd = fopen(configfile, "r");
00454  if (fd == NULL)
00455   return;
00456  while(!feof(fd))
00457  {
00458   if (fgets(line, BUFSIZ, fd))
00459   {
00460    if (sscanf(line, CONFIGFILE_FORMAT "\n", CONFIGFILE_VARS_SCAN) != 3) continue;
00461    a = strchr(strchr(line, '\t')+1, '\t')+1;
00462    strlcpy(action, a, strchr(a, '\n')-a+1);
00463    ++config_items_count;
00464    config = (struct config_item *)realloc(config, config_items_count*sizeof(struct config_item));
00465    config[config_items_count-1].url = (char *)malloc(strlen(url)+1);
00466    strcpy(config[config_items_count-1].url, url);
00467    frequency = (frequency < 0)?(-frequency):(frequency);
00468    frequency = ((frequency < MIN_FREQUENCY)?(MIN_FREQUENCY):(frequency));
00469    config[config_items_count-1].freq = frequency;
00470    if (parse_url(url, &host, &port, &request) == -1)
00471     {
00472      free(host); free(request);
00473      --config_items_count;
00474      config = (struct config_item *)realloc(config, config_items_count*sizeof(struct config_item));
00475      continue;
00476     }
00477    config[config_items_count-1].action = (char *)malloc(strlen(action)+1);
00478    strcpy(config[config_items_count-1].action, action);
00479   }
00480  }
00481  fclose(fd);
00482  free(line); free(url); free(action);
00483 }
00484 
00485 void kill_rssbgr(void)
00486 {
00487  FILE *lockfile_s;
00488  unsigned int rssbgr_pid;
00489  if (((lockfile_s = fopen(lockfile, "r")) != NULL) && (fscanf(lockfile_s, "%u", &rssbgr_pid) == 1) && (rssbgr_pid > 0))
00490   kill(rssbgr_pid, SIGTERM);
00491  if (lockfile_s != NULL) fclose(lockfile_s);
00492 }

Generated on Fri May 26 08:40:18 2006 for RSSbgr by doxygen 1.3.6