~ubuntu-core-dev/update-notifier/ubuntu

« back to all changes in this revision

Viewing changes to src/update-notifier.c

  • Committer: mvo
  • Date: 2006-02-20 13:59:01 UTC
  • Revision ID: gustavo@niemeyer.net-20060220135901-720c2a7ec5a58192
* removed the wretched intl again

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 * Copyright (C) 2004 Lukas Lipka <lukas@pmad.net>
3
3
 *           (C) 2004 Michael Vogt <mvo@debian.org>
4
4
 *           (C) 2004 Michiel Sikkes <michiel@eyesopened.nl>
5
 
 *           (C) 2004-2009 Canonical
 
5
 *           (C) 2004-2006 Canonical
6
6
 *
7
7
 * This library is free software; you can redistribute it and/or
8
8
 * modify it under the terms of the GNU Lesser General Public
16
16
 *
17
17
 * You should have received a copy of the GNU Lesser General Public
18
18
 * License along with this library; if not, write to the
19
 
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor
20
 
 * Boston, MA  02110-1301 USA.
 
19
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
20
 * Boston, MA 02111-1307, USA.
21
21
 */
22
22
 
23
23
#ifdef HAVE_CONFIG_H
24
24
#include "config.h"
25
25
#endif
26
26
 
27
 
#include <stdlib.h>
28
27
#include <signal.h>
 
28
#include <gnome.h>
29
29
#include <grp.h>
30
30
#include <pwd.h>
31
31
#include <limits.h>
32
 
#include <glib.h>
33
 
#include <glib/gstdio.h>
34
32
#include <gtk/gtk.h>
35
 
#include <gio/gio.h>
 
33
#include <glade/glade.h>
 
34
#include <libgnomevfs/gnome-vfs.h>
 
35
#include <libgnomevfs/gnome-vfs-utils.h>
 
36
#include <libgnomevfs/gnome-vfs-monitor.h>
36
37
 
37
38
#include "update-notifier.h"
 
39
#include "eggtrayicon.h"
 
40
#include "hal.h"
38
41
#include "update.h"
39
42
#include "hooks.h"
40
 
#include "gdu.h"
41
 
#include "reboot.h"
42
 
#include "crash.h"
43
 
#include "avahi.h"
44
43
 
45
44
/* some prototypes */
46
45
extern gboolean up_get_clipboard (void);
47
46
gboolean update_timer_finished(gpointer data);
 
47
static void tray_destroyed_cb(GtkWidget *widget, void *data);
 
48
 
 
49
#define UPDATE_ICON_FILE PACKAGE_DATA_DIR"/pixmaps/update-icon.png"
 
50
#define HOOK_ICON_FILE PACKAGE_DATA_DIR"/pixmaps/hook-notifier.png"
 
51
#define REBOOT_ICON_FILE PACKAGE_DATA_DIR"/pixmaps/reboot-icon.png"
48
52
 
49
53
// the time when we check for fam events
50
54
#define TIMEOUT_FAM 1000*5 /* 5 sec */
53
57
// /var/lib/apt/lists{/partial})
54
58
#define TIMEOUT_APT_GET_UPDATE 1000*30 /* 30 sec */
55
59
 
56
 
// the timeout (in sec) when a further activity from dpkg/apt
57
 
// causes the applet to "ungray"
58
 
#define TIMEOUT_APT_RUN 600 /* 600 sec */
59
 
 
60
 
// force startup even if the user is not in the admin group
61
 
static gboolean FORCE_START=FALSE;
62
 
 
63
 
// force gksu for all menu actions
64
 
static gboolean FORCE_GKSU=FALSE;
65
 
 
66
 
// delay on startup (to make session startup faster)
67
 
static int STARTUP_DELAY=1;
68
 
 
69
 
// global debug options
70
 
int HOOK_DEBUG = 0;
71
 
int UPDATE_DEBUG = 0;
72
 
int INOTIFY_DEBUG = 0;
73
 
 
74
 
// logging stuff
75
 
static void debug_log_handler (const gchar   *log_domain,
76
 
                              GLogLevelFlags log_level,
77
 
                              const gchar   *message,
78
 
                              gpointer       user_data)
79
 
{
80
 
   if (HOOK_DEBUG > 0 && strcmp(log_domain, "hooks") == 0)
81
 
       g_log_default_handler (log_domain, log_level, message, user_data);
82
 
   if (UPDATE_DEBUG > 0 && strcmp(log_domain, "update") == 0)
83
 
       g_log_default_handler (log_domain, log_level, message, user_data);
84
 
   if (INOTIFY_DEBUG > 0 && strcmp(log_domain, "inotify") == 0)
85
 
       g_log_default_handler (log_domain, log_level, message, user_data);
86
 
 
87
 
}
88
 
 
89
 
static inline void
90
 
g_debug_inotify(const char *msg, ...)
91
 
{
92
 
   va_list va;
93
 
   va_start(va, msg);
94
 
   g_logv("inotify",G_LOG_LEVEL_DEBUG, msg, va);
95
 
   va_end(va);
96
 
}
97
 
 
98
 
void invoke(const gchar *cmd, const gchar *desktop, gboolean with_gksu)
99
 
{
100
 
   GdkAppLaunchContext *context;
101
 
   GAppInfo *appinfo;
102
 
   GError *error = NULL;
103
 
   static GtkWidget *w = NULL;
104
 
 
105
 
   // gksu
106
 
   if(with_gksu || FORCE_GKSU) {
107
 
      invoke_with_gksu(cmd, desktop, FALSE);
108
 
      return;
109
 
   }
110
 
 
111
 
   // fake window to get the current server time *urgh*
112
 
   if (!w) {
113
 
      w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
114
 
      gtk_widget_realize (w);
115
 
   }
116
 
 
117
 
   // normal launch
118
 
   context = gdk_app_launch_context_new ();
119
 
   guint32 timestamp =  gdk_x11_get_server_time (w->window);
120
 
   appinfo = g_app_info_create_from_commandline(cmd, 
121
 
                                                cmd, 
122
 
                                                G_APP_INFO_CREATE_NONE,
123
 
                                                &error);
124
 
   gdk_app_launch_context_set_timestamp (context, timestamp);
125
 
   if (!g_app_info_launch (appinfo, NULL, context, &error))
126
 
      g_warning ("Launching failed: %s\n", error->message);
127
 
   g_object_unref (context);
128
 
   g_object_unref (appinfo);
129
 
 
130
 
}
 
60
// the timeout (in sec) for a notification after apt/dpkg have finished
 
61
#define TIMEOUT_APT_RUN 60 /* 60 sec */
 
62
 
131
63
 
132
64
void
133
 
invoke_with_gksu(const gchar *cmd, const gchar *descr, gboolean whole_message)
 
65
invoke_with_gksu(gchar *cmd, gchar *descr)
134
66
{
 
67
        gchar *full_descr = NULL;
 
68
        if(descr != NULL)
 
69
           full_descr = g_strdup_printf(_("Please enter your password to run:\n %s"), descr);
 
70
 
135
71
        //g_print("invoke_update_manager ()\n");
136
 
        gchar *argv[5];
137
 
        argv[0] = "/usr/bin/gksu";
138
 
        argv[1] = whole_message ? "--message" : "--desktop";
139
 
        argv[2] = (gchar*)descr;
140
 
        argv[3] = (gchar*)cmd;
 
72
        gchar *argv[5];
 
73
        argv[0] = "/usr/bin/gksudo";
 
74
        argv[1] = "--message";
 
75
        argv[2] = full_descr;
 
76
        argv[3] = cmd;
141
77
        argv[4] = NULL;
142
78
 
143
79
        g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, NULL, NULL);
 
80
        g_free(full_descr);
144
81
}
145
82
 
146
83
 
147
84
 
148
85
gboolean
149
 
trayapplet_create (TrayApplet *un, char *name)
 
86
trayapplet_create (TrayApplet *un, char *name, char *iconfile)
150
87
{
151
88
        //g_print("trayicon_create()\n");
 
89
        GdkPixbuf *pixbuf;
152
90
 
153
91
        /* setup widgets */
154
 
        un->tray_icon = gtk_status_icon_new_from_icon_name (name);
155
 
        un->name = name;
156
 
        gtk_status_icon_set_visible (un->tray_icon, FALSE);
 
92
        un->tooltip = gtk_tooltips_new ();
 
93
        un->tray_icon = egg_tray_icon_new (name);
 
94
        gtk_widget_show(un->tray_icon);
 
95
        un->eventbox = gtk_event_box_new ();
 
96
        gtk_widget_show(un->eventbox);
 
97
        un->icon = gtk_image_new ();
 
98
        gtk_widget_show(un->icon);
 
99
 
 
100
        /* load icon */
 
101
        pixbuf = gtk_image_get_pixbuf (GTK_IMAGE(un->icon));
 
102
        if (pixbuf)
 
103
                g_object_unref (G_OBJECT (pixbuf));
 
104
        pixbuf = gdk_pixbuf_new_from_file (iconfile, NULL);
 
105
        gtk_image_set_from_pixbuf (GTK_IMAGE (un->icon), pixbuf);
 
106
 
 
107
        /* build container */
 
108
        gtk_container_add (GTK_CONTAINER (un->eventbox), un->icon);
 
109
        gtk_container_add (GTK_CONTAINER (un->tray_icon), un->eventbox);
 
110
        gtk_widget_hide(un->tray_icon);
157
111
 
158
112
        return TRUE;
159
113
}
169
123
  - /var/lib/apt/lists/lock
170
124
  - /var/lib/apt/lists/ *
171
125
  - /var/lib/dpkg/lock
172
 
  - /var/lib/apt/periodic/update-success-stamp
173
126
*/
174
127
void
175
 
monitor_cb(GFileMonitor *handle,
176
 
           GFile *monitor_f,
177
 
           GFile *other_monitor_f,
178
 
           GFileMonitorEvent event_type,
 
128
monitor_cb(GnomeVFSMonitorHandle *handle,
 
129
           const gchar *monitor_uri,
 
130
           const gchar *info_uri,
 
131
           GnomeVFSMonitorEventType event_type,
179
132
           gpointer user_data)
180
133
{
181
134
   UpgradeNotifier *un = (UpgradeNotifier*)user_data;
 
135
   int i;
182
136
 
183
 
   gchar *info_uri = g_file_get_path(monitor_f);
184
137
#if 0
185
 
   g_debug_inotify("info_uri: %s\n", info_uri);
186
 
   g_debug_inotify("event_type: %i\n",event_type);
 
138
   g_print("monitor_uri: %s\n", monitor_uri);
 
139
   g_print("info_uri: %s\n", info_uri);
 
140
   g_print("event_type: %i\n",event_type);
187
141
#endif
188
142
 
189
143
   // we ignore lock file events because we can only get 
192
146
      return;
193
147
 
194
148
   // look for apt-get install/update
195
 
   if(g_str_has_prefix(info_uri,"/var/lib/apt/") 
196
 
      || g_str_has_prefix(info_uri,"/var/cache/apt/")
197
 
      || strcmp(info_uri,"/var/lib/dpkg/status") == 0) {
198
 
      g_debug_inotify("apt_get_running=TRUE");
199
 
      un->apt_get_runing=TRUE;
 
149
   if(g_str_has_prefix(info_uri,"file:///var/lib/apt/") 
 
150
      || g_str_has_prefix(info_uri,"file:///var/cache/apt/")
 
151
      || strcmp(info_uri,"file:///var/lib/dpkg/status") == 0) {
 
152
      // a timer is already runing, stop it and start a new one
 
153
      if(un->update_finished_timer > 0) {
 
154
         //g_print("removing old timer: %i\n", un->update_finished_timer);
 
155
         g_source_remove(un->update_finished_timer);
 
156
         un->update_finished_timer = 0;
 
157
      }
 
158
      un->apt_get_update_runing=TRUE;
200
159
   } 
201
 
   if(strstr(info_uri, "/var/lib/update-notifier/dpkg-run-stamp") ||
202
 
      strstr(info_uri, "/var/lib/apt/periodic/update-success-stamp")) {
203
 
      g_debug_inotify("dpkg_was_run=TRUE");
 
160
   if(strstr(info_uri, "/var/lib/update-notifier/dpkg-run-stamp")) {
204
161
      un->dpkg_was_run = TRUE;
205
162
   } 
206
163
   if(strstr(info_uri, REBOOT_FILE)) {
207
 
      g_debug_inotify("reboot required\n");
 
164
      //g_print("reboot required\n");
208
165
      un->reboot_pending = TRUE;
209
166
   }
210
167
   if(strstr(info_uri, HOOKS_DIR)) {
211
 
      g_debug_inotify("new hook!\n");
 
168
      //g_print("new hook!\n");
212
169
      un->hook_pending = TRUE;
213
170
   }
214
 
   if(strstr(info_uri, CRASHREPORT_DIR)) {
215
 
      g_debug_inotify("crashreport found\n");
216
 
      un->crashreport_pending = TRUE;
217
 
   }
218
 
   if(strstr(info_uri, UNICAST_LOCAL_AVAHI_FILE)) {
219
 
      g_debug_inotify("avahi disabled due to unicast .local domain\n");
220
 
      un->unicast_local_avahi_pending = TRUE;
221
 
   }
222
171
}
223
172
 
224
 
/*
225
 
 * We periodically check here what actions happend in this "time-slice". 
226
 
 * This can be:
227
 
 * - dpkg_was_run=TRUE: set when apt wrote the "dpkg-run-stamp" file
228
 
 * - apt_get_runing: set when apt/dpkg activity is detected (in the 
229
 
 *                   lists-dir, archive-cache, or /var/lib/dpkg/status
230
 
 * - hook_pending: we have new upgrade hoook information
231
 
 * - reboot_pending: we need to reboot
232
 
 * - crashreport_pending: we have a new crashreport
233
 
 * - unicast_local_avahi_pending: avahi got disabled due to a unicast .local domain
234
 
 *
235
 
 */
236
173
gboolean file_monitor_periodic_check(gpointer data)
237
174
 
238
175
{
239
176
   UpgradeNotifier *un = (UpgradeNotifier *)data;
240
177
 
241
 
   // we are not ready yet, wait for the next timeslice
242
 
   if((un->reboot == NULL) || (un->crashreport == NULL))
243
 
      return TRUE;
244
 
 
245
 
   // DPkg::Post-Invoke has written a stamp file, that means a install/remove
246
 
   // operation finished, we can show hooks/reboot notifications then
 
178
   // DPkg::Post-Invoke has written a stamp file
247
179
   if(un->dpkg_was_run) {
248
 
 
249
180
      // check updates
250
181
      update_check(un->update);
251
182
 
267
198
         un->reboot_pending = FALSE;
268
199
      }
269
200
 
270
 
      // apt must be finished when a new stamp file was writen, so we
271
 
      // reset the apt_get_runing time-slice field because its not 
272
 
      // important anymore (it finished runing)
273
 
      //
274
 
      // This may leave a 5s race condition when a apt-get install finished
275
 
      // and something new (apt-get) was started
276
 
      un->apt_get_runing = FALSE;
277
201
      un->last_apt_action = 0;
278
202
   }
279
203
 
280
 
   // apt-get update/install or dpkg is runing (and updates files in 
281
 
   // it's list/cache dir) or in /var/lib/dpkg/status
282
 
   if(un->apt_get_runing) 
 
204
   // apt-get update is runing (and udpates files in it's list dir)
 
205
   if(un->apt_get_update_runing) {
283
206
      update_apt_is_running(un->update, TRUE);
 
207
      un->update_finished_timer = g_timeout_add(TIMEOUT_APT_GET_UPDATE,
 
208
                                                update_timer_finished, un);
 
209
   }
284
210
 
285
211
   // update time information for apt/dpkg
286
212
   time_t now = time(NULL);
287
 
   if(un->apt_get_runing) 
 
213
   if(un->dpkg_was_run || un->apt_get_update_runing) 
288
214
      un->last_apt_action = now;
289
 
 
290
 
   // no apt operation for a long time
291
 
   if(un->last_apt_action > 0 &&
292
 
      (now - un->last_apt_action) >  TIMEOUT_APT_RUN) {
293
 
      update_apt_is_running(un->update, FALSE);
294
 
      update_check(un->update);
295
 
      un->last_apt_action = 0;
296
 
   }
297
 
 
298
 
   if(un->crashreport_pending) {
299
 
      g_print("checking for valid crashreport now\n");
300
 
      crashreport_check (un->crashreport);
301
 
      un->crashreport_pending = FALSE;
302
 
   }
303
 
 
304
 
   if(un->unicast_local_avahi_pending) {
305
 
      g_print("checking for disabled avahi due to unicast .local domain now\n");
306
 
      avahi_disabled_check ();
307
 
      un->unicast_local_avahi_pending = FALSE;
308
 
   }
309
 
 
310
 
   // reset the bitfields (for the next "time-slice")
 
215
  
 
216
 
 
217
   // if there is a hook pending, check that no apt/dpkg/etc is
 
218
   // runing within the last N-sec
 
219
   if(un->hook_pending || un->reboot_pending) {
 
220
 
 
221
      //g_print("hook_pending: now=%i last_action=%i (%i) \n", now, un->last_apt_action,now-un->last_apt_action);
 
222
 
 
223
      if( (now - un->last_apt_action) >  TIMEOUT_APT_RUN) {
 
224
         //g_print("checking hooks now because of timeout\n");
 
225
 
 
226
         if(un->hook_pending)
 
227
            check_update_hooks(un->hook);
 
228
 
 
229
         if(un->reboot_pending)
 
230
            reboot_check (un->reboot);
 
231
 
 
232
         un->hook_pending = FALSE;
 
233
         un->reboot_pending = FALSE;
 
234
         un->last_apt_action = 0;
 
235
      }
 
236
   }
 
237
 
 
238
   // reset the bitfields
311
239
   un->dpkg_was_run = FALSE;
312
 
   un->apt_get_runing = FALSE;
 
240
   un->apt_get_update_runing = FALSE;
313
241
 
314
242
   return TRUE;
315
243
}
321
249
 * End user might not understand the message at all */
322
250
void u_abort(gchar *msg)
323
251
{
324
 
   const char *fmt = "<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s\n";
325
 
   gtk_dialog_run(GTK_DIALOG(gtk_message_dialog_new_with_markup(NULL, 0,
 
252
   msg = g_strdup_printf("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s\n", _("Internal error"), msg);
 
253
   gtk_dialog_run(gtk_message_dialog_new_with_markup(NULL,0,
326
254
                                                     GTK_MESSAGE_ERROR,
327
255
                                                     GTK_BUTTONS_CLOSE,
328
 
                                                     fmt,
329
 
                                                     _("Internal error"),
330
 
                                                     msg)));
 
256
                                                     msg));
331
257
   g_free(msg);
332
258
   exit(1);
333
259
}
334
260
 
335
261
// FIXME: get the apt directories with apt-config or something
336
 
gboolean 
337
 
monitor_init(UpgradeNotifier *un)
 
262
gboolean monitor_init(UpgradeNotifier *un)
338
263
{
339
264
   int i;
340
 
   GFileMonitor *monitor_handle;
 
265
   GnomeVFSResult res;
 
266
   GnomeVFSMonitorHandle *monitor_handle;
341
267
 
342
 
   // monitor thise dirs
343
268
   static const char *monitor_dirs[] = { 
344
 
      "/var/lib/apt/lists/", "/var/lib/apt/lists/partial/", 
345
 
      "/var/cache/apt/archives/", "/var/cache/apt/archives/partial/", 
346
 
      HOOKS_DIR, 
347
 
      CRASHREPORT_DIR,
 
269
      "/var/lib/apt/lists/", "/var/lib/apt/list/partial", 
 
270
      "/var/cache/apt/archives/", "/var/cache/apt/archives/partial", 
 
271
      HOOKS_DIR,
348
272
      NULL};
 
273
      
349
274
   for(i=0;monitor_dirs[i] != NULL;i++) {
350
 
      GError *error = NULL;
351
 
      GFile *gf = g_file_new_for_path(monitor_dirs[i]);
352
 
      monitor_handle = g_file_monitor_directory(gf, 0, NULL, &error);
353
 
      if(monitor_handle)
354
 
         g_signal_connect(monitor_handle, "changed", (GCallback)monitor_cb, un);
355
 
      else
356
 
         g_warning("can not add '%s'\n", monitor_dirs[i]);
357
 
   }
358
 
 
359
 
   // and those files
360
 
   static const char *monitor_files[] = { 
361
 
      "/var/lib/dpkg/status", 
362
 
      "/var/lib/update-notifier/dpkg-run-stamp", 
363
 
      "/var/lib/apt/periodic/update-success-stamp",
364
 
      REBOOT_FILE,
365
 
      UNICAST_LOCAL_AVAHI_FILE,
366
 
      NULL};
367
 
   for(i=0;monitor_files[i] != NULL;i++) {
368
 
      GError *error = NULL;
369
 
      GFile *gf = g_file_new_for_path(monitor_files[i]);
370
 
      monitor_handle = g_file_monitor_file(gf, 0, NULL, &error);
371
 
      if(monitor_handle)
372
 
         g_signal_connect(monitor_handle, "changed", (GCallback)monitor_cb, un);
373
 
      else
374
 
         g_warning("can not add '%s'\n", monitor_dirs[i]);
375
 
   }
 
275
      res = gnome_vfs_monitor_add(&monitor_handle,
 
276
                                  monitor_dirs[i],
 
277
                                  GNOME_VFS_MONITOR_DIRECTORY,
 
278
                                  monitor_cb, un);
 
279
   }
 
280
   res = gnome_vfs_monitor_add(&monitor_handle,
 
281
                               "/var/lib/dpkg/status", 
 
282
                               GNOME_VFS_MONITOR_FILE,
 
283
                               monitor_cb,
 
284
                               un);
 
285
   res = gnome_vfs_monitor_add(&monitor_handle,
 
286
                               "/var/lib/update-notifier/dpkg-run-stamp", 
 
287
                               GNOME_VFS_MONITOR_FILE,
 
288
                               monitor_cb,
 
289
                               un);
 
290
   res = gnome_vfs_monitor_add(&monitor_handle,
 
291
                               "/var/run/reboot-required", 
 
292
                               GNOME_VFS_MONITOR_FILE,
 
293
                               monitor_cb,
 
294
                               un);
376
295
 
377
296
   g_timeout_add (TIMEOUT_FAM, (GSourceFunc)file_monitor_periodic_check, un);
378
297
 
379
298
 
 
299
#if 0
 
300
   FAMRequest frq;
 
301
 
 
302
   // FIXME: if the number of directories is increased that are monitored
 
303
   // for apt, make sure that they alaway fir in UpgradeNotifier.frq_apt
 
304
   int aptindx=0;
 
305
 
 
306
   /* setup FAM/GAMIN, monitor the importend directories */
 
307
   if(FAMOpen(&un->fc) >= 0) {
 
308
 
 
309
      // monitor for apt getting updates
 
310
      if(FAMMonitorDirectory(&un->fc, "/var/lib/apt/lists/", 
 
311
                             &un->frq_apt[aptindx++], NULL)) 
 
312
         u_abort("FAMMonitorFile() failed, make sure that fam/gamin "
 
313
                 "is installed");
 
314
 
 
315
      if(FAMMonitorDirectory(&un->fc, "/var/lib/apt/lists/partial/", 
 
316
                             &un->frq_apt[aptindx++], NULL))
 
317
         u_abort("FAMMonitorFile() failed, , make sure that fam/gamin "
 
318
                 "is installed");
 
319
 
 
320
      // monitor for apt geting packages
 
321
      if(FAMMonitorDirectory(&un->fc, "/var/cache/apt/archives/", 
 
322
                             &un->frq_apt[aptindx++], NULL))
 
323
         u_abort("FAMMonitorFile() failed, , make sure that fam/gamin "
 
324
                 "is installed");
 
325
 
 
326
      if(FAMMonitorDirectory(&un->fc, "/var/cache/apt/archives/partial/", 
 
327
                             &un->frq_apt[aptindx++], NULL))
 
328
         u_abort("FAMMonitorFile() failed, , make sure that fam/gamin "
 
329
                 "is installed");
 
330
 
 
331
      // dpkg database
 
332
      if(FAMMonitorFile(&un->fc, 
 
333
                        "/var/lib/dpkg/status", 
 
334
                        &un->frq_apt[aptindx++], NULL))
 
335
         u_abort("FAMMonitorFile() failed, make sure that fam/gamin "
 
336
                 "is installed");
 
337
 
 
338
      // monitor for hooks
 
339
      if(FAMMonitorDirectory(&un->fc, HOOKS_DIR, 
 
340
                             &un->frq_hooks, NULL))
 
341
         u_abort("FAMMonitorFile() failed, make sure that fam/gamin "
 
342
                 "is installed");
 
343
 
 
344
      // monitor for installs
 
345
      if(FAMMonitorFile(&un->fc, 
 
346
                        "/var/lib/update-notifier/dpkg-run-stamp", 
 
347
                        &frq, NULL))
 
348
         u_abort("FAMMonitorFile() failed, make sure that fam/gamin "
 
349
                 "is installed");
 
350
   } else {
 
351
      u_abort("FAMOpen() failed, make sure that fam/gamin "
 
352
              "is installed");
 
353
   }
 
354
 
 
355
   un->frq_apt[aptindx].reqnum = -1;
 
356
#endif
380
357
   return TRUE;
381
358
}
382
359
 
386
363
static gboolean
387
364
tray_icons_init(UpgradeNotifier *un)
388
365
{
389
 
   //g_debug_inotify("tray_icons_init");
390
 
 
391
 
   /* new upates tray icon */
392
 
   un->update = g_new0 (TrayApplet, 1);
393
 
 
394
 
   // check if the updates icon should be displayed
395
 
   if (in_admin_group() || FORCE_START) {
396
 
      trayapplet_create(un->update, "software-update-available");
397
 
      update_tray_icon_init(un->update);
398
 
   } else 
399
 
      un->update = NULL;
400
 
 
401
 
   /* update hook icon*/
402
 
   un->hook = g_new0 (TrayApplet, 1);
403
 
   trayapplet_create(un->hook, "hook-notifier");
404
 
   hook_tray_icon_init(un->hook);
405
 
 
406
 
   /* reboot required icon */
407
 
   un->reboot = g_new0 (TrayApplet, 1);
408
 
   trayapplet_create(un->reboot, "reboot-notifier");
409
 
   reboot_tray_icon_init(un->reboot);
410
 
 
411
 
   /* crashreport detected icon */
412
 
   un->crashreport = g_new0 (TrayApplet, 1);
413
 
   trayapplet_create(un->crashreport, "apport");
414
 
   crashreport_tray_icon_init(un->crashreport);
415
 
 
416
 
   return FALSE; // for the tray_destroyed_cb
 
366
        /* new upates tray icon */
 
367
        un->update = g_new0 (TrayApplet, 1);
 
368
        trayapplet_create(un->update, "update-notifier", UPDATE_ICON_FILE);
 
369
        update_tray_icon_init(un->update);
 
370
 
 
371
        /* a destroy signal handler (e.g. when the gnome-panel is restarted */
 
372
        g_signal_connect(G_OBJECT(un->update->tray_icon), "destroy", 
 
373
                         G_CALLBACK(tray_destroyed_cb), un);
 
374
 
 
375
 
 
376
        /* update hook icon*/
 
377
        un->hook = g_new0 (TrayApplet, 1);
 
378
        trayapplet_create(un->hook, "hook-notifier", HOOK_ICON_FILE);
 
379
        hook_tray_icon_init(un->hook);
 
380
 
 
381
        /* reboot required icon */
 
382
        un->reboot = g_new0 (TrayApplet, 1);
 
383
        trayapplet_create(un->reboot, "reboot-notifier", REBOOT_ICON_FILE);
 
384
        reboot_tray_icon_init(un->reboot);
 
385
 
 
386
        return FALSE; // for the tray_destroyed_cb
417
387
}
418
388
 
419
 
gboolean
420
 
system_user()
 
389
static void
 
390
tray_destroyed_cb(GtkWidget *widget, void *data)
421
391
{
422
 
   /* do not start for system users, e.g. the guest session 
423
 
    * (see /usr/share/gdm/guest-session/guest-session-setup.sh)
424
 
    */
425
 
   int end_system_uid = 500;
426
 
   GConfClient *gconf = gconf_client_get_default();
427
 
   if (gconf) {
428
 
      int i = gconf_client_get_int(gconf, GCONF_KEY_END_SYSTEM_UIDS, NULL);
429
 
      if (i>0)
430
 
         end_system_uid = i;
431
 
   }
432
 
 
433
 
   uid_t uid = getuid();
434
 
   if (uid < end_system_uid)
435
 
      return TRUE;
436
 
   return FALSE;
 
392
        g_critical("tray icon destroyed\n");
 
393
        // FIXME: handle this situation
 
394
        g_timeout_add(1000, (GSourceFunc*)(tray_icons_init), data);
437
395
}
438
396
 
439
397
// this function checks if the user is in the admin group
440
398
// if there is no admin group, we return true becuase there
441
399
// is no way to figure if the user is a admin or not
442
 
gboolean
 
400
static gboolean
443
401
in_admin_group()
444
402
{
445
403
   int i, ng = 0;
446
404
   gid_t *groups = NULL;
 
405
   struct passwd *pw = getpwuid(getuid());
 
406
   if (pw == NULL)
 
407
      return TRUE;
447
408
 
448
409
   struct group *grp = getgrnam("admin");
449
410
   if(grp == NULL) 
450
411
      return TRUE;
451
 
 
452
 
   ng = getgroups (0, NULL);
453
 
   groups = (gid_t *) malloc (ng * sizeof (gid_t));
454
 
 
455
 
   i = getgroups (ng, groups);
456
 
   if (i != ng) {
457
 
     free (groups);
458
 
     return TRUE;
 
412
   
 
413
   if (getgrouplist(pw->pw_name, pw->pw_gid, NULL, &ng) < 0) {
 
414
      groups = (gid_t *) malloc(ng * sizeof (gid_t));
 
415
      getgrouplist(pw->pw_name, pw->pw_gid, groups, &ng);
459
416
   }
460
 
   
461
417
   for(i=0;i<ng;i++) {
462
418
      if(groups[i] == grp->gr_gid) {
463
 
        free(groups);
464
 
        return TRUE;
 
419
         return TRUE;
465
420
      }
466
421
   }
467
422
   
471
426
   return FALSE;
472
427
}
473
428
 
474
 
static GOptionEntry entries[] = 
475
 
{
476
 
   { "debug-hooks", 0, 0, G_OPTION_ARG_NONE, &HOOK_DEBUG, "Enable hooks debugging"},
477
 
   { "debug-updates", 0, 0, G_OPTION_ARG_NONE, &UPDATE_DEBUG, "Enable updates/autolaunch debugging"},
478
 
   { "debug-inotify", 0, 0, G_OPTION_ARG_NONE, &INOTIFY_DEBUG, "Enable inotify debugging"},
479
 
   { "force", 0, 0, G_OPTION_ARG_NONE, &FORCE_START, "Force start even if the user is not in the admin group"},
480
 
   { "force-use-gksu", 0, 0, G_OPTION_ARG_NONE, &FORCE_GKSU, "Force running all commands (update-manager, synaptic) with gksu" },
481
 
   { "startup-delay", 0, 0, G_OPTION_ARG_INT, &STARTUP_DELAY, "Delay startup by given amount of seconds" },
482
 
   { NULL }
483
 
};
484
 
 
485
429
int 
486
 
main (int argc, char **argv)
 
430
main (int argc, char *argv[])
487
431
{
 
432
        GnomeClient *client;
488
433
        UpgradeNotifier *un;
489
 
        GError *error = NULL;
490
434
 
491
 
        // init
492
 
        if(!gtk_init_with_args (&argc, &argv, 
493
 
                                _("- inform about updates"), entries, 
494
 
                                "update-notifier", &error) ) {
495
 
           fprintf(stderr, _("Failed to init the UI: %s\n"), 
496
 
                   error ? error->message : _("unknown error"));
497
 
           exit(1);
498
 
        }
 
435
        gnome_program_init (PACKAGE, PACKAGE_VERSION, 
 
436
                            LIBGNOMEUI_MODULE,
 
437
                            argc, argv, 
 
438
                            GNOME_PARAM_NONE);
499
439
 
500
440
        notify_init("update-notifier");
501
441
        bindtextdomain(PACKAGE, PACKAGE_LOCALE_DIR);
502
442
        bind_textdomain_codeset(PACKAGE, "UTF-8");
503
443
        textdomain(PACKAGE);
504
444
 
505
 
        // setup a custom debug log handler
506
 
        g_log_set_handler ("inotify", G_LOG_LEVEL_DEBUG,
507
 
                           debug_log_handler, NULL);
508
 
        g_log_set_handler ("hooks", G_LOG_LEVEL_DEBUG,
509
 
                           debug_log_handler, NULL);
510
 
        g_log_set_handler ("update", G_LOG_LEVEL_DEBUG,
511
 
                           debug_log_handler, NULL);
512
 
 
513
 
        g_set_application_name (_("update-notifier"));
514
 
        gtk_window_set_default_icon_name ("update-notifier");
515
 
 
516
445
        //g_print("starting update-notifier\n");
517
 
 
518
 
        // do not run as system user (e.g. guest user)
519
 
        if (system_user() && !FORCE_START) {
520
 
           g_warning("not starting for system user\n");
 
446
        
 
447
        // check if we should run at all (see HideAdminTools spec
 
448
        // on https://wiki.ubuntu.com/HideAdminToolsToUsers)
 
449
        if(!in_admin_group()) {
 
450
           g_warning("not starting because user is not in admin group\n");
521
451
           exit(0);
522
452
        }
523
453
 
524
 
        // check if it is running already
525
 
        if (!up_get_clipboard ()) {
 
454
        client = gnome_master_client ();
 
455
        if (up_get_clipboard ())
 
456
          gnome_client_set_restart_style (client, GNOME_RESTART_ANYWAY);
 
457
        else {
 
458
           gnome_client_set_restart_style (client, GNOME_RESTART_NEVER);
526
459
           g_warning ("already running?\n");
527
460
           return 1;
528
461
        }
529
462
 
 
463
        /* Make sure we die when the session dies */
 
464
        g_signal_connect (G_OBJECT (client), "die",
 
465
                          G_CALLBACK (gtk_main_quit), NULL);
 
466
        
530
467
        /* Create the UpgradeNotifier object */
531
468
        un = g_new0 (UpgradeNotifier, 1);
532
469
 
537
474
           g_mkdir(dirname, 0700);
538
475
        g_free(dirname);
539
476
 
540
 
        // delay icon creation for 30s so that the desktop 
541
 
        // login is not slowed down by update-notifier
542
 
        g_timeout_add_seconds(STARTUP_DELAY, 
543
 
                              (GSourceFunc)(tray_icons_init), un);
 
477
        // create the icons 
 
478
        tray_icons_init(un);
544
479
 
545
 
        // initial check for avahi
546
 
        avahi_disabled_check();
547
 
        
 
480
        // init hal (needs to be done _after_ the icons are created)
548
481
        /* setup hal so that inserted cdroms can be checked */
549
 
        if(!up_do_hal_init(un)) {
550
 
           g_warning("initializing gdu failed");
 
482
        LibHalContext *hal_ctx = up_do_hal_init();
 
483
        if (!hal_ctx) {
 
484
           u_abort("failed to initialize HAL!\n");
 
485
           return 1;
551
486
        }
552
 
 
553
 
        // init missing firmware monitoring
554
 
        missing_firmware_init();
555
 
 
556
 
        // init hplip monitoring
557
 
        hplip_init();
558
 
        
559
 
        // init gio file monitoring
560
 
        monitor_init (un);
561
 
        
 
487
        libhal_ctx_set_user_data(hal_ctx, un);
 
488
        
 
489
        // init fam
 
490
        monitor_init(un);
 
491
        
 
492
        /* Set a time-out for the fam check */
 
493
        //g_timeout_add (TIMEOUT_FAM, (GSourceFunc)file_monitor_check, un);
 
494
 
562
495
        /* Start the main gtk loop */
563
496
        gtk_main ();
564
497