]> git.sur5r.net Git - bacula/bacula/commitdiff
add src/tray-monitor directory
authorNicolas Boichat <nicolas@boichat.ch>
Sat, 14 Aug 2004 11:45:47 +0000 (11:45 +0000)
committerNicolas Boichat <nicolas@boichat.ch>
Sat, 14 Aug 2004 11:45:47 +0000 (11:45 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1528 91ce42f0-d328-0410-95d8-f526ca767f89

14 files changed:
bacula/src/tray-monitor/Makefile.in [new file with mode: 0644]
bacula/src/tray-monitor/authenticate.c [new file with mode: 0644]
bacula/src/tray-monitor/eggmarshalers.c [new file with mode: 0644]
bacula/src/tray-monitor/eggmarshalers.h [new file with mode: 0644]
bacula/src/tray-monitor/eggmarshalers.list [new file with mode: 0644]
bacula/src/tray-monitor/eggstatusicon.c [new file with mode: 0644]
bacula/src/tray-monitor/eggstatusicon.h [new file with mode: 0644]
bacula/src/tray-monitor/eggtrayicon.c [new file with mode: 0644]
bacula/src/tray-monitor/eggtrayicon.h [new file with mode: 0644]
bacula/src/tray-monitor/tray-monitor.c [new file with mode: 0644]
bacula/src/tray-monitor/tray-monitor.conf.in [new file with mode: 0644]
bacula/src/tray-monitor/tray-monitor.h [new file with mode: 0644]
bacula/src/tray-monitor/tray_conf.c [new file with mode: 0644]
bacula/src/tray-monitor/tray_conf.h [new file with mode: 0644]

diff --git a/bacula/src/tray-monitor/Makefile.in b/bacula/src/tray-monitor/Makefile.in
new file mode 100644 (file)
index 0000000..d93e4b0
--- /dev/null
@@ -0,0 +1,103 @@
+#
+#  Version $Id$
+#
+@MCOMMON@
+
+srcdir =       .
+VPATH =        .
+.PATH:         .
+
+# one up
+basedir = ..
+# top dir
+topdir = ../..
+# this dir relative to top dir
+thisdir = src/tray-monitor
+
+DEBUG=@DEBUG@
+
+first_rule: all
+dummy:
+
+#
+MONITORSRCS = tray-monitor.c tray_conf.c authenticate.c eggmarshalers.c eggstatusicon.c eggtrayicon.c
+MONITOROBJS = tray-monitor.o tray_conf.o authenticate.o eggmarshalers.o eggstatusicon.o eggtrayicon.o
+
+# these are the objects that are changed by the .configure process
+EXTRAOBJS = @OBJLIST@
+
+MONITOR_CPPFLAGS=@TRAY_MONITOR_CPPFLAGS@
+MONITOR_LDFLAGS=@TRAY_MONITOR_LDFLAGS@
+
+.SUFFIXES:     .c .o
+.PHONY:
+.DONTCARE:
+
+# inference rules
+.c.o:
+       $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) $(MONITOR_CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $<
+#-------------------------------------------------------------------------
+all: Makefile bacula-tray-monitor @STATIC_CONS@
+       @echo "==== Make of bacula-tray-monitor is good ===="
+       @echo " "
+
+bacula-tray-monitor: $(MONITOROBJS) ../lib/libbac.a
+       $(CXX) $(LDFLAGS) $(MONITOR_LDFLAGS) -L../lib -L../cats -o $@ $(MONITOROBJS) \
+             $(DLIB) -lbac -lm $(LIBS) 
+
+
+Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
+       cd $(topdir) \
+         && CONFIG_FILES=$(thisdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+clean:
+       @$(RMF) bacula-tray-monitor core core.* a.out *.o *.bak *~ *.intpro *.extpro 1 2 3
+
+realclean: clean
+       @$(RMF) tags tray-monitor.conf
+
+distclean: realclean
+       if test $(srcdir) = .; then $(MAKE) realclean; fi
+       (cd $(srcdir); $(RMF) Makefile; $(RMF) -r CVS)
+
+devclean: realclean
+       if test $(srcdir) = .; then $(MAKE) realclean; fi
+       (cd $(srcdir); $(RMF) Makefile)
+
+install: all
+       $(INSTALL_PROGRAM) bacula-tray-monitor $(DESTDIR)$(sbindir)/bacula-tray-monitor
+       @srcconf=tray-monitor.conf; \
+       if  test -f ${DESTDIR}${sysconfdir}/$$srcconf; then \
+          destconf=$$srcconf.new; \
+          echo "  ==> Found existing $$srcconf, installing new conf file as $$destconf"; \
+       else \
+          destconf=$$srcconf; \
+       fi; \
+       echo "${INSTALL_CONFIG} $$srcconf ${DESTDIR}${sysconfdir}/$$destconf"; \
+       ${INSTALL_CONFIG} $$srcconf ${DESTDIR}${sysconfdir}/$$destconf
+
+uninstall:
+       (cd $(DESTDIR)$(sbindir); $(RMF) bacula-tray-monitor)
+       (cd $(DESTDIR)$(sysconfdir); $(RMF) tray-monitor.conf)
+
+
+
+# Semi-automatic generation of dependencies:
+# Use gcc -MM because X11 `makedepend' doesn't work on all systems
+# and it also includes system headers.
+# `semi'-automatic since dependencies are generated at distribution time.
+
+depend:
+       @$(MV) Makefile Makefile.bak
+       @$(SED) "/^# DO NOT DELETE:/,$$ d" Makefile.bak > Makefile
+       @$(ECHO) "# DO NOT DELETE: nice dependency list follows" >> Makefile
+       @$(CC) -S -M $(CPPFLAGS) $(CONS_INC) -I$(srcdir) -I$(basedir) *.c >> Makefile
+       @if test -f Makefile ; then \
+           $(RMF) Makefile.bak; \
+       else \
+          $(MV) Makefile.bak Makefile; \
+          echo -e "Something went wrong\n\a"; \
+       fi
+
+# -----------------------------------------------------------------------
+# DO NOT DELETE: nice dependency list follows
diff --git a/bacula/src/tray-monitor/authenticate.c b/bacula/src/tray-monitor/authenticate.c
new file mode 100644 (file)
index 0000000..f6afcf4
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *
+ *   Bacula UA authentication. Provides authentication with
+ *     the Director.
+ *
+ *     Kern Sibbald, June MMI
+ *
+ *    This routine runs as a thread and must be thread reentrant.
+ *
+ *  Basic tasks done here:
+ *
+ */
+/*
+   Copyright (C) 2001-2004 Kern Sibbald and John Walker
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2
+   of the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, 
+   MA 02111-1307, USA.
+ */
+
+#include "bacula.h"
+#include "tray-monitor.h"
+#include "jcr.h"
+
+void senditf(const char *fmt, ...);
+void sendit(const char *buf); 
+
+/* Commands sent to Storage daemon and File daemon and received
+ *  from the User Agent */
+static char hello[]    = "Hello Director %s calling\n";
+
+/* Response from FD */
+static char FDOKhello[] = "2000 OK Hello\n";
+
+/* Forward referenced functions */
+
+/*
+ * Authenticate File daemon connection
+ */
+int authenticate_file_daemon(JCR *jcr, MONITOR *monitor, CLIENT* client)
+{
+   BSOCK *fd = jcr->file_bsock;
+   char dirname[MAX_NAME_LENGTH];
+   int ssl_need = BNET_SSL_NONE;
+
+   /* 
+    * Send my name to the File daemon then do authentication
+    */
+   bstrncpy(dirname, monitor->hdr.name, sizeof(dirname));
+   bash_spaces(dirname);
+   /* Timeout Hello after 5 mins */
+   btimer_t *tid = start_bsock_timer(fd, 60 * 5);
+   if (!bnet_fsend(fd, hello, dirname)) {
+      stop_bsock_timer(tid);
+      Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon. ERR=%s\n"), bnet_strerror(fd));
+      return 0;
+   }
+   if (!cram_md5_get_auth(fd, client->password, ssl_need) || 
+       !cram_md5_auth(fd, client->password, ssl_need)) {
+      stop_bsock_timer(tid);
+      Jmsg(jcr, M_FATAL, 0, _("Director and File daemon passwords or names not the same.\n"   
+       "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"));
+      return 0;
+   }
+   Dmsg1(116, ">filed: %s", fd->msg);
+   if (bnet_recv(fd) <= 0) {
+      stop_bsock_timer(tid);
+      Jmsg(jcr, M_FATAL, 0, _("Bad response from File daemon to Hello command: ERR=%s\n"),
+        bnet_strerror(fd));
+      return 0;
+   }
+   Dmsg1(110, "<stored: %s", fd->msg);
+   stop_bsock_timer(tid);
+   if (strncmp(fd->msg, FDOKhello, sizeof(FDOKhello)) != 0) {
+      Jmsg(jcr, M_FATAL, 0, _("File daemon rejected Hello command\n"));
+      return 0;
+   }
+   return 1;
+}
diff --git a/bacula/src/tray-monitor/eggmarshalers.c b/bacula/src/tray-monitor/eggmarshalers.c
new file mode 100644 (file)
index 0000000..5448488
--- /dev/null
@@ -0,0 +1,561 @@
+
+extern "C" {
+
+#include       <glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* VOID:OBJECT,OBJECT (eggmarshalers.list:1) */
+void
+_egg_marshal_VOID__OBJECT_OBJECT (GClosure     *closure,
+                                  GValue       *return_value,
+                                  guint         n_param_values,
+                                  const GValue *param_values,
+                                  gpointer      invocation_hint,
+                                  gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer     data1,
+                                                    gpointer     arg_1,
+                                                    gpointer     arg_2,
+                                                    gpointer     data2);
+  register GMarshalFunc_VOID__OBJECT_OBJECT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_object (param_values + 1),
+            g_marshal_value_peek_object (param_values + 2),
+            data2);
+}
+
+/* VOID:OBJECT,STRING,LONG,LONG (eggmarshalers.list:2) */
+void
+_egg_marshal_VOID__OBJECT_STRING_LONG_LONG (GClosure     *closure,
+                                            GValue       *return_value,
+                                            guint         n_param_values,
+                                            const GValue *param_values,
+                                            gpointer      invocation_hint,
+                                            gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG) (gpointer     data1,
+                                                              gpointer     arg_1,
+                                                              gpointer     arg_2,
+                                                              glong        arg_3,
+                                                              glong        arg_4,
+                                                              gpointer     data2);
+  register GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 5);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_object (param_values + 1),
+            g_marshal_value_peek_string (param_values + 2),
+            g_marshal_value_peek_long (param_values + 3),
+            g_marshal_value_peek_long (param_values + 4),
+            data2);
+}
+
+/* VOID:OBJECT,LONG (eggmarshalers.list:3) */
+void
+_egg_marshal_VOID__OBJECT_LONG (GClosure     *closure,
+                                GValue       *return_value,
+                                guint         n_param_values,
+                                const GValue *param_values,
+                                gpointer      invocation_hint,
+                                gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__OBJECT_LONG) (gpointer     data1,
+                                                  gpointer     arg_1,
+                                                  glong        arg_2,
+                                                  gpointer     data2);
+  register GMarshalFunc_VOID__OBJECT_LONG callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__OBJECT_LONG) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_object (param_values + 1),
+            g_marshal_value_peek_long (param_values + 2),
+            data2);
+}
+
+/* VOID:OBJECT,STRING,STRING (eggmarshalers.list:4) */
+void
+_egg_marshal_VOID__OBJECT_STRING_STRING (GClosure     *closure,
+                                         GValue       *return_value,
+                                         guint         n_param_values,
+                                         const GValue *param_values,
+                                         gpointer      invocation_hint,
+                                         gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__OBJECT_STRING_STRING) (gpointer     data1,
+                                                           gpointer     arg_1,
+                                                           gpointer     arg_2,
+                                                           gpointer     arg_3,
+                                                           gpointer     data2);
+  register GMarshalFunc_VOID__OBJECT_STRING_STRING callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 4);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__OBJECT_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_object (param_values + 1),
+            g_marshal_value_peek_string (param_values + 2),
+            g_marshal_value_peek_string (param_values + 3),
+            data2);
+}
+
+/* VOID:UINT,UINT (eggmarshalers.list:5) */
+void
+_egg_marshal_VOID__UINT_UINT (GClosure     *closure,
+                              GValue       *return_value,
+                              guint         n_param_values,
+                              const GValue *param_values,
+                              gpointer      invocation_hint,
+                              gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__UINT_UINT) (gpointer     data1,
+                                                guint        arg_1,
+                                                guint        arg_2,
+                                                gpointer     data2);
+  register GMarshalFunc_VOID__UINT_UINT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__UINT_UINT) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_uint (param_values + 1),
+            g_marshal_value_peek_uint (param_values + 2),
+            data2);
+}
+
+/* BOOLEAN:INT (eggmarshalers.list:6) */
+void
+_egg_marshal_BOOLEAN__INT (GClosure     *closure,
+                           GValue       *return_value,
+                           guint         n_param_values,
+                           const GValue *param_values,
+                           gpointer      invocation_hint,
+                           gpointer      marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__INT) (gpointer     data1,
+                                                 gint         arg_1,
+                                                 gpointer     data2);
+  register GMarshalFunc_BOOLEAN__INT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__INT) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_int (param_values + 1),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
+/* BOOLEAN:ENUM (eggmarshalers.list:7) */
+void
+_egg_marshal_BOOLEAN__ENUM (GClosure     *closure,
+                            GValue       *return_value,
+                            guint         n_param_values,
+                            const GValue *param_values,
+                            gpointer      invocation_hint,
+                            gpointer      marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__ENUM) (gpointer     data1,
+                                                  gint         arg_1,
+                                                  gpointer     data2);
+  register GMarshalFunc_BOOLEAN__ENUM callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__ENUM) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_enum (param_values + 1),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
+/* BOOLEAN:VOID (eggmarshalers.list:8) */
+void
+_egg_marshal_BOOLEAN__VOID (GClosure     *closure,
+                            GValue       *return_value,
+                            guint         n_param_values,
+                            const GValue *param_values,
+                            gpointer      invocation_hint,
+                            gpointer      marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__VOID) (gpointer     data1,
+                                                  gpointer     data2);
+  register GMarshalFunc_BOOLEAN__VOID callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 1);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__VOID) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
+/* OBJECT:VOID (eggmarshalers.list:9) */
+void
+_egg_marshal_OBJECT__VOID (GClosure     *closure,
+                           GValue       *return_value,
+                           guint         n_param_values,
+                           const GValue *param_values,
+                           gpointer      invocation_hint,
+                           gpointer      marshal_data)
+{
+  typedef GObject* (*GMarshalFunc_OBJECT__VOID) (gpointer     data1,
+                                                 gpointer     data2);
+  register GMarshalFunc_OBJECT__VOID callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  GObject* v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 1);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_OBJECT__VOID) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       data2);
+
+  g_value_set_object_take_ownership (return_value, v_return);
+}
+
+/* VOID:VOID (eggmarshalers.list:10) */
+
+/* VOID:INT,INT (eggmarshalers.list:11) */
+void
+_egg_marshal_VOID__INT_INT (GClosure     *closure,
+                            GValue       *return_value,
+                            guint         n_param_values,
+                            const GValue *param_values,
+                            gpointer      invocation_hint,
+                            gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__INT_INT) (gpointer     data1,
+                                              gint         arg_1,
+                                              gint         arg_2,
+                                              gpointer     data2);
+  register GMarshalFunc_VOID__INT_INT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__INT_INT) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_int (param_values + 1),
+            g_marshal_value_peek_int (param_values + 2),
+            data2);
+}
+
+/* VOID:UINT,UINT (eggmarshalers.list:12) */
+
+/* VOID:BOOLEAN (eggmarshalers.list:13) */
+
+/* VOID:OBJECT,ENUM,BOXED (eggmarshalers.list:14) */
+void
+_egg_marshal_VOID__OBJECT_ENUM_BOXED (GClosure     *closure,
+                                      GValue       *return_value,
+                                      guint         n_param_values,
+                                      const GValue *param_values,
+                                      gpointer      invocation_hint,
+                                      gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__OBJECT_ENUM_BOXED) (gpointer     data1,
+                                                        gpointer     arg_1,
+                                                        gint         arg_2,
+                                                        gpointer     arg_3,
+                                                        gpointer     data2);
+  register GMarshalFunc_VOID__OBJECT_ENUM_BOXED callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 4);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__OBJECT_ENUM_BOXED) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_object (param_values + 1),
+            g_marshal_value_peek_enum (param_values + 2),
+            g_marshal_value_peek_boxed (param_values + 3),
+            data2);
+}
+
+/* VOID:BOXED (eggmarshalers.list:15) */
+
+/* BOOLEAN:BOOLEAN (eggmarshalers.list:16) */
+void
+_egg_marshal_BOOLEAN__BOOLEAN (GClosure     *closure,
+                               GValue       *return_value,
+                               guint         n_param_values,
+                               const GValue *param_values,
+                               gpointer      invocation_hint,
+                               gpointer      marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__BOOLEAN) (gpointer     data1,
+                                                     gboolean     arg_1,
+                                                     gpointer     data2);
+  register GMarshalFunc_BOOLEAN__BOOLEAN callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__BOOLEAN) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_boolean (param_values + 1),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
+/* BOOLEAN:OBJECT,STRING,STRING (eggmarshalers.list:17) */
+void
+_egg_marshal_BOOLEAN__OBJECT_STRING_STRING (GClosure     *closure,
+                                            GValue       *return_value,
+                                            guint         n_param_values,
+                                            const GValue *param_values,
+                                            gpointer      invocation_hint,
+                                            gpointer      marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__OBJECT_STRING_STRING) (gpointer     data1,
+                                                                  gpointer     arg_1,
+                                                                  gpointer     arg_2,
+                                                                  gpointer     arg_3,
+                                                                  gpointer     data2);
+  register GMarshalFunc_BOOLEAN__OBJECT_STRING_STRING callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 4);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__OBJECT_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_object (param_values + 1),
+                       g_marshal_value_peek_string (param_values + 2),
+                       g_marshal_value_peek_string (param_values + 3),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
+} // extern "C"
diff --git a/bacula/src/tray-monitor/eggmarshalers.h b/bacula/src/tray-monitor/eggmarshalers.h
new file mode 100644 (file)
index 0000000..c375dbc
--- /dev/null
@@ -0,0 +1,127 @@
+
+#ifndef ___egg_marshal_MARSHAL_H__
+#define ___egg_marshal_MARSHAL_H__
+
+#include       <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* VOID:OBJECT,OBJECT (eggmarshalers.list:1) */
+extern void _egg_marshal_VOID__OBJECT_OBJECT (GClosure     *closure,
+                                              GValue       *return_value,
+                                              guint         n_param_values,
+                                              const GValue *param_values,
+                                              gpointer      invocation_hint,
+                                              gpointer      marshal_data);
+
+/* VOID:OBJECT,STRING,LONG,LONG (eggmarshalers.list:2) */
+extern void _egg_marshal_VOID__OBJECT_STRING_LONG_LONG (GClosure     *closure,
+                                                        GValue       *return_value,
+                                                        guint         n_param_values,
+                                                        const GValue *param_values,
+                                                        gpointer      invocation_hint,
+                                                        gpointer      marshal_data);
+
+/* VOID:OBJECT,LONG (eggmarshalers.list:3) */
+extern void _egg_marshal_VOID__OBJECT_LONG (GClosure     *closure,
+                                            GValue       *return_value,
+                                            guint         n_param_values,
+                                            const GValue *param_values,
+                                            gpointer      invocation_hint,
+                                            gpointer      marshal_data);
+
+/* VOID:OBJECT,STRING,STRING (eggmarshalers.list:4) */
+extern void _egg_marshal_VOID__OBJECT_STRING_STRING (GClosure     *closure,
+                                                     GValue       *return_value,
+                                                     guint         n_param_values,
+                                                     const GValue *param_values,
+                                                     gpointer      invocation_hint,
+                                                     gpointer      marshal_data);
+
+/* VOID:UINT,UINT (eggmarshalers.list:5) */
+extern void _egg_marshal_VOID__UINT_UINT (GClosure     *closure,
+                                          GValue       *return_value,
+                                          guint         n_param_values,
+                                          const GValue *param_values,
+                                          gpointer      invocation_hint,
+                                          gpointer      marshal_data);
+
+/* BOOLEAN:INT (eggmarshalers.list:6) */
+extern void _egg_marshal_BOOLEAN__INT (GClosure     *closure,
+                                       GValue       *return_value,
+                                       guint         n_param_values,
+                                       const GValue *param_values,
+                                       gpointer      invocation_hint,
+                                       gpointer      marshal_data);
+
+/* BOOLEAN:ENUM (eggmarshalers.list:7) */
+extern void _egg_marshal_BOOLEAN__ENUM (GClosure     *closure,
+                                        GValue       *return_value,
+                                        guint         n_param_values,
+                                        const GValue *param_values,
+                                        gpointer      invocation_hint,
+                                        gpointer      marshal_data);
+
+/* BOOLEAN:VOID (eggmarshalers.list:8) */
+extern void _egg_marshal_BOOLEAN__VOID (GClosure     *closure,
+                                        GValue       *return_value,
+                                        guint         n_param_values,
+                                        const GValue *param_values,
+                                        gpointer      invocation_hint,
+                                        gpointer      marshal_data);
+
+/* OBJECT:VOID (eggmarshalers.list:9) */
+extern void _egg_marshal_OBJECT__VOID (GClosure     *closure,
+                                       GValue       *return_value,
+                                       guint         n_param_values,
+                                       const GValue *param_values,
+                                       gpointer      invocation_hint,
+                                       gpointer      marshal_data);
+
+/* VOID:VOID (eggmarshalers.list:10) */
+#define _egg_marshal_VOID__VOID        g_cclosure_marshal_VOID__VOID
+
+/* VOID:INT,INT (eggmarshalers.list:11) */
+extern void _egg_marshal_VOID__INT_INT (GClosure     *closure,
+                                        GValue       *return_value,
+                                        guint         n_param_values,
+                                        const GValue *param_values,
+                                        gpointer      invocation_hint,
+                                        gpointer      marshal_data);
+
+/* VOID:UINT,UINT (eggmarshalers.list:12) */
+
+/* VOID:BOOLEAN (eggmarshalers.list:13) */
+#define _egg_marshal_VOID__BOOLEAN     g_cclosure_marshal_VOID__BOOLEAN
+
+/* VOID:OBJECT,ENUM,BOXED (eggmarshalers.list:14) */
+extern void _egg_marshal_VOID__OBJECT_ENUM_BOXED (GClosure     *closure,
+                                                  GValue       *return_value,
+                                                  guint         n_param_values,
+                                                  const GValue *param_values,
+                                                  gpointer      invocation_hint,
+                                                  gpointer      marshal_data);
+
+/* VOID:BOXED (eggmarshalers.list:15) */
+#define _egg_marshal_VOID__BOXED       g_cclosure_marshal_VOID__BOXED
+
+/* BOOLEAN:BOOLEAN (eggmarshalers.list:16) */
+extern void _egg_marshal_BOOLEAN__BOOLEAN (GClosure     *closure,
+                                           GValue       *return_value,
+                                           guint         n_param_values,
+                                           const GValue *param_values,
+                                           gpointer      invocation_hint,
+                                           gpointer      marshal_data);
+
+/* BOOLEAN:OBJECT,STRING,STRING (eggmarshalers.list:17) */
+extern void _egg_marshal_BOOLEAN__OBJECT_STRING_STRING (GClosure     *closure,
+                                                        GValue       *return_value,
+                                                        guint         n_param_values,
+                                                        const GValue *param_values,
+                                                        gpointer      invocation_hint,
+                                                        gpointer      marshal_data);
+
+G_END_DECLS
+
+#endif /* ___egg_marshal_MARSHAL_H__ */
+
diff --git a/bacula/src/tray-monitor/eggmarshalers.list b/bacula/src/tray-monitor/eggmarshalers.list
new file mode 100644 (file)
index 0000000..d443ca7
--- /dev/null
@@ -0,0 +1,17 @@
+VOID:OBJECT,OBJECT
+VOID:OBJECT,STRING,LONG,LONG
+VOID:OBJECT,LONG
+VOID:OBJECT,STRING,STRING
+VOID:UINT,UINT
+BOOLEAN:INT
+BOOLEAN:ENUM
+BOOLEAN:VOID
+OBJECT:VOID
+VOID:VOID
+VOID:INT,INT
+VOID:UINT,UINT
+VOID:BOOLEAN
+VOID:OBJECT,ENUM,BOXED
+VOID:BOXED
+BOOLEAN:BOOLEAN
+BOOLEAN:OBJECT,STRING,STRING
diff --git a/bacula/src/tray-monitor/eggstatusicon.c b/bacula/src/tray-monitor/eggstatusicon.c
new file mode 100644 (file)
index 0000000..7b4ce61
--- /dev/null
@@ -0,0 +1,779 @@
+/* eggstatusicon.c:
+ *
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *     Mark McLoughlin <mark@skynet.ie>
+ */
+
+#include <string.h>
+#include <libintl.h>
+
+#include "eggstatusicon.h"
+
+#include <gtk/gtk.h>
+#include "eggmarshalers.h"
+
+#ifndef EGG_COMPILATION
+#ifndef _
+#define _(x) dgettext (GETTEXT_PACKAGE, x)
+#define N_(x) x
+#endif
+#else
+#define _(x) x
+#define N_(x) x
+#endif
+
+enum{
+  PROP_0,
+  PROP_PIXBUF,
+  PROP_FILE,
+  PROP_STOCK,
+  PROP_PIXBUF_ANIMATION,
+  PROP_STORAGE_TYPE,
+  PROP_SIZE,
+  PROP_BLINKING
+};
+
+enum {
+  ACTIVATE_SIGNAL,
+  POPUP_MENU_SIGNAL,
+  SIZE_CHANGED_SIGNAL,
+  LAST_SIGNAL
+};
+
+struct _EggStatusIconPrivate
+{
+  GtkWidget    *tray_icon;
+  GtkWidget    *image;
+  gint          size;
+
+  GtkTooltips  *tooltips;
+
+  GtkImageType  image_type;
+
+  union
+    {
+      GdkPixbuf          *pixbuf;
+      const gchar        *stock_id;
+      GdkPixbufAnimation *animimation;
+    } image_data;
+
+  GdkPixbuf    *blank_icon;
+  guint         blinking_timeout;
+
+  guint         blinking : 1;
+  guint         blink_off : 1;
+};
+
+static void egg_status_icon_class_init (EggStatusIconClass *klass);
+static void egg_status_icon_init       (EggStatusIcon      *status_icon);
+
+static void egg_status_icon_finalize     (GObject      *object);
+static void egg_status_icon_set_property (GObject      *object,
+                                         guint         prop_id,
+                                         const GValue *value,
+                                         GParamSpec   *pspec);
+static void egg_status_icon_get_property (GObject      *object,
+                                         guint         prop_id,
+                                         GValue       *value,
+                                         GParamSpec   *pspec);
+
+static void     egg_status_icon_size_allocate    (EggStatusIcon  *status_icon,
+                                                 GtkAllocation  *allocation);
+static gboolean egg_status_icon_button_release   (EggStatusIcon  *status_icon,
+                                                 GdkEventButton *event);
+static void     egg_status_icon_disable_blinking (EggStatusIcon  *status_icon);
+static void     egg_status_icon_reset_image_data (EggStatusIcon  *status_icon);
+                                          
+
+static GObjectClass *parent_class = NULL;
+static guint status_icon_signals [LAST_SIGNAL] = { 0 };
+
+GType
+egg_status_icon_get_type (void)
+{
+  static GType status_icon_type = 0;
+  
+  if (!status_icon_type)
+    {
+      static const GTypeInfo status_icon_info =
+      {
+       sizeof (EggStatusIconClass),
+       NULL,           /* base_init */
+       NULL,           /* base_finalize */
+       (GClassInitFunc) egg_status_icon_class_init,
+       NULL,           /* class_finalize */
+       NULL,           /* class_data */
+       sizeof (EggStatusIcon),
+       0,              /* n_preallocs */
+       (GInstanceInitFunc) egg_status_icon_init,
+      };
+      
+      status_icon_type = g_type_register_static (G_TYPE_OBJECT,
+                                                "EggStatusIcon",
+                                                &status_icon_info, (GTypeFlags)0);
+    }
+  
+  return status_icon_type;
+}
+
+static void
+egg_status_icon_class_init (EggStatusIconClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+
+  parent_class = (GObjectClass*)g_type_class_peek_parent (klass);
+
+  gobject_class->finalize     = egg_status_icon_finalize;
+  gobject_class->set_property = egg_status_icon_set_property;
+  gobject_class->get_property = egg_status_icon_get_property;
+
+  g_object_class_install_property (gobject_class,
+                                  PROP_PIXBUF,
+                                  g_param_spec_object ("pixbuf",
+                                                       "Pixbuf",
+                                                       "A GdkPixbuf to display",
+                                                       GDK_TYPE_PIXBUF,
+                                                       (GParamFlags)G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                  PROP_FILE,
+                                  g_param_spec_string ("file",
+                                                       "Filename",
+                                                       "Filename to load and display",
+                                                       NULL,
+                                                       G_PARAM_WRITABLE));
+
+  g_object_class_install_property (gobject_class,
+                                  PROP_STOCK,
+                                  g_param_spec_string ("stock",
+                                                       "Stock ID",
+                                                       "Stock ID for a stock image to display",
+                                                       NULL,
+                                                       (GParamFlags)G_PARAM_READWRITE));
+  
+  g_object_class_install_property (gobject_class,
+                                  PROP_PIXBUF_ANIMATION,
+                                  g_param_spec_object ("pixbuf-animation",
+                                                       "Animation",
+                                                       "GdkPixbufAnimation to display",
+                                                       GDK_TYPE_PIXBUF_ANIMATION,
+                                                       (GParamFlags)G_PARAM_READWRITE));
+  
+  g_object_class_install_property (gobject_class,
+                                  PROP_STORAGE_TYPE,
+                                  g_param_spec_enum ("image-type",
+                                                     "Image type",
+                                                     "The representation being used for image data",
+                                                     GTK_TYPE_IMAGE_TYPE,
+                                                     GTK_IMAGE_EMPTY,
+                                                     G_PARAM_READABLE));
+
+  g_object_class_install_property (gobject_class,
+                                  PROP_SIZE,
+                                  g_param_spec_int ("size",
+                                                    "Size",
+                                                    "The size of the icon",
+                                                    G_MININT,
+                                                    G_MAXINT,
+                                                    0,
+                                                    G_PARAM_READABLE));
+
+  g_object_class_install_property (gobject_class,
+                                  PROP_BLINKING,
+                                  g_param_spec_boolean ("blinking",
+                                                        "Blinking",
+                                                        "Whether or not the status icon is blinking",
+                                                        FALSE,
+                                                        (GParamFlags)G_PARAM_READWRITE));
+
+  status_icon_signals [ACTIVATE_SIGNAL] =
+    g_signal_new ("activate",
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
+                 G_STRUCT_OFFSET (EggStatusIconClass, activate),
+                 NULL,
+                 NULL,
+                 g_cclosure_marshal_VOID__VOID,
+                 G_TYPE_NONE,
+                 0);
+
+  status_icon_signals [POPUP_MENU_SIGNAL] =
+    g_signal_new ("popup-menu",
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
+                 G_STRUCT_OFFSET (EggStatusIconClass, popup_menu),
+                 NULL,
+                 NULL,
+                 _egg_marshal_VOID__UINT_UINT,
+                 G_TYPE_NONE,
+                 2,
+                 G_TYPE_UINT,
+                 G_TYPE_UINT);
+
+  status_icon_signals [SIZE_CHANGED_SIGNAL] =
+    g_signal_new ("size-changed",
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET (EggStatusIconClass, size_changed),
+                 NULL,
+                 NULL,
+                 g_cclosure_marshal_VOID__INT,
+                 G_TYPE_NONE,
+                 1,
+                 G_TYPE_INT);
+}
+
+static void
+egg_status_icon_init (EggStatusIcon *status_icon)
+{
+  status_icon->priv = g_new0 (EggStatusIconPrivate, 1);
+
+  status_icon->priv->image_type = GTK_IMAGE_EMPTY;
+  status_icon->priv->size       = G_MAXINT;
+
+  status_icon->priv->tray_icon = GTK_WIDGET (egg_tray_icon_new (NULL));
+
+  gtk_widget_add_events (GTK_WIDGET (status_icon->priv->tray_icon),
+                        GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
+
+  g_signal_connect_swapped (status_icon->priv->tray_icon, "button-release-event",
+                           G_CALLBACK (egg_status_icon_button_release), status_icon);
+
+  status_icon->priv->image = gtk_image_new ();
+  gtk_container_add (GTK_CONTAINER (status_icon->priv->tray_icon),
+                    status_icon->priv->image);
+
+  g_signal_connect_swapped (status_icon->priv->image, "size-allocate",
+                           G_CALLBACK (egg_status_icon_size_allocate), status_icon);
+
+  gtk_widget_show (status_icon->priv->image);
+  gtk_widget_show (status_icon->priv->tray_icon);
+
+  status_icon->priv->tooltips = gtk_tooltips_new ();
+  g_object_ref (status_icon->priv->tooltips);
+  gtk_object_sink (GTK_OBJECT (status_icon->priv->tooltips));
+}
+
+static void
+egg_status_icon_finalize (GObject *object)
+{
+  EggStatusIcon *status_icon = EGG_STATUS_ICON (object);
+
+  egg_status_icon_disable_blinking (status_icon);
+
+  egg_status_icon_reset_image_data (status_icon);
+
+  if (status_icon->priv->blank_icon)
+    g_object_unref (status_icon->priv->blank_icon);
+  status_icon->priv->blank_icon = NULL;
+
+  if (status_icon->priv->tooltips)
+    g_object_unref (status_icon->priv->tooltips);
+  status_icon->priv->tooltips = NULL;
+
+  gtk_widget_destroy (status_icon->priv->tray_icon);
+
+  g_free (status_icon->priv);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+egg_status_icon_set_property (GObject      *object,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  EggStatusIcon *status_icon = EGG_STATUS_ICON (object);
+
+  switch (prop_id)
+    {
+    case PROP_PIXBUF:
+      egg_status_icon_set_from_pixbuf (status_icon, (GdkPixbuf*)g_value_get_object (value));
+      break;
+    case PROP_FILE:
+      egg_status_icon_set_from_file (status_icon, g_value_get_string (value));
+      break;
+    case PROP_STOCK:
+      egg_status_icon_set_from_stock (status_icon, g_value_get_string (value));
+      break;
+    case PROP_PIXBUF_ANIMATION:
+      egg_status_icon_set_from_animation (status_icon, (GdkPixbufAnimation*)g_value_get_object (value));
+      break;
+    case PROP_BLINKING:
+      egg_status_icon_set_is_blinking (status_icon, g_value_get_boolean (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+egg_status_icon_get_property (GObject    *object,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+  EggStatusIcon *status_icon = EGG_STATUS_ICON (object);
+
+  switch (prop_id)
+    {
+    case PROP_PIXBUF:
+      g_value_set_object (value, egg_status_icon_get_pixbuf (status_icon));
+      break;
+    case PROP_STOCK:
+      g_value_set_string (value, egg_status_icon_get_stock (status_icon));
+      break;
+    case PROP_PIXBUF_ANIMATION:
+      g_value_set_object (value, egg_status_icon_get_animation (status_icon));
+      break;
+    case PROP_STORAGE_TYPE:
+      g_value_set_enum (value, egg_status_icon_get_image_type (status_icon));
+      break;
+    case PROP_SIZE:
+      g_value_set_int (value, status_icon->priv->size);
+      break;
+    case PROP_BLINKING:
+      g_value_set_boolean (value, status_icon->priv->blinking);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+EggStatusIcon *
+egg_status_icon_new (void)
+{
+  return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON, NULL);
+}
+
+EggStatusIcon *
+egg_status_icon_new_from_pixbuf (GdkPixbuf *pixbuf)
+{
+  return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON,
+                      "pixbuf", pixbuf,
+                      NULL);
+}
+
+EggStatusIcon *
+egg_status_icon_new_from_file (const gchar *filename)
+{
+  return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON,
+                      "file", filename,
+                      NULL);
+}
+
+EggStatusIcon *
+egg_status_icon_new_from_stock (const gchar *stock_id)
+{
+  return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON,
+                      "stock", stock_id,
+                      NULL);
+}
+
+EggStatusIcon *
+egg_status_icon_new_from_animation (GdkPixbufAnimation *animation)
+{
+  return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON,
+                      "pixbuf_animation", animation,
+                      NULL);
+}
+
+static void
+emit_activate_signal (EggStatusIcon *status_icon)
+{
+  g_signal_emit (status_icon,
+                status_icon_signals [ACTIVATE_SIGNAL], 0);
+}
+
+static void
+emit_popup_menu_signal (EggStatusIcon *status_icon,
+                       guint          button,
+                       guint32        activate_time)
+{
+  g_signal_emit (status_icon,
+                status_icon_signals [POPUP_MENU_SIGNAL], 0,
+                button,
+                activate_time);
+}
+
+static gboolean
+emit_size_changed_signal (EggStatusIcon *status_icon,
+                         gint           size)
+{
+  gboolean handled = FALSE;
+  
+  g_signal_emit (status_icon,
+                status_icon_signals [SIZE_CHANGED_SIGNAL], 0,
+                size,
+                &handled);
+
+  return handled;
+}
+
+static GdkPixbuf *
+egg_status_icon_blank_icon (EggStatusIcon *status_icon)
+{
+  if (status_icon->priv->blank_icon)
+    {
+      gint width, height;
+
+      width  = gdk_pixbuf_get_width (status_icon->priv->blank_icon);
+      height = gdk_pixbuf_get_width (status_icon->priv->blank_icon);
+
+      if (width  == status_icon->priv->size &&
+          height == status_icon->priv->size)
+       {
+         return status_icon->priv->blank_icon;
+       }
+      else
+       {
+         g_object_unref (status_icon->priv->blank_icon);
+         status_icon->priv->blank_icon = NULL;
+       }
+    }
+
+  status_icon->priv->blank_icon = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+                                                 status_icon->priv->size,
+                                                 status_icon->priv->size);
+  if (status_icon->priv->blank_icon)
+    gdk_pixbuf_fill (status_icon->priv->blank_icon, 0);
+
+  return status_icon->priv->blank_icon;
+}
+
+static void
+egg_status_icon_update_image (EggStatusIcon *status_icon)
+{
+  if (status_icon->priv->blink_off)
+    {
+      gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image),
+                                egg_status_icon_blank_icon (status_icon));
+      return;
+    }
+
+  switch (status_icon->priv->image_type)
+    {
+    case GTK_IMAGE_PIXBUF:
+      {
+       GdkPixbuf *pixbuf;
+
+       pixbuf = status_icon->priv->image_data.pixbuf;
+
+       if (pixbuf)
+         {
+           GdkPixbuf *scaled;
+           gint size;
+           gint width;
+           gint height;
+
+           size = status_icon->priv->size;
+
+           width  = gdk_pixbuf_get_width  (pixbuf);
+           height = gdk_pixbuf_get_height (pixbuf);
+
+           if (width > size || height > size)
+             {
+               scaled = gdk_pixbuf_scale_simple (pixbuf,
+                                                 MIN (size, width),
+                                                 MIN (size, height),
+                                                 GDK_INTERP_BILINEAR);
+             }
+           else
+             {
+               scaled = (GdkPixbuf*)g_object_ref (pixbuf);
+             }
+
+           gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image), scaled);
+
+           g_object_unref (scaled);
+         }
+       else
+         {
+           gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image), NULL);
+         }
+      }
+      break;
+    case GTK_IMAGE_STOCK:
+    case GTK_IMAGE_ANIMATION:
+    case GTK_IMAGE_EMPTY:
+      gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image), NULL);
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+}
+
+static void
+egg_status_icon_size_allocate (EggStatusIcon *status_icon,
+                              GtkAllocation *allocation)
+{
+  GtkOrientation orientation;
+  gint size;
+
+  orientation = egg_tray_icon_get_orientation (EGG_TRAY_ICON (status_icon->priv->tray_icon));
+
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    size = allocation->height;
+  else
+    size = allocation->width;
+
+  if (status_icon->priv->size != size)
+    {
+      status_icon->priv->size = size;
+
+      g_object_notify (G_OBJECT (status_icon), "size");
+
+      if (!emit_size_changed_signal (status_icon, size))
+       {
+         egg_status_icon_update_image (status_icon);
+       }
+    }
+}
+
+static gboolean
+egg_status_icon_button_release (EggStatusIcon  *status_icon,
+                               GdkEventButton *event)
+{
+  if (event->button == 1)
+    {
+      emit_activate_signal (status_icon);
+      return TRUE;
+    }
+  if (event->button == 3)
+    {
+      emit_popup_menu_signal (status_icon, event->button, event->time);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+egg_status_icon_reset_image_data (EggStatusIcon *status_icon)
+{
+  switch (status_icon->priv->image_type)
+  {
+    case GTK_IMAGE_PIXBUF:
+      status_icon->priv->image_type = GTK_IMAGE_EMPTY;
+
+      if (status_icon->priv->image_data.pixbuf)
+       g_object_unref (status_icon->priv->image_data.pixbuf);
+      status_icon->priv->image_data.pixbuf = NULL;
+
+      g_object_notify (G_OBJECT (status_icon), "image-type");
+      g_object_notify (G_OBJECT (status_icon), "pixbuf");
+      break;
+    case GTK_IMAGE_STOCK:
+    case GTK_IMAGE_ANIMATION:
+    case GTK_IMAGE_EMPTY:
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+  }
+}
+
+void
+egg_status_icon_set_from_pixbuf (EggStatusIcon *status_icon,
+                                GdkPixbuf     *pixbuf)
+{
+  g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+  g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
+
+  if (pixbuf)
+    g_object_ref (pixbuf);
+
+  g_object_freeze_notify (G_OBJECT (status_icon));
+
+  egg_status_icon_reset_image_data (status_icon);
+
+  status_icon->priv->image_type = GTK_IMAGE_PIXBUF;
+  status_icon->priv->image_data.pixbuf = pixbuf;
+
+  g_object_notify (G_OBJECT (status_icon), "image-type");
+  g_object_notify (G_OBJECT (status_icon), "pixbuf");
+
+  g_object_thaw_notify (G_OBJECT (status_icon));
+
+  egg_status_icon_update_image (status_icon);
+}
+
+void
+egg_status_icon_set_from_file (EggStatusIcon *status_icon,
+                              const gchar   *filename)
+{
+  g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+}
+
+void
+egg_status_icon_set_from_stock (EggStatusIcon *status_icon,
+                               const gchar   *stock_id)
+{
+  g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+}
+
+void
+egg_status_icon_set_from_animation (EggStatusIcon      *status_icon,
+                                   GdkPixbufAnimation *animation)
+{
+  g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+  g_return_if_fail (animation == NULL || GDK_IS_PIXBUF_ANIMATION (animation));
+}
+                                                                                                             
+GtkImageType
+egg_status_icon_get_image_type (EggStatusIcon *status_icon)
+{
+  g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), GTK_IMAGE_EMPTY);
+
+  return status_icon->priv->image_type;
+}
+                                                                                                             
+GdkPixbuf *
+egg_status_icon_get_pixbuf (EggStatusIcon *status_icon)
+{
+  g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), NULL);
+  g_return_val_if_fail (status_icon->priv->image_type == GTK_IMAGE_PIXBUF ||
+                       status_icon->priv->image_type == GTK_IMAGE_EMPTY, NULL);
+                                                                                                             
+  if (status_icon->priv->image_type == GTK_IMAGE_EMPTY)
+    status_icon->priv->image_data.pixbuf = NULL;
+                                                                                                             
+  return status_icon->priv->image_data.pixbuf;
+}
+
+G_CONST_RETURN gchar *
+egg_status_icon_get_stock (EggStatusIcon *status_icon)
+{
+  g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), NULL);
+
+  return NULL;
+}
+
+GdkPixbufAnimation *
+egg_status_icon_get_animation (EggStatusIcon *status_icon)
+{
+  g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), NULL);
+
+  return NULL;
+}
+                                                                                                             
+gint
+egg_status_icon_get_size (EggStatusIcon *status_icon)
+{
+  g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), -1);
+
+  return status_icon->priv->size;
+}
+                                                                                                             
+void
+egg_status_icon_set_tooltip (EggStatusIcon *status_icon,
+                            const gchar   *tooltip_text,
+                            const gchar   *tooltip_private)
+{
+  g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+
+  gtk_tooltips_set_tip (status_icon->priv->tooltips,
+                       status_icon->priv->tray_icon,
+                       tooltip_text,
+                       tooltip_private);
+}
+
+void
+egg_status_icon_set_balloon_text (EggStatusIcon *status_icon,
+                                 const gchar   *text)
+{
+  g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+}
+
+G_CONST_RETURN gchar *
+egg_status_icon_get_balloon_text (EggStatusIcon *status_icon)
+{
+  g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), NULL);
+
+  return NULL;
+}
+
+static gboolean
+egg_status_icon_blinker (EggStatusIcon *status_icon)
+{
+  status_icon->priv->blink_off = !status_icon->priv->blink_off;
+
+  egg_status_icon_update_image (status_icon);
+
+  return TRUE;
+}
+
+static void
+egg_status_icon_enable_blinking (EggStatusIcon *status_icon)
+{
+  if (!status_icon->priv->blinking_timeout)
+    {
+      egg_status_icon_blinker (status_icon);
+
+      status_icon->priv->blinking_timeout =
+       g_timeout_add (500, (GSourceFunc) egg_status_icon_blinker, status_icon);
+    }
+}
+
+static void
+egg_status_icon_disable_blinking (EggStatusIcon *status_icon)
+{
+  if (status_icon->priv->blinking_timeout)
+    {
+      g_source_remove (status_icon->priv->blinking_timeout);
+      status_icon->priv->blinking_timeout = 0;
+      status_icon->priv->blink_off = FALSE;
+
+      egg_status_icon_update_image (status_icon);
+    }
+}
+
+void
+egg_status_icon_set_is_blinking (EggStatusIcon *status_icon,
+                                gboolean       is_blinking)
+{
+  g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+
+  is_blinking = is_blinking != FALSE;
+
+  if (status_icon->priv->blinking != is_blinking)
+    {
+      status_icon->priv->blinking = is_blinking;
+
+      if (is_blinking)
+       egg_status_icon_enable_blinking (status_icon);
+      else
+       egg_status_icon_disable_blinking (status_icon);
+
+      g_object_notify (G_OBJECT (status_icon), "blinking");
+    }
+}
+
+gboolean
+egg_status_icon_get_is_blinking (EggStatusIcon *status_icon)
+{
+  g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), FALSE);
+
+  return status_icon->priv->blinking;
+}
diff --git a/bacula/src/tray-monitor/eggstatusicon.h b/bacula/src/tray-monitor/eggstatusicon.h
new file mode 100644 (file)
index 0000000..cde7ae9
--- /dev/null
@@ -0,0 +1,101 @@
+/* eggstatusicon.h:
+ *
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *      Mark McLoughlin <mark@skynet.ie>
+ */
+
+#ifndef __EGG_STATUS_ICON_H__
+#define __EGG_STATUS_ICON_H__
+
+#include "eggtrayicon.h"
+#include <gtk/gtkimage.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_STATUS_ICON         (egg_status_icon_get_type ())
+#define EGG_STATUS_ICON(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EGG_TYPE_STATUS_ICON, EggStatusIcon))
+#define EGG_STATUS_ICON_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), EGG_TYPE_STATUS_ICON, EggStatusIconClass))
+#define EGG_IS_STATUS_ICON(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EGG_TYPE_STATUS_ICON))
+#define EGG_IS_STATUS_ICON_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EGG_TYPE_STATUS_ICON))
+#define EGG_STATUS_ICON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EGG_TYPE_STATUS_ICON, EggStatusIconClass))
+       
+typedef struct _EggStatusIcon       EggStatusIcon;
+typedef struct _EggStatusIconClass   EggStatusIconClass;
+typedef struct _EggStatusIconPrivate EggStatusIconPrivate;
+
+struct _EggStatusIcon
+{
+  GObject               parent_instance;
+
+  EggStatusIconPrivate *priv;
+};
+
+struct _EggStatusIconClass
+{
+  GObjectClass parent_class;
+
+  void     (* activate)     (EggStatusIcon *status_icon);
+  void     (* popup_menu)   (EggStatusIcon *status_icon,
+                            guint          buttton,
+                            guint32        activate_time);
+  gboolean (* size_changed) (EggStatusIcon *status_icon,
+                            gint           size);
+};
+
+GType                 egg_status_icon_get_type           (void);
+
+EggStatusIcon        *egg_status_icon_new                (void);
+EggStatusIcon        *egg_status_icon_new_from_pixbuf    (GdkPixbuf          *pixbuf);
+EggStatusIcon        *egg_status_icon_new_from_file      (const gchar        *filename);
+EggStatusIcon        *egg_status_icon_new_from_stock     (const gchar        *stock_id);
+EggStatusIcon        *egg_status_icon_new_from_animation (GdkPixbufAnimation *animation);
+
+void                  egg_status_icon_set_from_pixbuf    (EggStatusIcon      *status_icon,
+                                                         GdkPixbuf          *pixbuf);
+void                  egg_status_icon_set_from_file      (EggStatusIcon      *status_icon,
+                                                         const gchar        *filename);
+void                  egg_status_icon_set_from_stock     (EggStatusIcon      *status_icon,
+                                                         const gchar        *stock_id);
+void                  egg_status_icon_set_from_animation (EggStatusIcon      *status_icon,
+                                                         GdkPixbufAnimation *animation);
+
+GtkImageType          egg_status_icon_get_image_type     (EggStatusIcon      *status_icon);
+
+GdkPixbuf            *egg_status_icon_get_pixbuf         (EggStatusIcon      *status_icon);
+G_CONST_RETURN gchar *egg_status_icon_get_stock          (EggStatusIcon      *status_icon);
+GdkPixbufAnimation   *egg_status_icon_get_animation      (EggStatusIcon      *status_icon);
+
+gint                  egg_status_icon_get_size           (EggStatusIcon      *status_icon);
+
+void                  egg_status_icon_set_tooltip        (EggStatusIcon      *status_icon,
+                                                         const gchar        *tooltip_text,
+                                                         const gchar        *tooltip_private);
+
+void                  egg_status_icon_set_balloon_text   (EggStatusIcon      *status_icon,
+                                                         const gchar        *text);
+G_CONST_RETURN gchar *egg_status_icon_get_balloon_text   (EggStatusIcon      *status_icon);
+
+void                  egg_status_icon_set_is_blinking    (EggStatusIcon      *status_icon,
+                                                         gboolean            enable_blinking);
+gboolean              egg_status_icon_get_is_blinking    (EggStatusIcon      *status_icon);
+
+G_END_DECLS
+
+#endif /* __EGG_STATUS_ICON_H__ */
diff --git a/bacula/src/tray-monitor/eggtrayicon.c b/bacula/src/tray-monitor/eggtrayicon.c
new file mode 100644 (file)
index 0000000..0539cd9
--- /dev/null
@@ -0,0 +1,479 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* eggtrayicon.c
+ * Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <libintl.h>
+
+#include "eggtrayicon.h"
+
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+
+#ifndef EGG_COMPILATION
+#ifndef _
+#define _(x) dgettext (GETTEXT_PACKAGE, x)
+#define N_(x) x
+#endif
+#else
+#define _(x) x
+#define N_(x) x
+#endif
+
+#define SYSTEM_TRAY_REQUEST_DOCK    0
+#define SYSTEM_TRAY_BEGIN_MESSAGE   1
+#define SYSTEM_TRAY_CANCEL_MESSAGE  2
+
+#define SYSTEM_TRAY_ORIENTATION_HORZ 0
+#define SYSTEM_TRAY_ORIENTATION_VERT 1
+
+enum {
+  PROP_0,
+  PROP_ORIENTATION
+};
+         
+static GtkPlugClass *parent_class = NULL;
+
+static void egg_tray_icon_init (EggTrayIcon *icon);
+static void egg_tray_icon_class_init (EggTrayIconClass *klass);
+
+static void egg_tray_icon_get_property (GObject    *object,
+                                       guint       prop_id,
+                                       GValue     *value,
+                                       GParamSpec *pspec);
+
+static void egg_tray_icon_realize   (GtkWidget *widget);
+static void egg_tray_icon_unrealize (GtkWidget *widget);
+
+static void egg_tray_icon_update_manager_window (EggTrayIcon *icon);
+
+GType
+egg_tray_icon_get_type (void)
+{
+  static GType our_type = 0;
+
+  if (our_type == 0)
+    {
+      static const GTypeInfo our_info =
+      {
+       sizeof (EggTrayIconClass),
+       (GBaseInitFunc) NULL,
+       (GBaseFinalizeFunc) NULL,
+       (GClassInitFunc) egg_tray_icon_class_init,
+       NULL, /* class_finalize */
+       NULL, /* class_data */
+       sizeof (EggTrayIcon),
+       0,    /* n_preallocs */
+       (GInstanceInitFunc) egg_tray_icon_init
+      };
+
+      our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, (GTypeFlags)0);
+    }
+
+  return our_type;
+}
+
+static void
+egg_tray_icon_init (EggTrayIcon *icon)
+{
+  icon->stamp = 1;
+  icon->orientation = GTK_ORIENTATION_HORIZONTAL;
+  
+  gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK);
+}
+
+static void
+egg_tray_icon_class_init (EggTrayIconClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *)klass;
+  GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
+
+  parent_class = (GtkPlugClass*)g_type_class_peek_parent (klass);
+
+  gobject_class->get_property = egg_tray_icon_get_property;
+
+  widget_class->realize   = egg_tray_icon_realize;
+  widget_class->unrealize = egg_tray_icon_unrealize;
+
+  g_object_class_install_property (gobject_class,
+                                  PROP_ORIENTATION,
+                                  g_param_spec_enum ("orientation",
+                                                     "Orientation",
+                                                     "The orientation of the tray.",
+                                                     GTK_TYPE_ORIENTATION,
+                                                     GTK_ORIENTATION_HORIZONTAL,
+                                                     G_PARAM_READABLE));
+}
+
+static void
+egg_tray_icon_get_property (GObject    *object,
+                           guint       prop_id,
+                           GValue     *value,
+                           GParamSpec *pspec)
+{
+  EggTrayIcon *icon = EGG_TRAY_ICON (object);
+
+  switch (prop_id)
+    {
+    case PROP_ORIENTATION:
+      g_value_set_enum (value, icon->orientation);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+egg_tray_icon_get_orientation_property (EggTrayIcon *icon)
+{
+  Display *xdisplay;
+  Atom type;
+  int format;
+  union {
+       gulong *prop;
+       guchar *prop_ch;
+  } prop = { NULL };
+  gulong nitems;
+  gulong bytes_after;
+  int error, result;
+
+  g_assert (icon->manager_window != None);
+  
+  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+  gdk_error_trap_push ();
+  type = None;
+  result = XGetWindowProperty (xdisplay,
+                              icon->manager_window,
+                              icon->orientation_atom,
+                              0, G_MAXLONG, FALSE,
+                              XA_CARDINAL,
+                              &type, &format, &nitems,
+                              &bytes_after, &(prop.prop_ch));
+  error = gdk_error_trap_pop ();
+
+  if (error || result != Success)
+    return;
+
+  if (type == XA_CARDINAL)
+    {
+      GtkOrientation orientation;
+
+      orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ?
+                                       GTK_ORIENTATION_HORIZONTAL :
+                                       GTK_ORIENTATION_VERTICAL;
+
+      if (icon->orientation != orientation)
+       {
+         icon->orientation = orientation;
+
+         g_object_notify (G_OBJECT (icon), "orientation");
+       }
+    }
+
+  if (prop.prop)
+    XFree (prop.prop);
+}
+
+static GdkFilterReturn
+egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data)
+{
+  EggTrayIcon *icon = (EggTrayIcon*)user_data;
+  XEvent *xev = (XEvent *)xevent;
+
+  if (xev->xany.type == ClientMessage &&
+      xev->xclient.message_type == icon->manager_atom &&
+      xev->xclient.data.l[1] == icon->selection_atom)
+    {
+      egg_tray_icon_update_manager_window (icon);
+    }
+  else if (xev->xany.window == icon->manager_window)
+    {
+      if (xev->xany.type == PropertyNotify &&
+         xev->xproperty.atom == icon->orientation_atom)
+       {
+         egg_tray_icon_get_orientation_property (icon);
+       }
+      if (xev->xany.type == DestroyNotify)
+       {
+         egg_tray_icon_update_manager_window (icon);
+       }
+    }
+  
+  return GDK_FILTER_CONTINUE;
+}
+
+static void
+egg_tray_icon_unrealize (GtkWidget *widget)
+{
+  EggTrayIcon *icon = EGG_TRAY_ICON (widget);
+  GdkWindow *root_window;
+
+  if (icon->manager_window != None)
+    {
+      GdkWindow *gdkwin;
+
+      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget),
+                                              icon->manager_window);
+
+      gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+    }
+
+  root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
+
+  gdk_window_remove_filter (root_window, egg_tray_icon_manager_filter, icon);
+
+  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
+egg_tray_icon_send_manager_message (EggTrayIcon *icon,
+                                   long         message,
+                                   Window       window,
+                                   long         data1,
+                                   long         data2,
+                                   long         data3)
+{
+  XClientMessageEvent ev;
+  Display *display;
+  
+  ev.type = ClientMessage;
+  ev.window = window;
+  ev.message_type = icon->system_tray_opcode_atom;
+  ev.format = 32;
+  ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window);
+  ev.data.l[1] = message;
+  ev.data.l[2] = data1;
+  ev.data.l[3] = data2;
+  ev.data.l[4] = data3;
+
+  display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+  
+  gdk_error_trap_push ();
+  XSendEvent (display,
+             icon->manager_window, False, NoEventMask, (XEvent *)&ev);
+  XSync (display, False);
+  gdk_error_trap_pop ();
+}
+
+static void
+egg_tray_icon_send_dock_request (EggTrayIcon *icon)
+{
+  egg_tray_icon_send_manager_message (icon,
+                                     SYSTEM_TRAY_REQUEST_DOCK,
+                                     icon->manager_window,
+                                     gtk_plug_get_id (GTK_PLUG (icon)),
+                                     0, 0);
+}
+
+static void
+egg_tray_icon_update_manager_window (EggTrayIcon *icon)
+{
+  Display *xdisplay;
+  
+  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+  
+  if (icon->manager_window != None)
+    {
+      GdkWindow *gdkwin;
+
+      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
+                                             icon->manager_window);
+      
+      gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+    }
+  
+  XGrabServer (xdisplay);
+  
+  icon->manager_window = XGetSelectionOwner (xdisplay,
+                                            icon->selection_atom);
+
+  if (icon->manager_window != None)
+    XSelectInput (xdisplay,
+                 icon->manager_window, StructureNotifyMask|PropertyChangeMask);
+
+  XUngrabServer (xdisplay);
+  XFlush (xdisplay);
+  
+  if (icon->manager_window != None)
+    {
+      GdkWindow *gdkwin;
+
+      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
+                                             icon->manager_window);
+      
+      gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+
+      /* Send a request that we'd like to dock */
+      egg_tray_icon_send_dock_request (icon);
+
+      egg_tray_icon_get_orientation_property (icon);
+    }
+}
+
+static void
+egg_tray_icon_realize (GtkWidget *widget)
+{
+  EggTrayIcon *icon = EGG_TRAY_ICON (widget);
+  GdkScreen *screen;
+  GdkDisplay *display;
+  Display *xdisplay;
+  char buffer[256];
+  GdkWindow *root_window;
+
+  if (GTK_WIDGET_CLASS (parent_class)->realize)
+    GTK_WIDGET_CLASS (parent_class)->realize (widget);
+
+  screen = gtk_widget_get_screen (widget);
+  display = gdk_screen_get_display (screen);
+  xdisplay = gdk_x11_display_get_xdisplay (display);
+
+  /* Now see if there's a manager window around */
+  g_snprintf (buffer, sizeof (buffer),
+             "_NET_SYSTEM_TRAY_S%d",
+             gdk_screen_get_number (screen));
+
+  icon->selection_atom = XInternAtom (xdisplay, buffer, False);
+  
+  icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False);
+  
+  icon->system_tray_opcode_atom = XInternAtom (xdisplay,
+                                                  "_NET_SYSTEM_TRAY_OPCODE",
+                                                  False);
+
+  icon->orientation_atom = XInternAtom (xdisplay,
+                                       "_NET_SYSTEM_TRAY_ORIENTATION",
+                                       False);
+
+  egg_tray_icon_update_manager_window (icon);
+
+  root_window = gdk_screen_get_root_window (screen);
+  
+  /* Add a root window filter so that we get changes on MANAGER */
+  gdk_window_add_filter (root_window,
+                        egg_tray_icon_manager_filter, icon);
+}
+
+EggTrayIcon *
+egg_tray_icon_new_for_xscreen (Screen *xscreen, const char *name)
+{
+  GdkDisplay *display;
+  GdkScreen *screen;
+
+  display = gdk_x11_lookup_xdisplay (DisplayOfScreen (xscreen));
+  screen = gdk_display_get_screen (display, XScreenNumberOfScreen (xscreen));
+
+  return egg_tray_icon_new_for_screen (screen, name);
+}
+
+EggTrayIcon *
+egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  return (EggTrayIcon*)g_object_new (EGG_TYPE_TRAY_ICON, "screen", screen, "title", name, NULL);
+}
+
+EggTrayIcon*
+egg_tray_icon_new (const gchar *name)
+{
+  return (EggTrayIcon*)g_object_new (EGG_TYPE_TRAY_ICON, "title", name, NULL);
+}
+
+guint
+egg_tray_icon_send_message (EggTrayIcon *icon,
+                           gint         timeout,
+                           const gchar *message,
+                           gint         len)
+{
+  guint stamp;
+  
+  g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0);
+  g_return_val_if_fail (timeout >= 0, 0);
+  g_return_val_if_fail (message != NULL, 0);
+                    
+  if (icon->manager_window == None)
+    return 0;
+
+  if (len < 0)
+    len = strlen (message);
+
+  stamp = icon->stamp++;
+  
+  /* Get ready to send the message */
+  egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE,
+                                     (Window)gtk_plug_get_id (GTK_PLUG (icon)),
+                                     timeout, len, stamp);
+
+  /* Now to send the actual message */
+  gdk_error_trap_push ();
+  while (len > 0)
+    {
+      XClientMessageEvent ev;
+      Display *xdisplay;
+
+      xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+      
+      ev.type = ClientMessage;
+      ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon));
+      ev.format = 8;
+      ev.message_type = XInternAtom (xdisplay,
+                                    "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
+      if (len > 20)
+       {
+         memcpy (&ev.data, message, 20);
+         len -= 20;
+         message += 20;
+       }
+      else
+       {
+         memcpy (&ev.data, message, len);
+         len = 0;
+       }
+
+      XSendEvent (xdisplay,
+                 icon->manager_window, False, StructureNotifyMask, (XEvent *)&ev);
+      XSync (xdisplay, False);
+    }
+  gdk_error_trap_pop ();
+
+  return stamp;
+}
+
+void
+egg_tray_icon_cancel_message (EggTrayIcon *icon,
+                             guint        id)
+{
+  g_return_if_fail (EGG_IS_TRAY_ICON (icon));
+  g_return_if_fail (id > 0);
+  
+  egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE,
+                                     (Window)gtk_plug_get_id (GTK_PLUG (icon)),
+                                     id, 0, 0);
+}
+
+GtkOrientation
+egg_tray_icon_get_orientation (EggTrayIcon *icon)
+{
+  g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL);
+
+  return icon->orientation;
+}
diff --git a/bacula/src/tray-monitor/eggtrayicon.h b/bacula/src/tray-monitor/eggtrayicon.h
new file mode 100644 (file)
index 0000000..007f4c1
--- /dev/null
@@ -0,0 +1,77 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* eggtrayicon.h
+ * Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_TRAY_ICON_H__
+#define __EGG_TRAY_ICON_H__
+
+#include <gtk/gtkplug.h>
+#include <gdk/gdkx.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_TRAY_ICON             (egg_tray_icon_get_type ())
+#define EGG_TRAY_ICON(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TRAY_ICON, EggTrayIcon))
+#define EGG_TRAY_ICON_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_TRAY_ICON, EggTrayIconClass))
+#define EGG_IS_TRAY_ICON(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TRAY_ICON))
+#define EGG_IS_TRAY_ICON_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_TRAY_ICON))
+#define EGG_TRAY_ICON_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_TRAY_ICON, EggTrayIconClass))
+       
+typedef struct _EggTrayIcon      EggTrayIcon;
+typedef struct _EggTrayIconClass  EggTrayIconClass;
+
+struct _EggTrayIcon
+{
+  GtkPlug parent_instance;
+
+  guint stamp;
+  
+  Atom selection_atom;
+  Atom manager_atom;
+  Atom system_tray_opcode_atom;
+  Atom orientation_atom;
+  Window manager_window;
+
+  GtkOrientation orientation;
+};
+
+struct _EggTrayIconClass
+{
+  GtkPlugClass parent_class;
+};
+
+GType        egg_tray_icon_get_type       (void);
+
+EggTrayIcon *egg_tray_icon_new_for_screen (GdkScreen   *screen,
+                                          const gchar *name);
+
+EggTrayIcon *egg_tray_icon_new            (const gchar *name);
+
+guint        egg_tray_icon_send_message   (EggTrayIcon *icon,
+                                          gint         timeout,
+                                          const char  *message,
+                                          gint         len);
+void         egg_tray_icon_cancel_message (EggTrayIcon *icon,
+                                          guint        id);
+
+GtkOrientation egg_tray_icon_get_orientation (EggTrayIcon *icon);
+                                           
+G_END_DECLS
+
+#endif /* __EGG_TRAY_ICON_H__ */
diff --git a/bacula/src/tray-monitor/tray-monitor.c b/bacula/src/tray-monitor/tray-monitor.c
new file mode 100644 (file)
index 0000000..e06e8eb
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ *
+ *   Bacula Gnome Tray Monitor
+ *
+ *     Nicolas Boichat, August MMIV
+ *
+ *     Version $Id$
+ */
+
+/*
+   Copyright (C) 2000-2004 Kern Sibbald and John Walker
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+   MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "tray-monitor.h"
+
+#include "eggstatusicon.h"
+#include <gtk/gtk.h>
+
+#include "idle.xpm"
+#include "error.xpm"
+#include "running.xpm"
+#include "saving.xpm"
+#include "warn.xpm"
+
+/* Imported functions */
+int authenticate_file_daemon(JCR *jcr, MONITOR *monitor, CLIENT* client);
+
+/* Forward referenced functions */
+static void terminate_console(int sig);
+void writecmd(const char* command);
+
+/* Static variables */
+static char *configfile = NULL;
+static BSOCK *FD_sock = NULL;
+static MONITOR *monitor;
+static POOLMEM *args;
+
+/* UI variables and functions */
+gboolean fd_read(gpointer data);
+
+static EggStatusIcon* mTrayIcon;
+
+#define CONFIG_FILE "./tray-monitor.conf"   /* default configuration file */
+
+static void usage()
+{
+   fprintf(stderr, _(
+"Copyright (C) 2000-2004 Kern Sibbald and John Walker\n"
+"\nVersion: " VERSION " (" BDATE ") %s %s %s\n\n"
+"Usage: tray-monitor [-s] [-c config_file] [-d debug_level]\n"
+"       -c <file>   set configuration file to file\n"
+"       -dnn        set debug level to nn\n"
+"       -s          no signals\n"
+"       -t          test - read configuration and exit\n"
+"       -?          print this message.\n"  
+"\n"), HOST_OS, DISTNAME, DISTVER);
+}
+
+/*********************************************************************
+ *
+ *        Main Bacula Tray Monitor -- User Interface Program
+ *
+ */
+int main(int argc, char *argv[])
+{
+   int ch, nfiled;
+   bool test_config = false;
+   JCR jcr;
+   CLIENT* filed;
+
+   init_stack_dump();
+   my_name_is(argc, argv, "tray-monitor");
+   textdomain("bacula");
+   init_msg(NULL, NULL);
+   working_directory = "/tmp";
+   args = get_pool_memory(PM_FNAME);
+
+   while ((ch = getopt(argc, argv, "bc:d:r:st?")) != -1) {
+      switch (ch) {
+      case 'c':                    /* configuration file */
+        if (configfile != NULL) {
+           free(configfile);
+        }
+        configfile = bstrdup(optarg);
+        break;
+
+      case 'd':
+        debug_level = atoi(optarg);
+        if (debug_level <= 0) {
+           debug_level = 1;
+        }
+        break;
+
+      case 't':
+        test_config = true;
+        break;
+
+      case '?':
+      default:
+        usage();
+        exit(1);
+      }  
+   }
+   argc -= optind;
+   argv += optind;
+
+   if (argc) {
+      usage();
+      exit(1);
+   }
+
+   if (configfile == NULL) {
+      configfile = bstrdup(CONFIG_FILE);
+   }
+
+   parse_config(configfile);
+
+   LockRes();
+   nfiled = 0;
+   foreach_res(filed, R_CLIENT) {
+      nfiled++;
+   }
+   UnlockRes();
+   if (nfiled != 1) {
+      Emsg1(M_ERROR_TERM, 0, _("No Client resource defined in %s (or more than one)\n\
+Without that I don't how to get status from the Client :-(\n"), configfile);
+   }
+
+   if (test_config) {
+      terminate_console(0);
+      exit(0);
+   }
+   
+   LockRes();
+   filed = (CLIENT*)GetNextRes(R_CLIENT, NULL);
+   UnlockRes();
+
+   memset(&jcr, 0, sizeof(jcr));
+
+   (void)WSA_Init();                       /* Initialize Windows sockets */
+      
+   printf(_("Connecting to Client %s:%d\n"), filed->address, filed->FDport);
+   FD_sock = bnet_connect(NULL, 5, 15, "File daemon", filed->address, 
+                         NULL, filed->FDport, 0);
+   if (FD_sock == NULL) {
+      terminate_console(0);
+      return 1;
+   }
+   jcr.file_bsock = FD_sock;
+   
+   LockRes();
+   monitor = (MONITOR*)GetNextRes(R_MONITOR, (RES *)NULL);
+   UnlockRes();
+   
+   if (!authenticate_file_daemon(&jcr, monitor, filed)) {
+      fprintf(stderr, "ERR=%s", FD_sock->msg);
+      terminate_console(0);
+      return 1;
+   }
+
+   printf("Opened connection with File daemon\n");
+
+   writecmd("status");
+
+   gtk_init (&argc, &argv);
+   
+   GdkPixbuf* pixbuf = gdk_pixbuf_new_from_xpm_data(xpm_idle);
+   // This should be ideally replaced by a completely libpr0n-based icon rendering.
+   mTrayIcon = egg_status_icon_new_from_pixbuf(pixbuf);
+/*   g_signal_connect(G_OBJECT(mTrayIcon), "activate", G_CALLBACK(TrayIconActivate), this);
+   g_signal_connect(G_OBJECT(mTrayIcon), "popup-menu", G_CALLBACK(TrayIconPopupMenu), this);*/
+   g_object_unref(G_OBJECT(pixbuf));
+
+   gtk_idle_add( fd_read, NULL );
+      
+   gtk_main();
+   
+   if (FD_sock) {
+      bnet_sig(FD_sock, BNET_TERMINATE); /* send EOF */
+      bnet_close(FD_sock);
+   }
+
+   terminate_console(0);
+   return 0;
+}
+
+gboolean fd_read(gpointer data) {
+   int stat;
+   
+   while(1) {
+      if ((stat = bnet_recv(FD_sock)) >= 0) {
+         printf(FD_sock->msg);
+      }
+      else if (stat == BNET_SIGNAL) {
+         if (FD_sock->msglen == BNET_PROMPT) {
+            printf("<PROMPT>");
+         }
+         else if (FD_sock->msglen == BNET_EOD) {
+            printf("<END>");
+            writecmd("status");
+            sleep(1);
+            return 1;
+         }
+         else if (FD_sock->msglen == BNET_HEARTBEAT) {
+            bnet_sig(FD_sock, BNET_HB_RESPONSE);
+            printf("<< Heartbeat signal received, answered. >>");
+         }
+         else {
+            printf("<< Unexpected signal received : %s >>", bnet_sig_to_ascii(FD_sock));
+         }
+      }
+      else { /* BNET_HARDEOF || BNET_ERROR */
+         printf("<ERROR>");
+         break;
+      }
+           
+      if (is_bnet_stop(FD_sock)) {
+         printf("<STOP>");
+         break;            /* error or term */
+      }
+   }
+   return 0;
+}
+
+/* Cleanup and then exit */
+static void terminate_console(int sig)
+{
+
+   static bool already_here = false;
+
+   if (already_here) {               /* avoid recursive temination problems */
+      exit(1);
+   }
+   already_here = true;
+   free_pool_memory(args);
+   (void)WSACleanup();              /* Cleanup Windows sockets */
+   if (sig != 0) {
+      exit(1);
+   }
+   return;
+}
+
+void writecmd(const char* command) {
+   FD_sock->msglen = strlen(command);
+   pm_strcpy(&FD_sock->msg, command);
+   bnet_send(FD_sock);
+}
diff --git a/bacula/src/tray-monitor/tray-monitor.conf.in b/bacula/src/tray-monitor/tray-monitor.conf.in
new file mode 100644 (file)
index 0000000..3038b72
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Bacula Tray Monitor Configuration File
+#
+
+Monitor {
+  Name = @hostname@-dir
+}
+   
+Client {
+  Name = @hostname@-fd
+  Address = @hostname@
+  FDPort = @fd_port@
+  Password = "@fd_password@"          # password for FileDaemon
+}
\ No newline at end of file
diff --git a/bacula/src/tray-monitor/tray-monitor.h b/bacula/src/tray-monitor/tray-monitor.h
new file mode 100644 (file)
index 0000000..e62d7b1
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Includes specific to the Director
+ *
+ *     Kern Sibbald, December MM
+ *
+ *    Version $Id$
+ */
+/*
+   Copyright (C) 2000-2004 Kern Sibbald and John Walker
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+ */
+
+#include "tray_conf.h"
+
+#define TRAY_MONITOR 1
+
+#include "jcr.h"
diff --git a/bacula/src/tray-monitor/tray_conf.c b/bacula/src/tray-monitor/tray_conf.c
new file mode 100644 (file)
index 0000000..4e3955c
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+*   Main configuration file parser for Bacula Tray Monitor.
+*
+*   Adapted from dird_conf.c
+*
+*   Note, the configuration file parser consists of three parts
+*
+*   1. The generic lexical scanner in lib/lex.c and lib/lex.h
+*
+*   2. The generic config  scanner in lib/parse_config.c and 
+*      lib/parse_config.h.
+*      These files contain the parser code, some utility
+*      routines, and the common store routines (name, int,
+*      string).
+*
+*   3. The daemon specific file, which contains the Resource
+*      definitions as well as any specific store routines
+*      for the resource records.
+*
+*     Nicolas Boichat, August MMIV
+*
+*     Version $Id$
+*/
+/*
+   Copyright (C) 2000-2004 Kern Sibbald and John Walker
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+*/
+
+#include "bacula.h"
+#include "tray_conf.h"
+
+/* Define the first and last resource ID record
+* types. Note, these should be unique for each
+* daemon though not a requirement.
+*/
+int r_first = R_FIRST;
+int r_last  = R_LAST;
+static RES *sres_head[R_LAST - R_FIRST + 1];
+RES **res_head = sres_head;
+
+/* We build the current resource here as we are
+* scanning the resource configuration definition,
+* then move it to allocated memory when the resource
+* scan is complete.
+*/
+URES res_all;
+int  res_all_size = sizeof(res_all);
+
+
+/* Definition of records permitted within each
+* resource with the routine to process the record 
+* information.  NOTE! quoted names must be in lower case.
+*/ 
+/* 
+*    Monitor Resource
+*
+*   name          handler     value                 code flags    default_value
+*/
+static RES_ITEM dir_items[] = {
+   {"name",        store_name,     ITEM(res_monitor.hdr.name), 0, ITEM_REQUIRED, 0},
+   {"description", store_str,      ITEM(res_monitor.hdr.desc), 0, 0, 0},
+   {"requiressl",  store_yesno,    ITEM(res_monitor.require_ssl), 1, ITEM_DEFAULT, 0},
+   {"fdconnecttimeout", store_time,ITEM(res_monitor.FDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30},
+   {"sdconnecttimeout", store_time,ITEM(res_monitor.SDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30},
+   {NULL, NULL, NULL, 0, 0, 0}
+};
+
+/* 
+*    Client or File daemon resource
+*
+*   name          handler     value                 code flags    default_value
+*/
+
+static RES_ITEM cli_items[] = {
+   {"name",     store_name,       ITEM(res_client.hdr.name), 0, ITEM_REQUIRED, 0},
+   {"description", store_str,     ITEM(res_client.hdr.desc), 0, 0, 0},
+   {"address",  store_str,        ITEM(res_client.address),  0, ITEM_REQUIRED, 0},
+   {"fdaddress",  store_str,      ITEM(res_client.address),  0, 0, 0},
+   {"fdport",   store_pint,       ITEM(res_client.FDport),   0, ITEM_DEFAULT, 9102},
+   {"password", store_password,   ITEM(res_client.password), 0, ITEM_REQUIRED, 0},
+   {"fdpassword", store_password,   ITEM(res_client.password), 0, 0, 0},
+   {"enablessl", store_yesno,     ITEM(res_client.enable_ssl), 1, ITEM_DEFAULT, 0},
+   {NULL, NULL, NULL, 0, 0, 0} 
+};
+
+/* Storage daemon resource
+*
+*   name          handler     value                 code flags    default_value
+*/
+static RES_ITEM store_items[] = {
+   {"name",        store_name,     ITEM(res_store.hdr.name),   0, ITEM_REQUIRED, 0},
+   {"description", store_str,      ITEM(res_store.hdr.desc),   0, 0, 0},
+   {"sdport",      store_pint,     ITEM(res_store.SDport),     0, ITEM_DEFAULT, 9103},
+   {"address",     store_str,      ITEM(res_store.address),    0, ITEM_REQUIRED, 0},
+   {"sdaddress",   store_str,      ITEM(res_store.address),    0, 0, 0},
+   {"password",    store_password, ITEM(res_store.password),   0, ITEM_REQUIRED, 0},
+   {"sdpassword",  store_password, ITEM(res_store.password),   0, 0, 0},
+   {"enablessl",   store_yesno,    ITEM(res_store.enable_ssl),  1, ITEM_DEFAULT, 0},
+   {NULL, NULL, NULL, 0, 0, 0} 
+};
+
+/* 
+* This is the master resource definition.  
+* It must have one item for each of the resources.
+*
+*  NOTE!!! keep it in the same order as the R_codes
+*    or eliminate all resources[rindex].name
+*
+*  name             items        rcode        res_head
+*/
+RES_TABLE resources[] = {
+   {"monitor",      dir_items,    R_MONITOR},
+   {"client",        cli_items,   R_CLIENT},
+   {"storage",       store_items, R_STORAGE},
+   {NULL,           NULL,        0}
+};
+
+/* Dump contents of resource */
+void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock)
+{
+   URES *res = (URES *)reshdr;
+   bool recurse = true;
+   char ed1[100], ed2[100];
+
+   if (res == NULL) {
+      sendit(sock, "No %s resource defined\n", res_to_str(type));
+      return;
+   }
+   if (type < 0) {                   /* no recursion */
+      type = - type;
+      recurse = false;
+   }
+   switch (type) {
+   case R_MONITOR:
+      sendit(sock, "Director: name=%s FDtimeout=%s SDtimeout=%s\n", 
+   reshdr->name, 
+   edit_uint64(res->res_monitor.FDConnectTimeout, ed1),
+   edit_uint64(res->res_monitor.SDConnectTimeout, ed2));
+      break;
+   case R_CLIENT:
+      sendit(sock, "Client: name=%s address=%s FDport=%d\n",
+   res->res_client.hdr.name, res->res_client.address, res->res_client.FDport);
+      break;
+   case R_STORAGE:
+      sendit(sock, "Storage: name=%s address=%s SDport=%d\n",
+   res->res_store.hdr.name, res->res_store.address, res->res_store.SDport);
+      break;
+   default:
+      sendit(sock, "Unknown resource type %d in dump_resource.\n", type);
+      break;
+   }
+   if (recurse && res->res_monitor.hdr.next) {
+      dump_resource(type, res->res_monitor.hdr.next, sendit, sock);
+   }
+}
+
+
+/* 
+* Free memory of resource -- called when daemon terminates.
+* NB, we don't need to worry about freeing any references
+* to other resources as they will be freed when that 
+* resource chain is traversed.  Mainly we worry about freeing
+* allocated strings (names).
+*/
+void free_resource(RES *sres, int type)
+{
+   int num;
+   RES *nres;                        /* next resource if linked */
+   URES *res = (URES *)sres;
+
+   if (res == NULL)
+      return;
+
+   /* common stuff -- free the resource name and description */
+   nres = (RES *)res->res_monitor.hdr.next;
+   if (res->res_monitor.hdr.name) {
+      free(res->res_monitor.hdr.name);
+   }
+   if (res->res_monitor.hdr.desc) {
+      free(res->res_monitor.hdr.desc);
+   }
+
+   switch (type) {
+   case R_MONITOR:
+      break;
+   case R_CLIENT:
+      if (res->res_client.address) {
+   free(res->res_client.address);
+      }
+      if (res->res_client.password) {
+   free(res->res_client.password);
+      }
+      break;
+   case R_STORAGE:
+      if (res->res_store.address) {
+   free(res->res_store.address);
+      }
+      if (res->res_store.password) {
+   free(res->res_store.password);
+      }
+      break;
+   default:
+      printf("Unknown resource type %d in free_resource.\n", type);
+   }
+   /* Common stuff again -- free the resource, recurse to next one */
+   if (res) {
+      free(res);
+   }
+   if (nres) {
+      free_resource(nres, type);
+   }
+}
+
+/*
+* Save the new resource by chaining it into the head list for
+* the resource. If this is pass 2, we update any resource
+* pointers because they may not have been defined until 
+* later in pass 1.
+*/
+void save_resource(int type, RES_ITEM *items, int pass)
+{
+   URES *res;
+   int rindex = type - r_first;
+   int i, size;
+   int error = 0;
+   
+   /* 
+   * Ensure that all required items are present
+   */
+   for (i=0; items[i].name; i++) {
+      if (items[i].flags & ITEM_REQUIRED) {
+         if (!bit_is_set(i, res_all.res_monitor.hdr.item_present)) {
+               Emsg2(M_ERROR_TERM, 0, "%s item is required in %s resource, but not found.\n",
+                  items[i].name, resources[rindex]);
+         }
+      }
+      /* If this triggers, take a look at lib/parse_conf.h */
+      if (i >= MAX_RES_ITEMS) {
+         Emsg1(M_ERROR_TERM, 0, "Too many items in %s resource\n", resources[rindex]);
+      }
+   }
+
+   /*
+   * During pass 2 in each "store" routine, we looked up pointers 
+   * to all the resources referrenced in the current resource, now we
+   * must copy their addresses from the static record to the allocated
+   * record.
+   */
+   if (pass == 2) {
+      switch (type) {
+      /* Resources not containing a resource */
+      case R_MONITOR:
+      case R_CLIENT:
+      case R_STORAGE:
+         break;
+      default:
+         Emsg1(M_ERROR, 0, "Unknown resource type %d in save_resource.\n", type);
+         error = 1;
+         break;
+      }
+      /* Note, the resource name was already saved during pass 1,
+      * so here, we can just release it.
+      */
+      if (res_all.res_monitor.hdr.name) {
+         free(res_all.res_monitor.hdr.name);
+         res_all.res_monitor.hdr.name = NULL;
+      }
+      if (res_all.res_monitor.hdr.desc) {
+         free(res_all.res_monitor.hdr.desc);
+         res_all.res_monitor.hdr.desc = NULL;
+      }
+      return;
+   }
+
+   /*
+   * The following code is only executed during pass 1   
+   */
+   switch (type) {
+   case R_MONITOR:
+      size = sizeof(MONITOR);
+      break;
+   case R_CLIENT:
+      size =sizeof(CLIENT);
+      break;
+   case R_STORAGE:
+      size = sizeof(STORE); 
+      break;
+   default:
+      printf("Unknown resource type %d in save_resrouce.\n", type);
+      error = 1;
+      size = 1;
+      break;
+   }
+   /* Common */
+   if (!error) {
+      res = (URES *)malloc(size);
+      memcpy(res, &res_all, size);
+      if (!res_head[rindex]) {
+   res_head[rindex] = (RES *)res; /* store first entry */
+         Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type),
+         res->res_monitor.hdr.name, rindex);
+      } else {
+   RES *next;
+   /* Add new res to end of chain */
+   for (next=res_head[rindex]; next->next; next=next->next) {
+      if (strcmp(next->name, res->res_monitor.hdr.name) == 0) {
+         Emsg2(M_ERROR_TERM, 0,
+                  _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
+         resources[rindex].name, res->res_monitor.hdr.name);
+      }
+   }
+   next->next = (RES *)res;
+         Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
+         res->res_monitor.hdr.name, rindex, pass);
+      }
+   }
+}
diff --git a/bacula/src/tray-monitor/tray_conf.h b/bacula/src/tray-monitor/tray_conf.h
new file mode 100644 (file)
index 0000000..bc16b31
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Tray Monitor specific configuration and defines
+ *
+ *   Adapted from dird_conf.c
+ *
+ *     Nicolas Boichat, August MMIV
+ *
+ *    Version $Id$
+ */
+/*
+   Copyright (C) 2000-2004 Kern Sibbald and John Walker
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+ */
+
+/* NOTE:  #includes at the end of this file */
+
+/*
+ * Resource codes -- they must be sequential for indexing   
+ */
+enum {
+   R_MONITOR = 1001,
+   R_CLIENT,
+   R_STORAGE,
+   R_FIRST = R_MONITOR,
+   R_LAST  = R_STORAGE                /* keep this updated */
+};
+
+
+/*
+ * Some resource attributes
+ */
+enum {
+   R_NAME = 1020,
+   R_ADDRESS,
+   R_PASSWORD,
+   R_TYPE,
+   R_BACKUP
+};
+
+/* 
+ *   Tray Monitor Resource  
+ *
+ */
+struct MONITOR {
+   RES   hdr;
+   int require_ssl;                   /* Require SSL for all connections */
+   MSGS *messages;                    /* Daemon message handler */
+   utime_t FDConnectTimeout;          /* timeout for connect in seconds */
+   utime_t SDConnectTimeout;          /* timeout in seconds */
+};
+
+
+/*
+ *   Client Resource
+ *
+ */
+struct CLIENT {
+   RES   hdr;
+
+   int   FDport;                      /* Where File daemon listens */
+   char *address;
+   char *password;
+   int enable_ssl;                    /* Use SSL */
+};
+
+/*
+ *   Store Resource
+ * 
+ */
+struct STORE {
+   RES   hdr;
+
+   int   SDport;                      /* port where Directors connect */
+   char *address;
+   char *password;
+   int enable_ssl;                    /* Use SSL */
+};
+
+
+
+/* Define the Union of all the above
+ * resource structure definitions.
+ */
+union URES {
+   MONITOR    res_monitor;
+   CLIENT     res_client;
+   STORE      res_store;
+   RES        hdr;
+};
+