fmonitor.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  1. /* GKrellM (C) 1999-2000 Bill Wilson
  2. |
  3. | Author: Bill Wilson bill@gkrellm.net
  4. | Latest versions might be found at: http://gkrellm.net
  5. |
  6. | This program is free software which I release under the GNU General Public
  7. | License. You may redistribute and/or modify this program under the terms
  8. | of that license as published by the Free Software Foundation; either
  9. | version 2 of the License, or (at your option) any later version.
  10. |
  11. | This program is distributed in the hope that it will be useful,
  12. | but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. | GNU General Public License for more details.
  15. |
  16. | To get a copy of the GNU General Puplic License, write to the
  17. | Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. /* File Monitor plugin for GKrellM
  20. |
  21. | Copyright (C) 2000 Anatoly Asviyan
  22. |
  23. | Author: Anatoly Asviyan <aanatoly@linuxmail.org>
  24. |
  25. | Version: for gkrellm version 0.10.4 and up
  26. |
  27. | See README for details
  28. */
  29. #include <sys/types.h>
  30. #include <sys/wait.h>
  31. #include <gkrellm2/gkrellm.h>
  32. #include "fm_led.xpm"
  33. static char *plugin_info[] =
  34. {
  35. "File Monitor plugin for GKrellM\n"
  36. "Copyright (C) 2001 Anatoly Asviyan\n"
  37. "aanatoly@linuxmail.org\n"
  38. "Released under GPL\n"
  39. "Modified by Jindrich Makovicka\n",
  40. "makovick@kmlinux.fjfi.cvut.cz\n"
  41. "\n"
  42. "This plugin monitors a file and displays its contens in gkrellm. File can have\n"
  43. "multiple rows of the form 'name : value : [flag]'. If flag non-empty then\n"
  44. "for WARNING value - the orange led will light up and for ALERT value - red.\n"
  45. "For example\n"
  46. " CPU:50.8:ALERT\n"
  47. " SBr:33.4:WARNING\n"
  48. " Fan1:4560:\n"
  49. "or\n"
  50. " Temp:31 C:\n"
  51. " Hum:49 %:\n"
  52. "\n"
  53. "Plugin can monitor multiple files and for each file, you can specify\n"
  54. "the following:\n",
  55. "<i>Label", " - label of gkrellm panel\n",
  56. "<i>File to monitor", " - file to monitor.\n",
  57. "If preceded with a pipe (\"|\"), it will be instead executed in the shell\n",
  58. "and the result will be read from standard output\n",
  59. "<i>Update program", " - the program to update a monitored file.\n",
  60. "<i>Warning command", " - any shell command to run whenever warning flag is set.\n",
  61. "<i>Alert command", " - any shell command to run whenever alert flag is set.\n",
  62. "<i>Check interval", " - how often to check.\n"
  63. "\n",
  64. "<b>CREDITS\n",
  65. "Plugin is based on Bill Willson (bill@gkrellm.net) demo programs\n"
  66. "and on fileread plugin by Henry Palonen (h@yty.net)\n"
  67. "\n"
  68. };
  69. #define FM_CONFIG_NAME "FMonitor" /* Name in the configuration window */
  70. #define FM_STYLE_NAME "fmonitor" /* Theme subdirectory name and gkrellmrc
  71. */
  72. #define LEN 1024
  73. #define MAXFILENUM 10
  74. #define MAXPARAMNUM 10
  75. #define MAXARGNUM 20
  76. //#define HORIZONTALLY_CENTERED_LED
  77. enum { FM_LABEL, FM_FILE, FM_UPDATE, FM_WARN, FM_ALERT, FM_INTERVAL, FM_ENTRY_NUM };
  78. typedef struct {
  79. gchar *text[FM_ENTRY_NUM];
  80. gint pid; //pid of update command
  81. int ticker;
  82. } fm_data;
  83. static GkrellmMonitor *monitor;
  84. typedef struct {
  85. GkrellmPanel *panel;
  86. GkrellmDecal *label;
  87. GkrellmDecal *led[MAXPARAMNUM];
  88. GkrellmDecal *name[MAXPARAMNUM];
  89. GkrellmDecal *value[MAXPARAMNUM];
  90. int fn[MAXPARAMNUM];
  91. int rownum, y;
  92. } fm_gui;
  93. static fm_data fmc[MAXFILENUM];
  94. static fm_gui fmg[MAXFILENUM];
  95. static int fmnum = 0, cnum = 0, selrow = -1;
  96. extern struct tm current_tm;
  97. //static Panel *panel;
  98. //static Decal *label_text;
  99. static gint style_id;
  100. static gboolean force_update;
  101. static GdkPixmap *ledp, *ledm;
  102. static GtkWidget *fm_vbox;
  103. static GtkWidget *entry[FM_ENTRY_NUM];
  104. static GtkWidget *config_list;
  105. static GtkWidget *btn_enter, *btn_del;
  106. static char *config_name[FM_ENTRY_NUM] = {
  107. "label", "file", "update", "warn", "alert", "interval"
  108. };
  109. #define MY_FREE(x) if(x) {g_free(x);(x)=NULL;}
  110. static void destroy_fm_panels();
  111. static void create_fm_panels(int first_create);
  112. static void run_update_cmds();
  113. static gint
  114. panel_expose_event(GtkWidget *widget, GdkEventExpose *ev)
  115. {
  116. int i;
  117. for (i = 0; i < fmnum; i++) {
  118. if (widget == fmg[i].panel->drawing_area)
  119. gdk_draw_pixmap(widget->window,
  120. widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
  121. fmg[i].panel->pixmap, ev->area.x, ev->area.y, ev->area.x, ev->area.y,
  122. ev->area.width, ev->area.height);
  123. }
  124. return FALSE;
  125. }
  126. /* Shamelessly ripped from the Gtk docs. */
  127. static void fr_message(gchar *message)
  128. {
  129. GtkWidget *dialog, *label, *okay_button;
  130. dialog = gtk_dialog_new();
  131. label = gtk_label_new (message);
  132. okay_button = gtk_button_new_with_label("OK");
  133. gtk_signal_connect_object (GTK_OBJECT (okay_button), "clicked",
  134. GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT(dialog));
  135. gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area),
  136. okay_button);
  137. gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
  138. label);
  139. gtk_widget_show_all (dialog);
  140. }
  141. static void
  142. destroy_decal(GkrellmPanel *p, GkrellmDecal *d)
  143. {
  144. p->decal_list = g_list_remove(p->decal_list, d);
  145. gkrellm_destroy_decal(d);
  146. }
  147. static void
  148. update_plugin()
  149. {
  150. GkrellmStyle *style;
  151. GkrellmTextstyle *ts, *ts_alt;
  152. int x, h, r, i, rownum, ph, drawing_leds, changed = 0;
  153. int alert = 0, warning = 0;
  154. char s[LEN];
  155. FILE *fp;
  156. /* animation of alert and warning led */
  157. for (i = 0; i < fmnum; i++) {
  158. drawing_leds = FALSE;
  159. for (r = 0; r < fmg[i].rownum; ++r) {
  160. if (fmg[i].fn[r] < 2) {
  161. x = ((GK.timer_ticks % 10) < 2) ? 2 : fmg[i].fn[r];
  162. gkrellm_draw_decal_pixmap(fmg[i].panel, fmg[i].led[r],x);
  163. drawing_leds = TRUE;
  164. }
  165. }
  166. if (drawing_leds)
  167. gkrellm_draw_panel_layers(fmg[i].panel);
  168. }
  169. if (!GK.second_tick)
  170. return;
  171. /* time to check monitored file(s) */
  172. force_update = FALSE;
  173. style = gkrellm_meter_style(style_id);
  174. ts = gkrellm_meter_textstyle(style_id);
  175. ts_alt = gkrellm_meter_alt_textstyle(style_id);
  176. for (i = 0; i < fmnum; i++) {
  177. int interval = atoi(fmc[i].text[FM_INTERVAL]);
  178. if (interval < 1 || interval > 3600) interval = 60;
  179. if (++fmc[i].ticker >= interval) {
  180. fmc[i].ticker = 0;
  181. } else {
  182. continue;
  183. }
  184. ph = fmg[i].panel->h;
  185. rownum = 0;
  186. if (fmc[i].text[FM_FILE][0] == '|') {
  187. // fprintf(stderr, "popen %s\n", fmc[i].text[FM_FILE]+1);
  188. fp = popen(fmc[i].text[FM_FILE]+1, "r");
  189. } else {
  190. fp = fopen(fmc[i].text[FM_FILE], "r");
  191. }
  192. if (fp) {
  193. /* read at most MAXPARAMNUM valid rows from file */
  194. while (fgets(s, LEN, fp) && (rownum < MAXPARAMNUM)) {
  195. char *sname, *svalue, *sled;
  196. // fprintf(stderr, "str %s\n", s);
  197. sname = strtok(s, ":");
  198. if (!sname || *sname == '\0')
  199. continue;
  200. svalue = strtok(NULL, ":");
  201. if (!svalue || *svalue == '\0')
  202. continue;
  203. sled = strtok(NULL, " \n\t");
  204. rownum++;
  205. /* create decals for new row */
  206. if (rownum > fmg[i].rownum) {
  207. changed = 1;
  208. r = rownum - 1;
  209. #ifdef HORIZONTALLY_CENTERED_LED
  210. /* Create led first so it will be behind name and value */
  211. /* name at left margin, value at right margin, led center */
  212. fmg[i].led[r] = gkrellm_create_decal_pixmap(fmg[i].panel,
  213. ledp, ledm, 3, style, 0, fmg[i].y);
  214. fmg[i].led[r]->x = (gkrellm_chart_width() - fmg[i].led[r]->w) / 2;
  215. fmg[i].name[r] = gkrellm_create_decal_text(fmg[i].panel,
  216. "VCOR2", ts_alt, style, -1, fmg[i].y, 0);
  217. fmg[i].value[r] = gkrellm_create_decal_text(fmg[i].panel,
  218. "5555", ts_alt, style, 0, fmg[i].y, 0);
  219. fmg[i].value[r]->x = gkrellm_chart_width() - fmg[i].value[r]->w
  220. - style->margin;
  221. #else
  222. fmg[i].led[r] = gkrellm_create_decal_pixmap(fmg[i].panel,
  223. ledp, ledm, 3, style, -1, fmg[i].y);
  224. x = style->margin.left + 5;
  225. fmg[i].name[r] = gkrellm_create_decal_text(fmg[i].panel,
  226. "VCOR2", ts_alt, style, x, fmg[i].y, 0);
  227. // fmg[i].value[r] = gkrellm_create_decal_text(fmg[i].panel,
  228. // "5555", ts_alt, style, x+fmg[i].name[r]->w, fmg[i].y, 0);
  229. /* Bill: Do you think value decal should be at right margin ? */
  230. /* Anatoly: Yes I do, I added it to TODO list */
  231. fmg[i].value[r] = gkrellm_create_decal_text(fmg[i].panel,
  232. "5555", ts_alt, style, 0, fmg[i].y, 0);
  233. fmg[i].value[r]->x = gkrellm_chart_width()
  234. - fmg[i].value[r]->w - style->margin.left;
  235. #endif
  236. h = fmg[i].name[r]->h;
  237. if (fmg[i].value[r]->h > h)
  238. h = fmg[i].value[r]->h;
  239. if (fmg[i].led[r]->h < h) /* vertically center led */
  240. fmg[i].led[r]->y += (h - fmg[i].led[r]->h) / 2;
  241. fmg[i].y += h + 1;
  242. fmg[i].rownum++;
  243. }
  244. if (!sled || !(*sled)) {
  245. fmg[i].fn[rownum-1] = 2;
  246. } else if (!strcmp(sled, "WARNING")) {
  247. fmg[i].fn[rownum-1] = 1;
  248. warning = 1;
  249. } else {
  250. fmg[i].fn[rownum-1] = 0;
  251. alert = 1;
  252. }
  253. gkrellm_draw_decal_pixmap(fmg[i].panel, fmg[i].led[rownum-1], fmg[i].fn[rownum-1]);
  254. // fprintf(stderr, "update led pixmap\n");
  255. gkrellm_draw_decal_text(fmg[i].panel, fmg[i].name[rownum-1], sname, -1);
  256. gkrellm_draw_decal_text(fmg[i].panel, fmg[i].value[rownum-1], svalue, -1);
  257. }
  258. if (fmc[i].text[FM_FILE][0] == '|') {
  259. pclose(fp);
  260. } else {
  261. fclose(fp);
  262. }
  263. }
  264. /* destroys unused decals */
  265. while (fmg[i].rownum > rownum) {
  266. changed = 1;
  267. h = fmg[i].name[fmg[i].rownum-1]->h;
  268. if (fmg[i].value[fmg[i].rownum-1]->h > h)
  269. h = fmg[i].value[fmg[i].rownum-1]->h;
  270. fmg[i].y -= h + 1;
  271. destroy_decal(fmg[i].panel, fmg[i].led[fmg[i].rownum-1]);
  272. destroy_decal(fmg[i].panel, fmg[i].name[fmg[i].rownum-1]);
  273. destroy_decal(fmg[i].panel, fmg[i].value[fmg[i].rownum-1]);
  274. fmg[i].rownum--;
  275. }
  276. //gkrellm_monitor_height_adjust(fmg[i].panel->h - ph);
  277. if (changed) {
  278. gkrellm_panel_configure(fmg[i].panel, NULL, style);
  279. gkrellm_panel_create(fm_vbox, monitor, fmg[i].panel);
  280. if (fmc[i].text[FM_LABEL]) {
  281. gkrellm_draw_decal_text(fmg[i].panel, fmg[i].label,
  282. fmc[i].text[FM_LABEL], -1);
  283. }
  284. }
  285. if (warning)
  286. system(fmc[i].text[FM_WARN]);
  287. if (alert)
  288. system(fmc[i].text[FM_ALERT]);
  289. gkrellm_draw_panel_layers(fmg[i].panel);
  290. }
  291. return;
  292. }
  293. /* creates "Sensors" monitor panel. the panel consists of label,
  294. * and led/name/value pair for each row found in rc_file
  295. */
  296. static void
  297. create_plugin(GtkWidget *vbox, gint first_create)
  298. {
  299. fm_vbox = vbox;
  300. create_fm_panels(first_create);
  301. force_update = TRUE;
  302. }
  303. static void
  304. destroy_fm_panels()
  305. {
  306. int i;
  307. for (i = 0; i < fmnum; i++) {
  308. if (fmg[i].panel) {
  309. // gkrellm_monitor_height_adjust(-fmg[i].panel->h);
  310. // gkrellm_destroy_decal_list(fmg[i].panel);
  311. // gkrellm_destroy_krell_list(fmg[i].panel);
  312. gkrellm_panel_destroy(fmg[i].panel);
  313. // g_free(fmg[i].panel);
  314. fmg[i].panel = NULL;
  315. fmg[i].rownum = 0;
  316. }
  317. }
  318. }
  319. static void
  320. create_fm_panels(int first_create)
  321. {
  322. GkrellmStyle *style;
  323. GkrellmTextstyle *ts, *ts_alt;
  324. int i;
  325. GkrellmPiximage *led = NULL;
  326. style = gkrellm_meter_style(style_id);
  327. ts = gkrellm_meter_textstyle(style_id);
  328. ts_alt = gkrellm_meter_alt_textstyle(style_id);
  329. /* gkrellm_load_image will kill red_led and orange_led if not NULL */
  330. gkrellm_load_piximage("fm_led", fm_led_xpm, &led, FM_STYLE_NAME);
  331. gkrellm_scale_piximage_to_pixmap(led, &ledp, &ledm, 0, 0);
  332. for (i = 0; i < fmnum; i++) {
  333. //int y;
  334. if (first_create)
  335. fmg[i].panel = gkrellm_panel_new0();
  336. else {
  337. gkrellm_destroy_krell_list(fmg[i].panel);
  338. gkrellm_destroy_decal_list(fmg[i].panel);
  339. fmg[i].rownum = 0;
  340. }
  341. fmg[i].panel->textstyle = ts; /* would be used for a panel label */
  342. fmg[i].y = 0;
  343. if (fmc[i].text[FM_LABEL]) {
  344. fmg[i].label = gkrellm_create_decal_text(fmg[i].panel,
  345. fmc[i].text[FM_LABEL], ts, style, -1, -1, -1);
  346. fmg[i].y = fmg[i].label->y + fmg[i].label->h;
  347. }
  348. else /* If no label, start remaining decals at top margin */
  349. gkrellm_get_top_bottom_margins(style, &fmg[i].y, NULL);
  350. gkrellm_panel_configure(fmg[i].panel, NULL, style);
  351. //panel->label->h_panel += 2; /* Some bottom margin */
  352. gkrellm_panel_create(fm_vbox, monitor, fmg[i].panel);
  353. if (fmc[i].text[FM_LABEL]) {
  354. gkrellm_draw_decal_text(fmg[i].panel, fmg[i].label,
  355. fmc[i].text[FM_LABEL], 1);
  356. }
  357. if (first_create)
  358. gtk_signal_connect(GTK_OBJECT (fmg[i].panel->drawing_area), "expose_event",
  359. (GtkSignalFunc) panel_expose_event, NULL);
  360. gkrellm_draw_panel_layers(fmg[i].panel);
  361. }
  362. if (first_create)
  363. run_update_cmds();
  364. }
  365. static void
  366. item_sel(GtkWidget *clist, gint row, gint column,
  367. GdkEventButton *event,
  368. gpointer data )
  369. {
  370. gchar *tmp;
  371. int i;
  372. selrow = row;
  373. for (i = 0; i < FM_ENTRY_NUM; i++) {
  374. if (gtk_clist_get_text(GTK_CLIST(config_list), row, i, &tmp)) {
  375. gtk_entry_set_text(GTK_ENTRY(entry[i]), tmp);
  376. } else {
  377. fprintf(stderr, "Strange: can't read %d-th col data "
  378. "of %d selected row\n", i, row);
  379. }
  380. }
  381. gtk_widget_set_sensitive(btn_del, TRUE);
  382. return;
  383. }
  384. static void
  385. item_unsel(GtkWidget *clist, gint row, gint column, GdkEventButton *event,
  386. gpointer data )
  387. {
  388. int i;
  389. selrow = -1;
  390. for (i = 0; i < FM_ENTRY_NUM; i++) {
  391. gtk_entry_set_text(GTK_ENTRY(entry[i]), "");
  392. }
  393. gtk_widget_set_sensitive(btn_del, FALSE);
  394. return;
  395. }
  396. static void
  397. on_add_click(GtkButton *button, gpointer *data)
  398. {
  399. char str[80];
  400. int i;
  401. fm_data c;
  402. if (!*gtk_entry_get_text(GTK_ENTRY(entry[FM_FILE]))) {
  403. sprintf(str, "You must specify file to monitor.\n");
  404. fr_message(str);
  405. return;
  406. }
  407. if (selrow >= 0) {
  408. /* we're editing existing entry */
  409. gtk_clist_freeze( GTK_CLIST(config_list) );
  410. for (i = 0; i < FM_ENTRY_NUM; i++) {
  411. gtk_clist_set_text(GTK_CLIST(config_list), selrow, i,
  412. gtk_entry_get_text(GTK_ENTRY(entry[i])));
  413. }
  414. gtk_clist_thaw( GTK_CLIST(config_list) );
  415. } else {
  416. /* we're adding new row */
  417. if (cnum == MAXFILENUM) {
  418. sprintf(str, "Maximum (%d) files has reached.\nSorry.\n",
  419. MAXFILENUM);
  420. fr_message(str);
  421. return;
  422. }
  423. cnum++;
  424. for (i = 0; i < FM_ENTRY_NUM; i++) {
  425. c.text[i] = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry[i])));
  426. }
  427. gtk_clist_append (GTK_CLIST(config_list), c.text);
  428. for (i = 0; i < FM_ENTRY_NUM; i++) {
  429. g_free(c.text[i]);
  430. }
  431. }
  432. return;
  433. }
  434. static void
  435. on_del_click(GtkButton *button, gpointer *data)
  436. {
  437. if (selrow == -1) return;
  438. gtk_clist_remove(GTK_CLIST(config_list), selrow);
  439. cnum--;
  440. }
  441. static void
  442. create_config_tab(GtkWidget *tab_vbox)
  443. {
  444. GtkWidget *vbox;
  445. GtkWidget *tabs;
  446. GtkWidget *text;
  447. GtkWidget *btn_hbox;
  448. gchar *titles[]={"Lable","File",
  449. "Update Command",
  450. "Warning Command",
  451. "Alert Command",
  452. "Interval"};
  453. GtkWidget *edit_table, *scrolled_window;
  454. GtkWidget *llabel, *lfile, *lupdate, *lwarn, *lalert, *linterval, *linterval2;
  455. gint i;
  456. //item_t *item;
  457. tabs = gtk_notebook_new();
  458. gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
  459. gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0);
  460. /* Preferences Tab */
  461. vbox = gkrellm_gtk_notebook_page(tabs, "Preferences");
  462. // Edit table
  463. edit_table = gtk_table_new(3, 5, FALSE);
  464. llabel = gtk_label_new("Label:");
  465. gtk_misc_set_alignment (GTK_MISC (llabel), 1, 1);
  466. gtk_table_attach(GTK_TABLE(edit_table), llabel, 0, 1, 0, 1, GTK_FILL, 0, 1,
  467. 1);
  468. entry[FM_LABEL] = gtk_entry_new_with_max_length(9);
  469. gtk_table_attach(GTK_TABLE(edit_table), entry[FM_LABEL], 1, 2, 0, 1, 0, 0, 1
  470. , 1);
  471. llabel = gtk_label_new(" ");
  472. gtk_misc_set_alignment (GTK_MISC (llabel), 1, 1);
  473. gtk_table_attach(GTK_TABLE(edit_table), llabel, 2, 3, 0, 1,
  474. GTK_FILL|GTK_EXPAND, 0, 1, 1);
  475. lfile = gtk_label_new("File to monitor:");
  476. gtk_misc_set_alignment (GTK_MISC (lfile), 1, 1);
  477. gtk_table_attach(GTK_TABLE(edit_table), lfile, 0, 1, 1, 2, GTK_FILL, 0, 1,
  478. 1);
  479. entry[FM_FILE] = gtk_entry_new_with_max_length(255);
  480. gtk_table_attach(GTK_TABLE(edit_table), entry[FM_FILE], 1, 3, 1, 2,
  481. GTK_FILL|GTK_EXPAND, 0, 1, 1);
  482. lupdate = gtk_label_new("Update Command:");
  483. gtk_misc_set_alignment (GTK_MISC (lupdate), 1, 1);
  484. gtk_table_attach(GTK_TABLE(edit_table), lupdate, 0, 1, 2, 3, GTK_FILL, 0, 1,
  485. 1);
  486. entry[FM_UPDATE] = gtk_entry_new_with_max_length(255);
  487. gtk_table_attach(GTK_TABLE(edit_table), entry[FM_UPDATE], 1, 3, 2, 3,
  488. GTK_FILL, 0, 1, 1);
  489. lwarn = gtk_label_new("Warning Command:");
  490. gtk_misc_set_alignment (GTK_MISC (lwarn), 1, 1);
  491. gtk_table_attach(GTK_TABLE(edit_table), lwarn, 0, 1, 3, 4, GTK_FILL, 0, 1, 1
  492. );
  493. entry[FM_WARN] = gtk_entry_new_with_max_length(255);
  494. gtk_table_attach(GTK_TABLE(edit_table), entry[FM_WARN], 1, 3, 3, 4,
  495. GTK_FILL, 0, 1, 1);
  496. lalert = gtk_label_new("Alert Command:");
  497. gtk_misc_set_alignment (GTK_MISC (lalert), 1, 1);
  498. gtk_table_attach(GTK_TABLE(edit_table), lalert, 0, 1, 4, 5, GTK_FILL, 0, 1, 1);
  499. entry[FM_ALERT] = gtk_entry_new_with_max_length(255);
  500. gtk_table_attach(GTK_TABLE(edit_table), entry[FM_ALERT], 1, 3, 4, 5,
  501. GTK_FILL, 0, 1, 1);
  502. linterval = gtk_label_new("Check Interval:");
  503. gtk_misc_set_alignment (GTK_MISC (linterval), 1, 1);
  504. gtk_table_attach(GTK_TABLE(edit_table), linterval, 0, 1, 5, 6, GTK_FILL, 0, 1, 1);
  505. entry[FM_INTERVAL] = gtk_entry_new_with_max_length(4);
  506. gtk_table_attach(GTK_TABLE(edit_table), entry[FM_INTERVAL], 1, 2, 5, 6,
  507. GTK_FILL, 0, 1, 1);
  508. linterval2 = gtk_label_new("seconds");
  509. gtk_misc_set_alignment (GTK_MISC (linterval2), 0, 1);
  510. gtk_table_attach(GTK_TABLE(edit_table), linterval2, 2, 3, 5, 6, GTK_FILL, 0, 1, 1);
  511. // Buttons to accept/reject config. data in the edit box
  512. btn_hbox = gtk_hbox_new(FALSE, 5);
  513. btn_enter=gtk_button_new_with_label("Enter");
  514. gtk_signal_connect(GTK_OBJECT(btn_enter), "clicked",
  515. GTK_SIGNAL_FUNC(on_add_click),NULL);
  516. btn_del=gtk_button_new_with_label("Delete");
  517. gtk_widget_set_sensitive(btn_del, FALSE);
  518. gtk_signal_connect(GTK_OBJECT(btn_del), "clicked",
  519. GTK_SIGNAL_FUNC(on_del_click),NULL);
  520. gtk_box_pack_start(GTK_BOX(btn_hbox), btn_enter, TRUE, FALSE, 2);
  521. gtk_box_pack_start(GTK_BOX(btn_hbox), btn_del, TRUE, FALSE, 2);
  522. // List with saved configurations
  523. scrolled_window = gtk_scrolled_window_new (NULL, NULL);
  524. gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
  525. GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS);
  526. config_list = gtk_clist_new_with_titles(6,titles);
  527. gtk_container_add(GTK_CONTAINER(scrolled_window), config_list);
  528. gtk_signal_connect(GTK_OBJECT(config_list), "select-row",
  529. GTK_SIGNAL_FUNC(item_sel), NULL);
  530. gtk_signal_connect(GTK_OBJECT(config_list), "unselect-row",
  531. GTK_SIGNAL_FUNC(item_unsel), NULL);
  532. gtk_clist_set_selection_mode(GTK_CLIST(config_list), GTK_SELECTION_SINGLE);
  533. for (i=0; i<6; i++) {
  534. int width;
  535. switch (i) {
  536. case 0: width=70;break;
  537. case 1: width=80;break;
  538. default: width=150;break;
  539. }
  540. gtk_clist_set_column_width(GTK_CLIST(config_list), i, width);
  541. }
  542. for (i = 0; i < fmnum; i++)
  543. gtk_clist_append(GTK_CLIST(config_list), fmc[i].text);
  544. cnum = fmnum;
  545. //gtk_clist_columns_autosize(GTK_CLIST(config_list));
  546. gtk_box_pack_start(GTK_BOX(vbox), edit_table, FALSE, FALSE, 2);
  547. gtk_box_pack_start(GTK_BOX(vbox), btn_hbox, FALSE, FALSE, 2);
  548. gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 2);
  549. /* Info Tab */
  550. vbox = gkrellm_gtk_notebook_page(tabs, "Info");
  551. text = gkrellm_gtk_scrolled_text_view(vbox, NULL, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
  552. gkrellm_gtk_text_view_append_strings(text,plugin_info,sizeof(plugin_info)/sizeof(gchar *));
  553. }
  554. static void
  555. save_config(FILE *f)
  556. {
  557. int i, j;
  558. for (i = 0; i < fmnum; i++) {
  559. for (j = 0; j < FM_ENTRY_NUM; j++) {
  560. fprintf(f, "FMonitor %s:%d:%s\n", config_name[j], i,
  561. fmc[i].text[j] ? fmc[i].text[j] : "");
  562. }
  563. }
  564. }
  565. static void
  566. load_config( gchar* arg )
  567. {
  568. char *tmp, *tmp2, *name, *value;
  569. int rowno, i;
  570. tmp = g_strdup(arg);
  571. name = strtok(tmp, ":");
  572. if (!name) return;
  573. tmp2 = strtok(NULL, ":");
  574. if (!tmp2) return;
  575. rowno = atoi(tmp2);
  576. if (rowno < MAXFILENUM) {
  577. value = strtok(NULL, "\n");
  578. for (i = 0; i < FM_ENTRY_NUM; i++) {
  579. if (!strcmp(name, config_name[i])) {
  580. if (value)
  581. fmc[rowno].text[i] = g_strdup(value);
  582. else
  583. fmc[rowno].text[i] = g_strdup("");
  584. }
  585. }
  586. fmc[rowno].ticker = 10000;
  587. if (rowno+1 > fmnum) fmnum = rowno+1;
  588. }
  589. g_free(tmp);
  590. }
  591. static void
  592. del_fmc_entries()
  593. {
  594. int i, no;
  595. for (no = 0; no < fmnum; no++) {
  596. for (i = 0; i < FM_ENTRY_NUM; i++) {
  597. MY_FREE(fmc[no].text[i]);
  598. }
  599. }
  600. }
  601. static void
  602. run_update_cmds()
  603. {
  604. int i, pid, ac;
  605. char *arg[MAXARGNUM], *cmd;
  606. //fprintf(stderr, "run_update_cmds\n");
  607. for (i = 0; i < fmnum; i++) {
  608. cmd = g_strdup(fmc[i].text[FM_UPDATE]);
  609. ac = 0;
  610. arg[ac] = strtok(cmd, " \n\t");
  611. while ((ac < MAXARGNUM-1) && arg[ac])
  612. arg[++ac] = strtok(NULL, " \n\t");
  613. if (arg[0] && *(arg[0])) {
  614. pid = fork();
  615. if (pid) {
  616. //papa
  617. fmc[i].pid = pid;
  618. g_free(cmd);
  619. } else {
  620. //son
  621. execvp(arg[0], arg);
  622. fprintf(stderr, "Can't execvp <%s>\n", fmc[i].text[FM_UPDATE]);
  623. _exit(1);
  624. }
  625. }
  626. }
  627. }
  628. static void
  629. kill_update_cmds()
  630. {
  631. int i;
  632. //fprintf(stderr, "kill_update_cmds\n");
  633. for (i = 0; i < fmnum; i++) {
  634. if (fmc[i].pid) {
  635. //fprintf(stderr, "\tkilling %d\n", fmc[i].pid);
  636. kill(fmc[i].pid, SIGKILL);
  637. }
  638. }
  639. }
  640. static void
  641. apply_config()
  642. {
  643. char *tmp;
  644. int i;
  645. selrow = -1;
  646. //fprintf(stderr, "apply_config\n");
  647. item_unsel(GTK_WIDGET(config_list), 0, 0, NULL, NULL);
  648. del_fmc_entries();
  649. kill_update_cmds();
  650. destroy_fm_panels();
  651. fmnum = 0;
  652. while (gtk_clist_get_text(GTK_CLIST(config_list), fmnum, 0, &tmp)) {
  653. for (i = 0; i < FM_ENTRY_NUM; i++) {
  654. if (gtk_clist_get_text(GTK_CLIST(config_list), fmnum, i, &tmp))
  655. fmc[fmnum].text[i] = g_strdup(tmp);
  656. }
  657. fmc[fmnum].ticker = 10000;
  658. fmnum++;
  659. if (fmnum == MAXFILENUM)
  660. break;
  661. }
  662. create_fm_panels(1);
  663. force_update = TRUE;
  664. }
  665. static void my_wait(int signo)
  666. {
  667. waitpid(-1, NULL, WNOHANG | WUNTRACED);
  668. }
  669. /* The monitor structure tells GKrellM how to call the plugin routines.
  670. */
  671. static GkrellmMonitor plugin_mon =
  672. {
  673. FM_CONFIG_NAME, /* Name, for config tab. */
  674. 0, /* Id, 0 if a plugin */
  675. create_plugin, /* The create function */
  676. update_plugin, /* The update function */
  677. create_config_tab, /* The config tab create function */
  678. apply_config, /* Apply the config function */
  679. save_config, /* Save user config */
  680. load_config, /* Load user config */
  681. FM_CONFIG_NAME, /* config keyword */
  682. NULL, /* Undefined 2 */
  683. NULL, /* Undefined 1 */
  684. NULL, /* private */
  685. MON_MAIL, /* Insert plugin before this monitor */
  686. NULL, /* Handle if a plugin, filled in by GKrellM */
  687. NULL /* path if a plugin, filled in by GKrellM */
  688. };
  689. /* All GKrellM plugins must have one global routine named init_plugin()
  690. | which returns a pointer to a filled in monitor structure.
  691. */
  692. GkrellmMonitor *
  693. gkrellm_init_plugin()
  694. {
  695. style_id = gkrellm_add_meter_style(&plugin_mon, FM_STYLE_NAME);
  696. atexit(kill_update_cmds);
  697. signal(SIGCHLD, my_wait);
  698. monitor = &plugin_mon;
  699. return &plugin_mon;
  700. }