Changeset 242 for trunk/gtk


Ignore:
Timestamp:
Apr 25, 2006, 7:26:27 AM (16 years ago)
Author:
joshe
Message:

Add IPC code for another process to communicate with a running

transmission-gtk instance.

Try to add any filenames found on the command-line, using IPC if

transmission-gtk is already running.

Some minor code cleanups.
Remove lockfile on a normal exit, justfor the sake of being tidy.

Location:
trunk/gtk
Files:
4 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/Makefile

    r227 r242  
    22include ../Makefile.common
    33
    4 SRCS = conf.c dialogs.c main.c trcellrenderertorrent.c util.c
     4SRCS = conf.c dialogs.c io.c ipc.c main.c trcellrenderertorrent.c util.c
    55OBJS = $(SRCS:%.c=%.o)
    66
  • trunk/gtk/conf.c

    r214 r242  
    3131#include <fcntl.h>
    3232#include <pwd.h>
     33#include <stdio.h>
    3334#include <stdlib.h>
    3435#include <string.h>
     
    3637#include <unistd.h>
    3738
    38 #include <gtk/gtk.h>
     39#include <glib.h>
    3940#include <glib/gi18n.h>
    4041
     
    4546#define CONF_SUBDIR             "gtk"
    4647#define FILE_LOCK               "lock"
     48#define FILE_SOCKET             "socket"
    4749#define FILE_PREFS              "prefs"
    4850#define FILE_PREFS_TMP          "prefs.tmp"
     
    5860static int
    5961lockfile(const char *file, char **errstr);
     62static void
     63cf_removelocks(void);
    6064static gboolean
    6165writefile_traverse(gpointer key, gpointer value, gpointer data);
     
    6367getstateval(struct cf_torrentstate *state, char *line);
    6468
    65 static char *confdir = NULL;
    66 static char *old_confdir = NULL;
    67 static GTree *prefs = NULL;
    68 
     69static char *gl_confdir = NULL;
     70static char *gl_old_confdir = NULL;
     71static GTree *gl_prefs = NULL;
     72static char *gl_lockpath = NULL;
     73static char *gl_old_lockpath = NULL;
     74
     75/* errstr may be NULL, this might be called before GTK is initialized */
    6976static int
    7077lockfile(const char *file, char **errstr) {
     
    7279  struct flock lk;
    7380
    74   *errstr = NULL;
     81  if(NULL != errstr)
     82    *errstr = NULL;
    7583
    7684  if(0 > (fd = open(file, O_RDWR | O_CREAT, 0666))) {
    7785    savederr = errno;
    78     *errstr = g_strdup_printf(_("Failed to open the file %s for writing:\n%s"),
    79       file, strerror(errno));
     86    if(NULL != errstr)
     87      *errstr = g_strdup_printf(_("Failed to open the file %s for writing:\n%s"),
     88                                file, strerror(errno));
    8089    errno = savederr;
    8190    return -1;
     
    8998  if(-1 == fcntl(fd, F_SETLK, &lk)) {
    9099    savederr = errno;
    91     if(EAGAIN == errno)
    92       *errstr = g_strdup_printf(_("Another copy of %s is already running."),
    93                                 g_get_application_name());
    94     else
    95       *errstr = g_strdup_printf(_("Failed to lock the file %s:\n%s"),
    96         file, strerror(errno));
     100    if(NULL != errstr) {
     101      if(EAGAIN == errno)
     102        *errstr = g_strdup_printf(_("Another copy of %s is already running."),
     103                                  g_get_application_name());
     104      else
     105        *errstr = g_strdup_printf(_("Failed to lock the file %s:\n%s"),
     106                                  file, strerror(errno));
     107    }
    97108    close(fd);
    98109    errno = savederr;
     
    103114}
    104115
     116/* errstr may be NULL, this might be called before GTK is initialized */
    105117gboolean
    106118cf_init(const char *dir, char **errstr) {
    107   *errstr = NULL;
    108   old_confdir = g_strdup(dir);
    109   confdir = g_build_filename(dir, CONF_SUBDIR, NULL);
    110 
    111   if(mkdir_p(confdir, 0777))
     119  if(NULL != errstr)
     120    *errstr = NULL;
     121  gl_old_confdir = g_strdup(dir);
     122  gl_confdir = g_build_filename(dir, CONF_SUBDIR, NULL);
     123
     124  if(mkdir_p(gl_confdir, 0777))
    112125    return TRUE;
    113126
    114   *errstr = g_strdup_printf(_("Failed to create the directory %s:\n%s"),
    115                             confdir, strerror(errno));
     127  if(NULL != errstr)
     128    *errstr = g_strdup_printf(_("Failed to create the directory %s:\n%s"),
     129                              gl_confdir, strerror(errno));
    116130  return FALSE;
    117131}
    118132
     133/* errstr may be NULL, this might be called before GTK is initialized */
    119134gboolean
    120135cf_lock(char **errstr) {
    121   char *path = g_build_filename(old_confdir, OLD_FILE_LOCK, NULL);
     136  char *path = g_build_filename(gl_old_confdir, OLD_FILE_LOCK, NULL);
    122137  int fd = lockfile(path, errstr);
    123138
    124   if(0 <= fd) {
     139  if(0 > fd)
    125140    g_free(path);
    126     path = g_build_filename(confdir, FILE_LOCK, NULL);
     141  else {
     142    gl_old_lockpath = path;
     143    path = g_build_filename(gl_confdir, FILE_LOCK, NULL);
    127144    fd = lockfile(path, errstr);
    128   }
    129 
    130   g_free(path);
     145    if(0 > fd)
     146      g_free(path);
     147    else
     148      gl_lockpath = path;
     149  }
     150
     151  g_atexit(cf_removelocks);
     152
    131153  return 0 <= fd;
     154}
     155
     156static void
     157cf_removelocks(void) {
     158  if(NULL != gl_lockpath) {
     159    unlink(gl_lockpath);
     160    g_free(gl_lockpath);
     161  }
     162
     163  if(NULL != gl_old_lockpath) {
     164    unlink(gl_old_lockpath);
     165    g_free(gl_old_lockpath);
     166  }
     167}
     168
     169char *
     170cf_sockname(void) {
     171  return g_build_filename(gl_confdir, FILE_SOCKET, NULL);
    132172}
    133173
    134174gboolean
    135175cf_loadprefs(char **errstr) {
    136   char *path = g_build_filename(confdir, FILE_PREFS, NULL);
     176  char *path = g_build_filename(gl_confdir, FILE_PREFS, NULL);
    137177  char *oldpath;
    138178  GIOChannel *io;
     
    144184  *errstr = NULL;
    145185
    146   if(NULL != prefs)
    147     g_tree_destroy(prefs);
    148 
    149   prefs = g_tree_new_full((GCompareDataFunc)g_ascii_strcasecmp, NULL,
     186  if(NULL != gl_prefs)
     187    g_tree_destroy(gl_prefs);
     188
     189  gl_prefs = g_tree_new_full((GCompareDataFunc)g_ascii_strcasecmp, NULL,
    150190                          g_free, g_free);
    151191
     
    159199      g_error_free(err);
    160200      err = NULL;
    161       oldpath = g_build_filename(old_confdir, OLD_FILE_PREFS, NULL);
     201      oldpath = g_build_filename(gl_old_confdir, OLD_FILE_PREFS, NULL);
    162202      io = g_io_channel_new_file(oldpath, "r", &err);
    163203      g_free(oldpath);
     
    182222            *sep = '\0';
    183223            line[termpos] = '\0';
    184             g_tree_insert(prefs, g_strcompress(line), g_strcompress(sep + 1));
     224            g_tree_insert(gl_prefs, g_strcompress(line), g_strcompress(sep + 1));
    185225          }
    186226          g_free(line);
     
    206246const char *
    207247cf_getpref(const char *name) {
    208   assert(NULL != prefs);
    209 
    210   return g_tree_lookup(prefs, name);
     248  assert(NULL != gl_prefs);
     249
     250  return g_tree_lookup(gl_prefs, name);
    211251}
    212252
    213253void
    214254cf_setpref(const char *name, const char *value) {
    215   assert(NULL != prefs);
    216 
    217   g_tree_insert(prefs, g_strdup(name), g_strdup(value));
     255  assert(NULL != gl_prefs);
     256
     257  g_tree_insert(gl_prefs, g_strdup(name), g_strdup(value));
    218258}
    219259
     
    225265gboolean
    226266cf_saveprefs(char **errstr) {
    227   char *file = g_build_filename(confdir, FILE_PREFS, NULL);
    228   char *tmpfile = g_build_filename(confdir, FILE_PREFS_TMP, NULL);
     267  char *file = g_build_filename(gl_confdir, FILE_PREFS, NULL);
     268  char *tmpfile = g_build_filename(gl_confdir, FILE_PREFS_TMP, NULL);
    229269  GIOChannel *io = NULL;
    230270  struct writeinfo info;
    231271  int fd;
    232272
    233   assert(NULL != prefs);
     273  assert(NULL != gl_prefs);
    234274  assert(NULL != errstr);
    235275
     
    255295  info.io = io;
    256296  info.err = NULL;
    257   g_tree_foreach(prefs, writefile_traverse, &info);
     297  g_tree_foreach(gl_prefs, writefile_traverse, &info);
    258298  if(NULL != info.err ||
    259299     G_IO_STATUS_ERROR == g_io_channel_shutdown(io, TRUE, &info.err)) {
     
    313353GList *
    314354cf_loadstate(char **errstr) {
    315   char *path = g_build_filename(confdir, FILE_STATE, NULL);
     355  char *path = g_build_filename(gl_confdir, FILE_STATE, NULL);
    316356  char *oldpath;
    317357  GIOChannel *io;
     
    332372      g_error_free(err);
    333373      err = NULL;
    334       oldpath = g_build_filename(old_confdir, OLD_FILE_STATE, NULL);
     374      oldpath = g_build_filename(gl_old_confdir, OLD_FILE_STATE, NULL);
    335375      io = g_io_channel_new_file(oldpath, "r", &err);
    336376      g_free(oldpath);
     
    433473gboolean
    434474cf_savestate(GList *torrents, char **errstr) {
    435   char *file = g_build_filename(confdir, FILE_STATE, NULL);
    436   char *tmpfile = g_build_filename(confdir, FILE_STATE_TMP, NULL);
     475  char *file = g_build_filename(gl_confdir, FILE_STATE, NULL);
     476  char *tmpfile = g_build_filename(gl_confdir, FILE_STATE_TMP, NULL);
    437477  GIOChannel *io = NULL;
    438478  GError *err;
  • trunk/gtk/conf.h

    r162 r242  
    4040gboolean
    4141cf_lock(char **errstr);
     42char *
     43cf_sockname(void);
    4244gboolean
    4345cf_loadprefs(char **errstr);
  • trunk/gtk/dialogs.h

    r232 r242  
    2929
    3030#include "transmission.h"
     31#include "util.h"
    3132
    3233/* macros for names of prefs we use */
     
    4344#define DEF_UPLIMIT             20
    4445#define DEF_USEUPLIMIT          TRUE
    45 
    46 typedef gboolean (*add_torrent_func_t)(void *, const char *, const char *, gboolean, GList **);
    47 typedef void (*torrents_added_func_t)(void *);
    4846
    4947void
  • trunk/gtk/main.c

    r162 r242  
    4343#include "conf.h"
    4444#include "dialogs.h"
     45#include "ipc.h"
    4546#include "transmission.h"
    4647#include "trcellrenderertorrent.h"
     
    7071};
    7172
     73GList *
     74readargs(int argc, char **argv);
     75
    7276void
    7377maketypes(void);
     
    7882
    7983void
    80 makewind(GtkWidget *wind, tr_handle_t *tr, GList *saved);
     84makewind(GtkWidget *wind, tr_handle_t *tr, GList *saved, GList *args);
    8185GtkWidget *
    8286makewind_toolbar(struct cbdata *data);
     
    141145void
    142146maketorrentlist(tr_torrent_t *tor, void *data);
     147void
     148safepipe(void);
    143149void
    144150setupsighandlers(void);
     
    193199  const char *pref;
    194200  long intval;
     201  GList *argfiles;
     202  gboolean didinit, didlock;
     203
     204  safepipe();
     205
     206  argfiles = readargs(argc, argv);
     207
     208  didinit = cf_init(tr_getPrefsDirectory(), NULL);
     209  didlock = FALSE;
     210  if(NULL != argfiles && didinit && !(didlock = cf_lock(NULL)))
     211    return !ipc_sendfiles_blocking(argfiles);
    195212
    196213  setupsighandlers();
     
    213230    "widget \"TransmissionDialog\" style \"transmission-standard\"\n");
    214231
    215   if(cf_init(tr_getPrefsDirectory(), &err)) {
    216     if(cf_lock(&err)) {
     232  if(didinit || cf_init(tr_getPrefsDirectory(), &err)) {
     233    if(didlock || cf_lock(&err)) {
    217234      /* create main window now so any error dialogs can be it's children */
    218235      mainwind = gtk_window_new(GTK_WINDOW_TOPLEVEL);
     
    239256
    240257      maketypes();
    241       makewind(mainwind, tr, saved);
     258      makewind(mainwind, tr, saved, argfiles);
    242259
    243260      if(NULL != preferr)
     
    256273  }
    257274
     275  if(NULL != argfiles)
     276    freestrlist(argfiles);
     277
    258278  gtk_main();
    259279
    260280  return 0;
     281}
     282
     283GList *
     284readargs(int argc, char **argv) {
     285  while(0 < --argc) {
     286    argv++;
     287    if(0 == strcmp("--", *argv))
     288      return checkfilenames(argc - 1, argv + 1);
     289    else if('-' != argv[0][0])
     290      return checkfilenames(argc, argv);
     291  }
     292
     293  return NULL;
    261294}
    262295
     
    278311
    279312void
    280 makewind(GtkWidget *wind, tr_handle_t *tr, GList *saved) {
     313makewind(GtkWidget *wind, tr_handle_t *tr, GList *saved, GList *args) {
    281314  GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
    282315  GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL);
     
    327360  g_list_free(saved);
    328361
     362  for(ii = g_list_first(args); NULL != ii; ii = ii->next)
     363    addtorrent(data, ii->data, NULL, FALSE, &loaderrs);
     364
    329365  if(NULL != loaderrs) {
    330366    str = joinstrlist(loaderrs, "\n");
     
    354390
    355391  gtk_widget_show(wind);
     392
     393  ipc_socket_setup(GTK_WINDOW(wind), addtorrent, addedtorrents, data);
    356394}
    357395
     
    11941232
    11951233void
     1234safepipe(void) {
     1235  struct sigaction sa;
     1236
     1237  bzero(&sa, sizeof(sa));
     1238  sa.sa_handler = SIG_IGN;
     1239  sigaction(SIGPIPE, &sa, NULL);
     1240}
     1241
     1242void
    11961243setupsighandlers(void) {
    11971244  int sigs[] = {SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGUSR2};
  • trunk/gtk/util.c

    r162 r242  
    3131#include <stdarg.h>
    3232#include <string.h>
     33#include <unistd.h>
    3334
    3435#include <gtk/gtk.h>
     
    9495  ratio = (double)up / (double)down;
    9596
    96   return g_strdup_printf("%.*f", (10.0 > ratio ? 2 : (100.0 > ratio ? 1 : 0)),
    97                          ratio);
     97  return g_strdup_printf("%.*f", BESTDECIMAL(ratio), ratio);
    9898}
    9999
     
    145145
    146146  return ret;
     147}
     148
     149void
     150freestrlist(GList *list) {
     151  GList *ii;
     152
     153  if(NULL != list) {
     154    for(ii = g_list_first(list); NULL != ii; ii = ii->next)
     155      g_free(ii->data);
     156    g_list_free(list);
     157  }
    147158}
    148159
     
    184195}
    185196
     197GList *
     198checkfilenames(int argc, char **argv) {
     199  char *pwd = g_get_current_dir();
     200  int ii, cd;
     201  char *dirstr, *filestr;
     202  GList *ret = NULL;
     203
     204  for(ii = 0; ii < argc; ii++) {
     205    dirstr = g_path_get_dirname(argv[ii]);
     206    if(!g_path_is_absolute(argv[ii])) {
     207      filestr = g_build_filename(pwd, dirstr, NULL);
     208      g_free(dirstr);
     209      dirstr = filestr;
     210    }
     211    cd = chdir(dirstr);
     212    g_free(dirstr);
     213    if(0 > cd)
     214      continue;
     215    dirstr = g_get_current_dir();
     216    filestr = g_path_get_basename(argv[ii]);
     217    ret = g_list_append(ret, g_build_filename(dirstr, filestr, NULL));
     218    g_free(dirstr);
     219    g_free(filestr);
     220  }
     221
     222  chdir(pwd);
     223  g_free(pwd);
     224
     225  return ret;
     226}
     227
    186228GtkWidget *
    187229errmsg(GtkWindow *wind, const char *format, ...) {
  • trunk/gtk/util.h

    r162 r242  
    3838#endif
    3939
     40typedef gboolean (*add_torrent_func_t)(void *, const char *, const char *, gboolean, GList **);
     41typedef void (*torrents_added_func_t)(void *);
     42
    4043/* return number of items in array */
    4144#define ALEN(a)                 (sizeof(a) / sizeof((a)[0]))
     
    6770joinstrlist(GList *list, char *sep);
    6871
     72/* free a GList of strings */
     73void
     74freestrlist(GList *list);
     75
    6976/* decodes a string that has been urlencoded */
    7077char *
    7178urldecode(const char *str, int len);
     79
     80/* return a list of cleaned-up paths, with invalid directories removed */
     81GList *
     82checkfilenames(int argc, char **argv);
     83
     84#ifdef GTK_MAJOR_VERSION
    7285
    7386/* if wind is NULL then you must call gtk_widget_show on the returned widget */
     
    92105        const char *format, va_list ap);
    93106
     107#endif /* GTK_MAJOR_VERSION */
     108
    94109#endif /* TG_UTIL_H */
Note: See TracChangeset for help on using the changeset viewer.