source: trunk/third/gnome-applets/drivemount/drivemount.c @ 18647

Revision 18647, 21.1 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18646, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */
16
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20
21#include <stdio.h>
22#include <glib.h>
23#include <gtk/gtk.h>
24#include <libgnome/libgnome.h>
25#include <libgnomeui/libgnomeui.h>
26#include <panel-applet.h>
27#include <egg-screen-exec.h>
28
29#include "drivemount.h"
30#include "properties.h"
31
32#include "floppy_v_in.xpm"
33#include "floppy_v_out.xpm"
34#include "floppy_h_in.xpm"
35#include "floppy_h_out.xpm"
36#include "cdrom_v_in.xpm"
37#include "cdrom_v_out.xpm"
38#include "cdrom_h_in.xpm"
39#include "cdrom_h_out.xpm"
40#include "cdburn_v_in.xpm"
41#include "cdburn_v_out.xpm"
42#include "cdburn_h_in.xpm"
43#include "cdburn_h_out.xpm"
44#include "zipdrive_v_in.xpm"
45#include "zipdrive_v_out.xpm"
46#include "zipdrive_h_in.xpm"
47#include "zipdrive_h_out.xpm"
48#include "harddisk_v_in.xpm"
49#include "harddisk_v_out.xpm"
50#include "harddisk_h_in.xpm"
51#include "harddisk_h_out.xpm"
52
53#include "jazdrive_h_in.xpm"
54#include "jazdrive_h_out.xpm"
55#include "jazdrive_v_in.xpm"
56#include "jazdrive_v_out.xpm"
57
58
59static gboolean applet_factory (PanelApplet *applet, const gchar *iid,
60                                gpointer data);
61static gboolean applet_fill (PanelApplet *applet);
62static DriveData *create_drive_widget (PanelApplet *applet);
63static void dnd_init (DriveData *dd);
64static void dnd_drag_begin_cb (GtkWidget *widget, GdkDragContext *context,
65                               gpointer data);
66static void dnd_set_data_cb (GtkWidget *widget, GdkDragContext *context,
67                             GtkSelectionData *selection_data, guint info,
68                             guint time, gpointer data);
69static void applet_change_orient (GtkWidget *w, PanelAppletOrient o,
70                                  gpointer data);
71static void applet_change_pixel_size (GtkWidget *w, int size, gpointer data);
72static gboolean button_press_hack (GtkWidget      *widget,
73                                   GdkEventButton *event,
74                                   GtkWidget      *applet);
75static void destroy_drive_widget (GtkWidget *widget, gpointer data);
76static gint device_is_in_mountlist (DriveData *dd);
77static gint get_device (const gchar *file);
78static gint device_is_mounted (DriveData *dd);
79static void update_pixmap (DriveData *dd, gint t);
80static gint drive_update_cb (gpointer data);
81static void mount_cb (GtkWidget *widget, DriveData *dd);
82static void eject (DriveData *dd);
83
84static void browse_cb (BonoboUIComponent *uic,
85                       DriveData         *drivemount,
86                       const char        *verb);
87static void eject_cb  (BonoboUIComponent *uic,
88                       DriveData         *drivemount,
89                       const char        *verb);
90static void help_cb   (BonoboUIComponent *uic,
91                       DriveData         *drivemount,
92                       const char        *verb);
93static void about_cb  (BonoboUIComponent *uic,
94                       DriveData         *drivemount,
95                       const char        *verb);
96
97/*
98 *-------------------------------------------------------------------------
99 *icon struct
100 *-------------------------------------------------------------------------
101 */
102
103typedef struct _IconData IconData;
104struct _IconData {
105        char **pmap_h_in;
106        char **pmap_h_out;
107        char **pmap_v_in;
108        char **pmap_v_out;
109};
110
111static IconData icon_list[] = {
112        {
113         floppy_h_in_xpm,
114         floppy_h_out_xpm,
115         floppy_v_in_xpm,
116         floppy_v_out_xpm},
117        {
118         cdrom_h_in_xpm,
119         cdrom_h_out_xpm,
120         cdrom_v_in_xpm,
121         cdrom_v_out_xpm},
122        {
123         cdburn_h_in_xpm,
124         cdburn_h_out_xpm,
125         cdburn_v_in_xpm,
126         cdburn_v_out_xpm},
127        {
128         zipdrive_h_in_xpm,
129         zipdrive_h_out_xpm,
130         zipdrive_v_in_xpm,
131         zipdrive_v_out_xpm},
132        {
133         harddisk_h_in_xpm,
134         harddisk_h_out_xpm,
135         harddisk_v_in_xpm,
136         harddisk_v_out_xpm},
137        {
138         jazdrive_h_in_xpm,
139         jazdrive_h_out_xpm,
140         jazdrive_v_in_xpm,
141         jazdrive_v_out_xpm},
142        {
143         NULL,
144         NULL,
145         NULL,
146         NULL}
147};
148
149static gint icon_list_count = 6;
150
151/* Bonobo Verbs for our popup menu */
152static const BonoboUIVerb applet_menu_verbs [] = {
153        BONOBO_UI_UNSAFE_VERB ("Browse", browse_cb),
154        BONOBO_UI_UNSAFE_VERB ("Eject", eject_cb),
155        BONOBO_UI_UNSAFE_VERB ("Properties", properties_show),
156        BONOBO_UI_UNSAFE_VERB ("Help", help_cb),
157        BONOBO_UI_UNSAFE_VERB ("About", about_cb),
158        BONOBO_UI_VERB_END
159};
160
161enum {
162        TARGET_URI_LIST,
163        TARGET_TEXT_PLAIN
164};
165
166static GtkTargetEntry button_drag_types[] = {
167        {"text/uri-list", 0, TARGET_URI_LIST},
168        {"text/plain", 0, TARGET_TEXT_PLAIN}
169};
170static gint n_button_drag_types = 2;
171
172
173PANEL_APPLET_BONOBO_FACTORY ("OAFIID:GNOME_DriveMountApplet_Factory", PANEL_TYPE_APPLET,
174                             "Drive-Mount-Applet", "0", applet_factory, NULL)
175
176static gboolean
177applet_factory (PanelApplet *applet,
178                const gchar *iid, gpointer data)
179{
180        gboolean retval = FALSE;
181
182        if (!strcmp (iid, "OAFIID:GNOME_DriveMountApplet")) {
183                retval = applet_fill (applet);
184        }
185        return retval;
186}
187
188static gboolean
189applet_fill (PanelApplet *applet)
190{
191        DriveData *dd;
192        BonoboUIComponent *component;
193        gchar *tmp_path;
194       
195        gnome_window_icon_set_default_from_file (GNOME_ICONDIR"/drivemount-applet.png");
196       
197        panel_applet_add_preferences (applet,
198                                      "/schemas/apps/drivemount-applet/prefs",
199                                      NULL);
200        dd = create_drive_widget (applet);
201
202        gtk_container_add (GTK_CONTAINER (applet), dd->button);
203
204        dd->applet = GTK_WIDGET (applet);
205        dd->tooltips = gtk_tooltips_new ();
206        dd->orient = panel_applet_get_orient (PANEL_APPLET (applet));
207        dd->sizehint = panel_applet_get_size (PANEL_APPLET (applet));
208        g_signal_connect (G_OBJECT (dd->button), "button_press_event",
209                          G_CALLBACK (button_press_hack), applet);
210
211        g_signal_connect (G_OBJECT (applet), "change_orient",
212                          G_CALLBACK (applet_change_orient), dd);
213        g_signal_connect (G_OBJECT (applet), "change_size",
214                          G_CALLBACK (applet_change_pixel_size), dd);
215        g_signal_connect (GTK_OBJECT (applet), "destroy",
216                          G_CALLBACK (destroy_drive_widget), dd);
217
218        panel_applet_setup_menu_from_file (PANEL_APPLET (applet),
219                                           NULL,
220                                           "GNOME_DriveMountApplet.xml",
221                                           NULL,
222                                           applet_menu_verbs,
223                                           dd);
224
225        component = panel_applet_get_popup_component (PANEL_APPLET (applet));
226
227        tmp_path = gnome_is_program_in_path ("eject");
228        if (!tmp_path)
229                bonobo_ui_component_set_prop (component, "/commands/Eject",
230                                              "hidden", "1", NULL);
231        else
232                g_free (tmp_path);
233
234        redraw_pixmap (dd);
235        gtk_widget_show (GTK_WIDGET (applet));
236        start_callback_update (dd);
237        return TRUE;
238}
239
240static DriveData *
241create_drive_widget (PanelApplet *applet)
242{
243        DriveData *dd;
244
245        dd = g_new0 (DriveData, 1);
246        dd->applet = GTK_WIDGET (applet);
247
248        properties_load (dd);
249
250        dd->button = gtk_button_new ();
251        gtk_widget_show (dd->button);
252        g_signal_connect (G_OBJECT (dd->button), "clicked",
253                          G_CALLBACK (mount_cb), dd);
254        dnd_init (dd);
255        return dd;
256}
257
258/* This is a hack around the fact that gtk+ doesn't
259 * propogate button presses on button2/3.
260 */
261static gboolean
262button_press_hack (GtkWidget      *widget,
263                   GdkEventButton *event,
264                   GtkWidget      *applet)
265{
266    if (event->button == 3 || event->button == 2) {
267        gtk_propagate_event (applet, (GdkEvent *) event);
268
269        return TRUE;
270    }
271
272    return FALSE;
273}
274
275static void
276dnd_init (DriveData *dd)
277{
278        gtk_drag_source_set (dd->button, GDK_BUTTON1_MASK,
279                             button_drag_types, n_button_drag_types,
280                             GDK_ACTION_COPY | GDK_ACTION_LINK |
281                             GDK_ACTION_ASK);
282        g_signal_connect (G_OBJECT (dd->button), "drag_data_get",
283                          G_CALLBACK (dnd_set_data_cb), dd);
284        g_signal_connect (G_OBJECT (dd->button), "drag_begin",
285                          G_CALLBACK (dnd_drag_begin_cb), dd);
286}
287
288static void
289dnd_drag_begin_cb (GtkWidget *widget, GdkDragContext *context, gpointer data)
290{
291        DriveData *dd = data;
292
293        gtk_drag_set_icon_pixbuf (context,
294                                  gtk_image_get_pixbuf (GTK_IMAGE
295                                                        (dd->button_pixmap)),
296                                  -5, -5);
297}
298
299static void
300dnd_set_data_cb (GtkWidget *widget, GdkDragContext *context,
301                 GtkSelectionData *selection_data, guint info,
302                 guint time, gpointer data)
303{
304        DriveData *dd = data;
305
306        if (dd && dd->mount_point) {
307                gchar *text = NULL;
308
309                switch (info) {
310                case TARGET_URI_LIST:
311                        text = g_strconcat ("file:", dd->mount_point, "\r\n",
312                                            NULL);
313                        break;
314                case TARGET_TEXT_PLAIN:
315                        text = g_strdup (dd->mount_point);
316                        break;
317                }
318                gtk_selection_data_set (selection_data, selection_data->target,
319                                        8, text, strlen (text));
320                g_free (text);
321        } else {
322                gtk_selection_data_set (selection_data, selection_data->target,
323                                        8, NULL, 0);
324        }
325}
326
327void
328start_callback_update (DriveData *dd)
329{
330        gint delay;
331
332        delay = dd->interval *1000;
333        if (dd->timeout_id)
334                gtk_timeout_remove (dd->timeout_id);
335        dd->timeout_id =
336                gtk_timeout_add (delay, (GtkFunction) drive_update_cb, dd);
337}
338
339static void
340applet_change_orient (GtkWidget *w, PanelAppletOrient o, gpointer data)
341{
342        /* resize the applet and set the proper pixmaps */
343        DriveData *dd = data;
344
345        if (dd->orient == o)
346                return;
347
348        dd->orient = o;
349
350        redraw_pixmap (dd);
351}
352
353static void
354applet_change_pixel_size (GtkWidget *w, int size, gpointer data)
355{
356        DriveData *dd = data;
357
358        if (dd->sizehint != size) {
359                dd->sizehint = size;
360                redraw_pixmap (dd);
361        }
362}
363
364static void
365destroy_drive_widget (GtkWidget *widget, gpointer data)
366{
367        DriveData *dd = data;
368
369        g_free (dd->mount_point);
370        g_free (dd->mount_base);
371        g_free (dd);
372}
373
374static void
375browse_cb (BonoboUIComponent *uic,
376           DriveData         *drivemount,
377           const char        *verb)
378{
379        GError *error = NULL;
380        char   *command;
381
382        if (!drivemount->mounted)
383                mount_cb (NULL, drivemount);
384
385        if (!drivemount->mounted)
386                return;
387
388        command = g_strdup_printf ("nautilus %s", drivemount->mount_point);
389        egg_screen_execute_command_line_async (
390                gtk_widget_get_screen (drivemount->applet), command, &error);
391        g_free (command);
392        if (error) {
393                GtkWidget *dialog;
394
395                dialog = gtk_message_dialog_new (NULL,
396                                                 GTK_DIALOG_DESTROY_WITH_PARENT,
397                                                 GTK_MESSAGE_ERROR,
398                                                 GTK_BUTTONS_CLOSE,
399                                                 _("There was an error executing '%s' : %s"),
400                                                 command,
401                                                 error->message);
402
403                g_signal_connect (dialog, "response",
404                                  G_CALLBACK (gtk_widget_destroy),
405                                  NULL);
406
407                gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
408                gtk_window_set_screen (GTK_WINDOW (dialog),
409                                       gtk_widget_get_screen (drivemount->applet));
410
411                gtk_widget_show (dialog);
412
413                g_error_free (error);
414        }
415}
416
417static void
418eject_cb (BonoboUIComponent *uic,
419          DriveData         *drivemount,
420          const char        *verb)
421{
422        eject (drivemount);
423}
424
425static void
426help_cb (BonoboUIComponent *uic,
427         DriveData         *drivemount,
428         const char        *verb)
429
430{
431}
432
433static void
434about_cb (BonoboUIComponent *uic,
435          DriveData         *drivemount,
436          const char        *verb)
437{
438        static GtkWidget *about = NULL;
439        GdkPixbuf        *pixbuf;
440        GError           *error = NULL;
441        gchar            *file;
442       
443        static const gchar *authors[] = {
444                "John Ellis <johne@bellatlantic.net>",
445                "Chris Phelps <chicane@renient.com>",
446                NULL
447        };
448
449        const gchar *documenters[] = {
450                NULL
451        };
452
453        const gchar *translator_credits = _("translator_credits");
454
455        if (about) {
456                gtk_window_set_screen (GTK_WINDOW (about),
457                                       gtk_widget_get_screen (drivemount->applet));
458                gtk_window_present (GTK_WINDOW (about));
459                return;
460        }
461
462        file = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP, "drivemount-applet.png", FALSE, NULL);
463        pixbuf = gdk_pixbuf_new_from_file (file, &error);
464        g_free (file);
465   
466        if (error) {
467                g_warning (G_STRLOC ": cannot open %s: %s", file, error->message);
468                g_error_free (error);
469        }
470
471        about = gnome_about_new (_("Disk Mounter"), VERSION,
472                                 _("(C) 1999-2001 The GNOME Hackers\n"),
473                                 _
474                                 ("Applet for mounting and unmounting block volumes."),
475                                 authors,
476                                 documenters,
477                                 strcmp (translator_credits, "translator_credits") != 0 ? translator_credits : NULL,
478                                 pixbuf);
479        if (pixbuf)
480                gdk_pixbuf_unref (pixbuf);
481   
482        gtk_window_set_wmclass (GTK_WINDOW (about), "disk mounter", "Disk Mounter");
483        gtk_window_set_screen (GTK_WINDOW (about),
484                               gtk_widget_get_screen (drivemount->applet));
485        g_signal_connect (G_OBJECT (about), "destroy",
486                          G_CALLBACK (gtk_widget_destroyed), &about);
487        gtk_widget_show (about);
488}
489
490/*
491 *-------------------------------------------------------------------------
492 *mount status checks
493 *-------------------------------------------------------------------------
494 */
495
496static gint
497device_is_in_mountlist (DriveData *dd)
498{
499        FILE *fp;
500        gchar *command_line = "mount";
501        gchar buf[256];
502        gint found = FALSE;
503
504        if (!dd->mount_point)
505                return FALSE;
506
507        fp = popen (command_line, "r");
508        if (!fp) {
509                g_print ("unable to run command: %s\n", command_line);
510                return FALSE;
511        }
512        while (fgets (buf, sizeof (buf), fp)) {
513                gchar *ptr;
514                ptr = strstr (buf, dd->mount_point);
515                if (ptr != NULL) {
516                        gchar *p;
517                        p = ptr + strlen (dd->mount_point);
518                        if (*p == ' ' || *p == '\0' || *p == '\n') {
519                                found = TRUE;
520                                break;
521                        }
522                }
523        }
524        pclose (fp);
525        return found;
526}
527
528static gint
529get_device (const gchar *file)
530{
531        struct stat file_info;
532        gint t;
533
534        if (stat (file, &file_info) == -1)
535                t = -1;
536        else
537                t = (gint) file_info.st_dev;
538        return t;
539}
540
541static gint
542device_is_mounted (DriveData *dd)
543{
544        if (!dd->mount_point || !dd->mount_base)
545                return FALSE;
546
547        if (!dd->autofs_friendly) {
548                gint b, p;
549
550                b = get_device (dd->mount_base);
551                p = get_device (dd->mount_point);
552                if (b == p || p == -1 || b == -1)
553                        return FALSE;
554                else
555                        return TRUE;
556        } else {
557                if (device_is_in_mountlist (dd))
558                        return TRUE;
559                else
560                        return FALSE;
561        }
562}
563
564/*
565 *-------------------------------------------------------------------------
566 *image / widget setup and size changes
567 *-------------------------------------------------------------------------
568 */
569
570static void
571update_pixmap (DriveData *dd, gint t)
572{
573        GdkPixbuf *pixbuf;
574        GdkPixbuf *scaled;
575        char **pmap_d_in;
576        char **pmap_d_out;
577
578        gint width;
579        gint height;
580
581        gchar *tiptext;
582        gchar *text;
583
584        gint hint = dd->sizehint;
585
586        if (dd->device_pixmap > icon_list_count - 1)
587                dd->device_pixmap = 0;
588        if (dd->device_pixmap < 0
589            && (!dd->custom_icon_in || !dd->custom_icon_out))
590                dd->device_pixmap = 0;
591
592        if (!dd->button_pixmap) {
593                dd->button_pixmap = gtk_image_new ();
594                gtk_container_add (GTK_CONTAINER (dd->button),
595                                   dd->button_pixmap);
596                gtk_widget_show (dd->button_pixmap);
597        }
598
599        if (dd->device_pixmap < 0) {
600                if (t) {
601                        pixbuf = gdk_pixbuf_new_from_file (dd->custom_icon_in,
602                                                           NULL);
603                } else {
604                        pixbuf = gdk_pixbuf_new_from_file (dd->custom_icon_out,
605                                                           NULL);
606                }
607
608                if (pixbuf) {
609                        width = gdk_pixbuf_get_width (pixbuf);
610                        height = gdk_pixbuf_get_width (pixbuf);
611
612                        if (dd->orient == PANEL_APPLET_ORIENT_LEFT
613                            || dd->orient == PANEL_APPLET_ORIENT_RIGHT) {
614                                if (width > hint || dd->scale_applet) {
615                                        height = (float) height *hint / width;
616
617                                        width = hint;
618                                }
619                        } else {
620                                if (height > hint || dd->scale_applet) {
621                                        width = (float) width *hint / height;
622
623                                        height = hint;
624                                }
625                        }
626                        scaled = gdk_pixbuf_scale_simple (pixbuf, width, height,
627                                                          GDK_INTERP_BILINEAR);
628                        gtk_image_set_from_pixbuf (GTK_IMAGE
629                                                   (dd->button_pixmap), scaled);
630                        g_object_unref (G_OBJECT (pixbuf));
631                        g_object_unref (scaled);
632                }
633        } else {
634                if (dd->scale_applet) {
635                        width = hint;
636                        height = (float) hint / ICON_WIDTH *ICON_HEIGHT;
637                } else {
638                        width = ICON_WIDTH;
639                        height = ICON_HEIGHT;
640                }
641
642                if (dd->orient == PANEL_APPLET_ORIENT_LEFT
643                    || dd->orient == PANEL_APPLET_ORIENT_RIGHT || hint <= 36) {
644                        pmap_d_in = icon_list[dd->device_pixmap].pmap_h_in;
645                        pmap_d_out = icon_list[dd->device_pixmap].pmap_h_out;
646                } else {
647                        gint tmp;
648
649                        tmp = width;
650                        width = height;
651                        height = tmp;
652
653                        pmap_d_in = icon_list[dd->device_pixmap].pmap_v_in;
654                        pmap_d_out = icon_list[dd->device_pixmap].pmap_v_out;
655                }
656
657                if (t)
658                        pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **)
659                                                               pmap_d_in);
660                else
661                        pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **)
662                                                               pmap_d_out);
663                scaled = gdk_pixbuf_scale_simple (pixbuf, width, height,
664                                                  GDK_INTERP_BILINEAR);
665                gtk_image_set_from_pixbuf (GTK_IMAGE (dd->button_pixmap),
666                                           scaled);
667                g_object_unref (G_OBJECT (pixbuf));
668                g_object_unref (scaled);
669        }
670
671        if (t) {
672                text = _(" mounted");
673        } else {
674                text = _(" not mounted");
675        }
676        tiptext = g_strconcat (dd->mount_point, text, NULL);
677        gtk_tooltips_set_tip (dd->tooltips, dd->applet, tiptext, NULL);
678        g_free (tiptext);
679}
680
681void
682redraw_pixmap (DriveData *dd)
683{
684        if (!device_is_mounted (dd)) {
685                update_pixmap (dd, FALSE);
686                dd->mounted = FALSE;
687        } else {
688                update_pixmap (dd, TRUE);
689                dd->mounted = TRUE;
690        }
691}
692
693/*
694 *-------------------------------------------------------------------------
695 *main callback loop
696 *-------------------------------------------------------------------------
697 */
698
699static gint
700drive_update_cb (gpointer data)
701{
702        DriveData *dd = data;
703
704        if (!device_is_mounted (dd)) {
705                /* device not mounted */
706                if (dd->mounted) {
707                        update_pixmap (dd, FALSE);
708                        dd->mounted = FALSE;
709                }
710        } else {
711                /* device mounted */
712                if (!dd->mounted) {
713                        update_pixmap (dd, TRUE);
714                        dd->mounted = TRUE;
715                }
716        }
717        return TRUE;
718}
719
720/*
721 *-------------------------------------------------------------------------
722 *mount calls
723 *-------------------------------------------------------------------------
724 */
725
726static void
727mount_cb (GtkWidget *widget,
728          DriveData *dd)
729{
730        gchar *command_line;
731        gchar buf[512];
732        FILE *fp;
733        GString *str;
734        gint check = device_is_mounted (dd);
735        GtkWidget *hbox;
736        GtkWidget *label;
737        GtkWidget *image;
738
739        /* Stop the user from displaying zillions of error messages */
740        if (dd->error_dialog) {
741                gtk_window_set_screen (GTK_WINDOW (dd->error_dialog),
742                                       gtk_widget_get_screen (dd->applet));
743                gtk_window_present (GTK_WINDOW (dd->error_dialog));
744                return;
745        }
746
747        if (!check) {
748                command_line =
749                        g_strdup_printf ("mount %s 2>&1", dd->mount_point);
750        } else {
751                command_line =
752                        g_strdup_printf ("umount %s 2>&1", dd->mount_point);
753        }
754
755        fp = popen (command_line, "r");
756
757        if (!fp) {
758                printf ("unable to run command: %s\n", command_line);
759                g_free (command_line);
760                return;
761        }
762
763        str = g_string_new (NULL);
764
765        while (fgets (buf, sizeof (buf), fp) != NULL) {
766                gchar *b = buf;
767
768                g_string_append (str, b);
769        }
770
771        pclose (fp);
772
773        dd->mounted = device_is_mounted (dd);
774
775        if (check != dd->mounted) {
776                /* success! */
777                update_pixmap (dd, dd->mounted);
778
779                /* eject after unmounting, if enabled */
780                if (check && dd->auto_eject) {
781                        eject (dd);
782                }
783        } else {
784                dd->error_dialog =
785                        gtk_dialog_new_with_buttons (_
786                                                     ("Drive Mount Applet Warning"),
787                                                     NULL, GTK_DIALOG_MODAL,
788                                                     GTK_STOCK_OK,
789                                                     GTK_RESPONSE_OK, NULL);
790                gtk_window_set_screen (GTK_WINDOW (dd->error_dialog),
791                                       gtk_widget_get_screen (dd->applet));
792                hbox = gtk_hbox_new (FALSE, 0);
793                gtk_box_pack_start (GTK_BOX
794                                    (GTK_DIALOG (dd->error_dialog)->vbox), hbox,
795                                    FALSE, FALSE, 10);
796                g_string_prepend (str, _("\" reported:\n"));
797                g_string_prepend (str, command_line);
798                g_string_prepend (str, _("Drivemount command failed.\n\""));
799                image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR,
800                                                  GTK_ICON_SIZE_DIALOG);
801                gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 10);
802                label = gtk_label_new (str->str);
803                gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 10);
804                gtk_widget_show_all (dd->error_dialog);
805                gtk_dialog_run (GTK_DIALOG (dd->error_dialog));
806                gtk_widget_destroy (dd->error_dialog);
807                dd->error_dialog = NULL;
808        }
809        g_string_free (str, TRUE);
810        g_free (command_line);
811        return;
812}
813
814static void
815eject (DriveData *dd)
816{
817        gchar *command_line;
818        gchar buffer[512];
819        gchar dn[256];          /* Devicename */
820        gchar mp[256];          /* Mountpoint */
821        FILE *ml;               /* Mountlist */
822        gint found = FALSE;
823
824        if (!dd->mount_point)
825                return;
826
827        /*
828         * Search the output of mount for dd->mount_point
829         * and use the corresponting device name
830         * as argument for eject
831         * if the device is not mounted currently, use
832         * /etc/fstab for the check
833         */
834
835        if (dd->mounted) {
836                ml = popen ("mount", "r");
837                while (ml && fgets (buffer, sizeof (buffer), ml)) {
838                        if (sscanf (buffer, "%255s %*s %255s", dn, mp) == 2 &&
839                            (mp && strcmp (mp, dd->mount_point) == 0)) {
840                                found = TRUE;
841                                break;
842                        }
843                }
844                if (ml)
845                        pclose (ml);
846        } else {
847                ml = fopen ("/etc/fstab", "r");
848               
849                while (ml && fgets (buffer, sizeof (buffer), ml)) {
850                        if (sscanf (buffer, "%255s %255s", dn, mp) == 2 &&
851                            strcmp (mp, dd->mount_point) == 0) {
852                                found = TRUE;
853                                break;
854                        }
855                }
856                if (ml)
857                        fclose (ml);
858        }
859
860        if (!found) {           /* mp != dd->mount_point */
861                printf ("WARNING: drivemount.c ... dd->mount_point not found in list\
862                         (output of mount, or /etc/fstab) \n");
863                return;
864        }
865
866        if (dd->mounted) {
867                command_line = g_strdup_printf ("eject -u '%s'", dn);
868                /* perhaps it doesn't like the -u option */
869                if (system (command_line) != 0) {
870                        g_free (command_line);
871                        command_line = g_strdup_printf ("eject '%s'", dn);
872                        gnome_execute_shell (NULL, command_line);
873                }
874                g_free (command_line);
875        } else {
876                command_line = g_strdup_printf ("eject '%s'", dn);
877                gnome_execute_shell (NULL, command_line);
878                g_free (command_line);
879        }
880}
Note: See TracBrowser for help on using the repository browser.