From 6b2f7c2b073522efe8c8c33077718790f979a04f Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Sat, 14 Aug 2004 11:45:47 +0000 Subject: [PATCH] add src/tray-monitor directory git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1528 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/tray-monitor/Makefile.in | 103 +++ bacula/src/tray-monitor/authenticate.c | 90 +++ bacula/src/tray-monitor/eggmarshalers.c | 561 +++++++++++++ bacula/src/tray-monitor/eggmarshalers.h | 127 +++ bacula/src/tray-monitor/eggmarshalers.list | 17 + bacula/src/tray-monitor/eggstatusicon.c | 779 +++++++++++++++++++ bacula/src/tray-monitor/eggstatusicon.h | 101 +++ bacula/src/tray-monitor/eggtrayicon.c | 479 ++++++++++++ bacula/src/tray-monitor/eggtrayicon.h | 77 ++ bacula/src/tray-monitor/tray-monitor.c | 264 +++++++ bacula/src/tray-monitor/tray-monitor.conf.in | 14 + bacula/src/tray-monitor/tray-monitor.h | 32 + bacula/src/tray-monitor/tray_conf.c | 332 ++++++++ bacula/src/tray-monitor/tray_conf.h | 105 +++ 14 files changed, 3081 insertions(+) create mode 100644 bacula/src/tray-monitor/Makefile.in create mode 100644 bacula/src/tray-monitor/authenticate.c create mode 100644 bacula/src/tray-monitor/eggmarshalers.c create mode 100644 bacula/src/tray-monitor/eggmarshalers.h create mode 100644 bacula/src/tray-monitor/eggmarshalers.list create mode 100644 bacula/src/tray-monitor/eggstatusicon.c create mode 100644 bacula/src/tray-monitor/eggstatusicon.h create mode 100644 bacula/src/tray-monitor/eggtrayicon.c create mode 100644 bacula/src/tray-monitor/eggtrayicon.h create mode 100644 bacula/src/tray-monitor/tray-monitor.c create mode 100644 bacula/src/tray-monitor/tray-monitor.conf.in create mode 100644 bacula/src/tray-monitor/tray-monitor.h create mode 100644 bacula/src/tray-monitor/tray_conf.c create mode 100644 bacula/src/tray-monitor/tray_conf.h diff --git a/bacula/src/tray-monitor/Makefile.in b/bacula/src/tray-monitor/Makefile.in new file mode 100644 index 0000000000..d93e4b0dba --- /dev/null +++ b/bacula/src/tray-monitor/Makefile.in @@ -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 index 0000000000..f6afcf4a21 --- /dev/null +++ b/bacula/src/tray-monitor/authenticate.c @@ -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, "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 index 0000000000..544848845c --- /dev/null +++ b/bacula/src/tray-monitor/eggmarshalers.c @@ -0,0 +1,561 @@ + +extern "C" { + +#include + + +#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 index 0000000000..c375dbc04b --- /dev/null +++ b/bacula/src/tray-monitor/eggmarshalers.h @@ -0,0 +1,127 @@ + +#ifndef ___egg_marshal_MARSHAL_H__ +#define ___egg_marshal_MARSHAL_H__ + +#include + +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 index 0000000000..d443ca7cd7 --- /dev/null +++ b/bacula/src/tray-monitor/eggmarshalers.list @@ -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 index 0000000000..7b4ce61e7a --- /dev/null +++ b/bacula/src/tray-monitor/eggstatusicon.c @@ -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 + */ + +#include +#include + +#include "eggstatusicon.h" + +#include +#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 index 0000000000..cde7ae9df0 --- /dev/null +++ b/bacula/src/tray-monitor/eggstatusicon.h @@ -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 + */ + +#ifndef __EGG_STATUS_ICON_H__ +#define __EGG_STATUS_ICON_H__ + +#include "eggtrayicon.h" +#include + +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 index 0000000000..0539cd9bf8 --- /dev/null +++ b/bacula/src/tray-monitor/eggtrayicon.c @@ -0,0 +1,479 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* eggtrayicon.c + * Copyright (C) 2002 Anders Carlsson + * + * 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 +#include + +#include "eggtrayicon.h" + +#include +#include + +#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 index 0000000000..007f4c18e9 --- /dev/null +++ b/bacula/src/tray-monitor/eggtrayicon.h @@ -0,0 +1,77 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* eggtrayicon.h + * Copyright (C) 2002 Anders Carlsson + * + * 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 +#include + +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 index 0000000000..e06e8ebbb8 --- /dev/null +++ b/bacula/src/tray-monitor/tray-monitor.c @@ -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 + +#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 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(""); + } + else if (FD_sock->msglen == BNET_EOD) { + printf(""); + 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(""); + break; + } + + if (is_bnet_stop(FD_sock)) { + printf(""); + 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 index 0000000000..3038b725cc --- /dev/null +++ b/bacula/src/tray-monitor/tray-monitor.conf.in @@ -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 index 0000000000..e62d7b1249 --- /dev/null +++ b/bacula/src/tray-monitor/tray-monitor.h @@ -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 index 0000000000..4e3955c9e5 --- /dev/null +++ b/bacula/src/tray-monitor/tray_conf.c @@ -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 index 0000000000..bc16b311cc --- /dev/null +++ b/bacula/src/tray-monitor/tray_conf.h @@ -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; +}; + -- 2.39.5