The method of choice for IPC in our case is a unix socket because it has very
little overhead on both sides and is usually available without headaches in
most languages. In the default configuration file, the ipc-socket gets created
-in +/tmp/i3-%u/ipc-socket.%p+ where +%u+ is your UNIX username and +%p+ is the
-PID of i3. You can get the socketpath from i3 by calling +i3 --get-socketpath+.
+in +/tmp/i3-%u.XXXXXX/ipc-socket.%p+ where +%u+ is your UNIX username, +%p+ is
+the PID of i3 and XXXXXX is a string of random characters from the portable
+filename character set (see mkdtemp(3)). You can get the socketpath from i3 by
+calling +i3 --get-socketpath+.
All i3 utilities, like +i3-msg+ and +i3-input+ will read the +I3_SOCKET_PATH+
X11 property, stored on the X11 root window.
(to display a workspace bar), and to control i3.
The IPC socket is enabled by default and will be created in
-+/tmp/i3-%u/ipc-socket.%p+ where +%u+ is your UNIX username and +%p+ is the PID
-of i3.
++/tmp/i3-%u.XXXXXX/ipc-socket.%p+ where +%u+ is your UNIX username, +%p+ is
+the PID of i3 and XXXXXX is a string of random characters from the portable
+filename character set (see mkdtemp(3)).
You can override the default path through the environment-variable +I3SOCK+ or
by specifying the +ipc-socket+ directive. This is discouraged, though, since i3
-does the right thing by default.
+does the right thing by default. If you decide to change it, it is strongly
+recommended to set this to a location in your home directory so that no other
+user can create that directory.
*Examples*:
----------------------------
-ipc-socket /tmp/i3-ipc.sock
+ipc-socket ~/.i3/i3-ipc.sock
----------------------------
You can then use the +i3-msg+ application to perform any command listed in
=== I3SOCK
This variable overwrites the IPC socket path (placed in
-/tmp/i3-%u/ipc-socket.%p by default, where %u is replaced with your UNIX
-username and %p is replaced with i3’s PID). The IPC socket is used by external
-programs like i3-msg(1) or i3bar(1).
+/tmp/i3-%u.XXXXXX/ipc-socket.%p by default, where %u is replaced with your UNIX
+username, %p is replaced with i3’s PID and XXXXXX is a string of random
+characters from the portable filename character set (see mkdtemp(3))). The IPC
+socket is used by external programs like i3-msg(1) or i3bar(1).
== TODO
*
*/
char *get_process_filename(const char *prefix) {
- char *dir = getenv("XDG_RUNTIME_DIR");
+ /* dir stores the directory path for this and all subsequent calls so that
+ * we only create a temporary directory once per i3 instance. */
+ static char *dir = NULL;
if (dir == NULL) {
- struct passwd *pw = getpwuid(getuid());
- const char *username = pw ? pw->pw_name : "unknown";
- sasprintf(&dir, "/tmp/i3-%s", username);
- } else {
- char *tmp;
- sasprintf(&tmp, "%s/i3", dir);
- dir = tmp;
- }
- if (!path_exists(dir)) {
- if (mkdir(dir, 0700) == -1) {
- perror("mkdir()");
- return NULL;
+ /* Check if XDG_RUNTIME_DIR is set. If so, we use XDG_RUNTIME_DIR/i3 */
+ if ((dir = getenv("XDG_RUNTIME_DIR"))) {
+ char *tmp;
+ sasprintf(&tmp, "%s/i3", dir);
+ dir = tmp;
+ if (!path_exists(dir)) {
+ if (mkdir(dir, 0700) == -1) {
+ perror("mkdir()");
+ return NULL;
+ }
+ }
+ } else {
+ /* If not, we create a (secure) temp directory using the template
+ * /tmp/i3-<user>.XXXXXX */
+ struct passwd *pw = getpwuid(getuid());
+ const char *username = pw ? pw->pw_name : "unknown";
+ sasprintf(&dir, "/tmp/i3-%s.XXXXXX", username);
+ /* mkdtemp modifies dir */
+ if (mkdtemp(dir) == NULL) {
+ perror("mkdtemp()");
+ return NULL;
+ }
}
}
char *filename;
sasprintf(&filename, "%s/%s.%d", dir, prefix, getpid());
- free(dir);
return filename;
}
# ensure XDG_RUNTIME_DIR is not set
delete $ENV{XDG_RUNTIME_DIR};
+
+# See which files exist in /tmp before to not mistakenly check an already
+# existing tmpdir of another i3 instance.
+my @files_before = </tmp/i3-*>;
my $pid = launch_with_config($config, 1);
+my @files_after = </tmp/i3-*>;
+@files_after = grep { !($_ ~~ @files_before) } @files_after;
+
+is(@files_after, 1, 'one new temp directory');
my $folder = "/tmp/i3-" . getpwuid(getuid());
+like($files_after[0], qr/^$folder/, 'temp directory matches expected pattern');
+$folder = $files_after[0];
+
ok(-d $folder, "folder $folder exists");
my $socketpath = "$folder/ipc-socket." . $pid;
ok(-S $socketpath, "file $socketpath exists and is a socket");