7

I use a drawing program called Inkscape, which has both a GUI and a command line interface. When used on the command line, it has a large number of options that can only be controlled through a user-specific config file, which is hardcoded to be:

$HOME/.config/inkscape/preferences.xml

This config file always contains the options that were most recently used in the GUI, which may be the wrong ones when I'm scripting.

To work around this, I have my script save a copy of the config file, replace it with a standard config file, run the program, and then copy the saved config file back.

This works OK but is not really clean. For example, it won't work properly if two instances of the script are being run concurrently.

On Unix, is there a cleaner way to carry out this task of faking out a program so it takes its config file from someplace that I want, rather than from the pathname hardcoded in the program? Maybe something involving links, or something like BSD jails?

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175

4 Answers4

8

Inkscape has a feature for this as of 0.47:

$ INKSCAPE_PORTABLE_PROFILE_DIR=/some/other/path inkscape --args

Put your script's custom preferences.xml file in /some/other/path. It should be a dedicated directory, because Inkscape will populate it with all the other files it normally puts in ~/.config/Inkscape when you run it like this.

Warren Young
  • 71,107
  • 16
  • 178
  • 168
  • So you can run multiple versions simply by giving the a different variable prior to running, right? Good sluething BTW! – slm Nov 02 '13 at 04:04
  • 1
    @slm: Yes. Here, the environment variable is being used more like a command line option, as it affects just the single instance being run. And I found it by reading the source. :) – Warren Young Nov 02 '13 at 04:14
  • related: https://bugs.launchpad.net/inkscape/+bug/1247448 –  Nov 02 '13 at 18:22
  • @BenCrowell - thanks, I left a comment mentioning that the existence of that hidden env. variable in the official docs would've saved you and us a whole bunch of time. – slm Nov 09 '13 at 22:18
6

Because Inkscape is FOSS software, we can just add an option to the program which will let you pass the name of another config file, like so:

=== modified file 'src/inkscape.cpp'
--- src/inkscape.cpp    2013-09-28 19:20:27 +0000
+++ src/inkscape.cpp    2013-11-02 04:07:45 +0000
@@ -1443,6 +1443,12 @@
             prefdir = g_strdup(val);
         }

+        // Also accept an override via the command line
+        extern gchar* sp_preferences;
+        if (sp_preferences) {
+            prefdir = sp_preferences;
+        }
+
 #ifdef HAS_SHGetSpecialFolderLocation
         // prefer c:\Documents and Settings\UserName\Application Data\ to
         // c:\Documents and Settings\userName\;

=== modified file 'src/main.cpp'
--- src/main.cpp    2013-09-24 18:31:44 +0000
+++ src/main.cpp    2013-11-02 04:05:30 +0000
@@ -179,6 +179,7 @@
     SP_ARG_VERB_LIST,
     SP_ARG_VERB,
     SP_ARG_SELECT,
+    SP_ARG_PREFERENCES,
     SP_ARG_LAST
 };

@@ -228,6 +229,7 @@
 static gboolean sp_query_all = FALSE;
 static gchar *sp_query_id = NULL;
 static gboolean sp_shell = FALSE;
+gchar *sp_preferences = NULL;
 static gboolean sp_vacuum_defs = FALSE;
 #ifdef WITH_DBUS
 static gboolean sp_dbus_listen = FALSE;
@@ -520,6 +522,11 @@
      N_("Start Inkscape in interactive shell mode."),
      NULL},

+    {"preferences", 0,
+     POPT_ARG_STRING, &sp_preferences, SP_ARG_PREFERENCES,
+     N_("Specify a different preferences.xml file."),
+     NULL},
+
     POPT_AUTOHELP POPT_TABLEEND
 };

I wouldn't expect the Inkscape developers to accept this patch, for two reasons. First, they've got an alternative feature with the same effect already. But second, I wouldn't expect them to like the way I made sp_preferences program-global instead of module-global. That sort of code is fine for a personal feature that you do not intend to be part of the mainline software, however.

The above patch may look fairly ugly to a non-programmer or one not familiar with C++ and patch files, but trust me, this is about as simple as changes to software get. It's only 10 lines of new code.

(If you do your own count and come up with 13 new lines, three of those are blank or have only a curly brace, so you don't include those in the SLOC count.)

Warren Young
  • 71,107
  • 16
  • 178
  • 168
  • Using an alternative config file should be a command line option, but inkscape does not seem to have this. Strange. – Faheem Mitha Oct 22 '15 at 15:33
  • @FaheemMitha: The Inkskape developers' choice to implement this [as an environment variable](http://unix.stackexchange.com/a/98513/138) is effectively the same thing. It's not wrong, just a different style choice. Still, if you prefer the command line option to the environment variable, you've got my patch now, which you can take as-is or build upon. – Warren Young Oct 22 '15 at 15:44
  • I think both choices are possible and can co-exist. – Faheem Mitha Oct 22 '15 at 15:51
1

You could use symbolic links. Put the config file you use with your GUI somewhere, lets call it GUI_CONFIG, and the one with scripts to SCRIPT_CONFIG. At the beginning of your script put the line:

ln -sf SCRIPT_CONFIG $HOME/.config/inkscape/preferences.xml

and at the end:

ln -sf GUI_CONFIG $HOME/.config/inkscape/preferences.xml

When the script executes it will make preferences.xml a symbolic link that points to the config it needs. When it finishes, it points it back at the one the GUI uses. Running multiple scripts concurrently won't destroy your config, as it does when copying temp files, though the first script completing will break the config file for still running scripts. It maybe best to put the calls to ln around the individual calls to Inkscape, rather than the scripts as a whole, to try to prevent these race conditions.

Another option would be to run Inkscape as a different user from scripts, so you can set it up with a different config file. However, you'll then have to deal with permissions, possibly by copying files back and forth to /tmp.

wingedsubmariner
  • 2,884
  • 1
  • 17
  • 21
  • 1
    This is scarcely better than copying files, and does nothing to actually solve the problem, which is that the current hard-coded path in Inkscape allows multiple programs to interfere with each other. – Warren Young Nov 02 '13 at 03:18
  • 1
    If you don't want to edit the `ln` option out of your answer, you should at least post the "other user" option as a separate answer. I could upvote that on its own, but not when tied to the `ln` answer. – Warren Young Nov 02 '13 at 03:19
  • 1
    The calls to `ln` are idempotent, so he doesn't have to worry about destroying his config files or leaving it in an undesired state after all processes have finished. It narrows the window for race conditions, and makes them less severe. – wingedsubmariner Nov 02 '13 at 03:45
1

Looking through the documentation for the preferences subsystem in Inkscape it isn't possbile.

Your options:

  1. do what your doing
  2. play games via linking the file
  3. user a different user ID
  4. modify the source (see @WarrenYoung's answer for this!)
slm
  • 363,520
  • 117
  • 767
  • 871
  • I don't see how you come to your first conclusion. That page tells me the program already has a way to pass a different path on Windows vs Linux. All you have to do is provide a third data source for the path, which gets it from the command line. If OP isn't a C programmer, find one. They're plentiful. :) – Warren Young Nov 02 '13 at 03:22
  • @WarrenYoung - well it's currently not a possibility as it stands on Linux, at least according to the docs. I didn't mean to imply the functionality wasn't buried in Inkscape and a modification to the source wouldn't be easy or possible, just that there were no switches currently avail. – slm Nov 02 '13 at 03:33
  • @WarrenYoung - are you volunteering to mods this for him? – slm Nov 02 '13 at 03:33
  • Would this even be a discussion if this were a config file in `/etc` instead of a C program? What's the essential difference? Is it just the fact that one edit is more difficult to make? If so, why does that affect whether my answer is an answer? – Warren Young Nov 02 '13 at 03:39
  • @WarrenYoung - I wasn't asking to be a smartass I was asking if you were willing. – slm Nov 02 '13 at 03:41
  • @WarrenYoung - I too can program in a variety of langs (C too) and it's different only b/c there is inherent overhead in being able to do this. Familiarity with how to build/rebuild and all that. It just is complicated esp. if you've never done it. I wasn't disagreeing w/ your answer it's as correct as the other recommendations. – slm Nov 02 '13 at 03:43
  • 1
    @WarrenYoung your answer certainly is a valid answer, but so would answering that OP should write a kernel module to allow bind mounts on a per-process basis so he can trick Inkspace into reading its config file from a different directory. Of course, if you code this feature into Inkscape for him you've gone well beyond the call fo duty :) – wingedsubmariner Nov 02 '13 at 03:43
  • @WarrenYoung - as winged has stated is kind of how I'd see it too. Unfortunately C and C++ are just not accessible to the masses. Not in the same way that modifying a shell script or what not. – slm Nov 02 '13 at 03:46
  • Fine. I'm modifying Inkscape's source code right now. Expect a patch in my answer soon/ – Warren Young Nov 02 '13 at 04:03
  • @WarrenYoung - you are a very nice person for doing this!!! – slm Nov 02 '13 at 04:13
  • I wasn't trying to be a smartass above. I honestly don't think my patch above was difficult. The skills I used in making it aren't rare. The hard part will be rebuilding Inkscape after applying the patch. – Warren Young Nov 02 '13 at 04:33
  • @WarrenYoung - I've seen you on the site enough to know you weren't being a smartass, I wasn't sure if you thought I was 8-). I agree that ppl should be able to what you did, but given the range of Q's i answer here on a daily basis, I"m not surprised either that ppl either don't know how or don't know where to even start. Things are easy (easier?) when you've done them before. Also don't underestimate the skill it took to do what you did too!!! – slm Nov 02 '13 at 04:44