diff options
| author | 2018-04-25 18:07:30 -0400 | |
|---|---|---|
| committer | 2018-04-25 18:07:30 -0400 | |
| commit | 9b1b081cfdb1c0fb6457278775e0823f8bc10f62 (patch) | |
| tree | ce8840148d8445055ba9e4f12263b2208f234c16 /src/lib/arch/unix/ArchDaemonUnix.cpp | |
Import Upstream version 2.0.0+dfsgupstream/2.0.0+dfsg
Diffstat (limited to 'src/lib/arch/unix/ArchDaemonUnix.cpp')
| -rw-r--r-- | src/lib/arch/unix/ArchDaemonUnix.cpp | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/lib/arch/unix/ArchDaemonUnix.cpp b/src/lib/arch/unix/ArchDaemonUnix.cpp new file mode 100644 index 0000000..a03bf7a --- /dev/null +++ b/src/lib/arch/unix/ArchDaemonUnix.cpp @@ -0,0 +1,132 @@ +/* + * barrier -- mouse and keyboard sharing utility + * Copyright (C) 2012-2016 Symless Ltd. + * Copyright (C) 2002 Chris Schoeneman + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "arch/unix/ArchDaemonUnix.h" + +#include "arch/unix/XArchUnix.h" +#include "base/Log.h" + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <cstdlib> + +// +// ArchDaemonUnix +// + +ArchDaemonUnix::ArchDaemonUnix() +{ + // do nothing +} + +ArchDaemonUnix::~ArchDaemonUnix() +{ + // do nothing +} + + +#ifdef __APPLE__ + +// In Mac OS X, fork()'d child processes can't use most APIs (the frameworks +// that Barrier uses in fact prevent it and make the process just up and die), +// so need to exec a copy of the program that doesn't fork so isn't limited. +int +execSelfNonDaemonized() +{ + extern char** NXArgv; + char** selfArgv = NXArgv; + + setenv("_BARRIER_DAEMONIZED", "", 1); + + execvp(selfArgv[0], selfArgv); + return 0; +} + +bool alreadyDaemonized() { + return getenv("_BARRIER_DAEMONIZED") != NULL; +} + +#endif + +int +ArchDaemonUnix::daemonize(const char* name, DaemonFunc func) +{ +#ifdef __APPLE__ + if (alreadyDaemonized()) + return func(1, &name); +#endif + + // fork so shell thinks we're done and so we're not a process + // group leader + switch (fork()) { + case -1: + // failed + throw XArchDaemonFailed(new XArchEvalUnix(errno)); + + case 0: + // child + break; + + default: + // parent exits + exit(0); + } + + // become leader of a new session + setsid(); + +#ifndef __APPLE__ + // NB: don't run chdir on apple; causes strange behaviour. + // chdir to root so we don't keep mounted filesystems points busy + // TODO: this is a bit of a hack - can we find a better solution? + int chdirErr = chdir("/"); + if (chdirErr) + // NB: file logging actually isn't working at this point! + LOG((CLOG_ERR "chdir error: %i", chdirErr)); +#endif + + // mask off permissions for any but owner + umask(077); + + // close open files. we only expect stdin, stdout, stderr to be open. + close(0); + close(1); + close(2); + + // attach file descriptors 0, 1, 2 to /dev/null so inadvertent use + // of standard I/O safely goes in the bit bucket. + open("/dev/null", O_RDONLY); + open("/dev/null", O_RDWR); + + int dupErr = dup(1); + + if (dupErr < 0) { + // NB: file logging actually isn't working at this point! + LOG((CLOG_ERR "dup error: %i", dupErr)); + } + +#ifdef __APPLE__ + return execSelfNonDaemonized(); +#endif + + // invoke function + return func(1, &name); +} |
