contrib/chg/chg.c
author Jun Wu <quark@fb.com>
Tue, 16 Feb 2016 11:08:52 +0000
changeset 28196 87de4a22e8c2
parent 28194 7623ba92af72
child 28237 a3d73e069f8d
permissions -rw-r--r--
chg: hold a lock file before connected to server This is a part of the one server per config series. In multiple-server setup, multiple clients may try to start different servers (on demand) at the same time. The old lock will not guarantee a client to connect to the server it just started, and is not crash friendly. This patch addressed above issues by using flock and does not release the lock until the client actually connects to the server or times out.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     1
/*
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     2
 * A fast client for Mercurial command server
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     3
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     4
 * Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     5
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     6
 * This software may be used and distributed according to the terms of the
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     7
 * GNU General Public License version 2 or any later version.
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     8
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     9
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    10
#include <assert.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    11
#include <errno.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    12
#include <fcntl.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    13
#include <signal.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    14
#include <stdio.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    15
#include <stdlib.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    16
#include <string.h>
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
    17
#include <sys/file.h>
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    18
#include <sys/stat.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    19
#include <sys/types.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    20
#include <sys/un.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    21
#include <sys/wait.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    22
#include <time.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    23
#include <unistd.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    24
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    25
#include "hgclient.h"
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    26
#include "util.h"
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    27
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    28
#ifndef UNIX_PATH_MAX
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    29
#define UNIX_PATH_MAX (sizeof(((struct sockaddr_un *)NULL)->sun_path))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    30
#endif
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    31
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    32
struct cmdserveropts {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    33
	char sockname[UNIX_PATH_MAX];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    34
	char lockfile[UNIX_PATH_MAX];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    35
	char pidfile[UNIX_PATH_MAX];
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    36
	size_t argsize;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    37
	const char **args;
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
    38
	int lockfd;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    39
};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    40
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    41
static void initcmdserveropts(struct cmdserveropts *opts) {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    42
	memset(opts, 0, sizeof(struct cmdserveropts));
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
    43
	opts->lockfd = -1;
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    44
}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    45
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    46
static void freecmdserveropts(struct cmdserveropts *opts) {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    47
	free(opts->args);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    48
	opts->args = NULL;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    49
	opts->argsize = 0;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    50
}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    51
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    52
/*
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    53
 * Test if an argument is a sensitive flag that should be passed to the server.
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    54
 * Return 0 if not, otherwise the number of arguments starting from the current
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    55
 * one that should be passed to the server.
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    56
 */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    57
static size_t testsensitiveflag(const char *arg)
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    58
{
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    59
	static const struct {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    60
		const char *name;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    61
		size_t narg;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    62
	} flags[] = {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    63
		{"--config", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    64
		{"--cwd", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    65
		{"--repo", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    66
		{"--repository", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    67
		{"--traceback", 0},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    68
		{"-R", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    69
	};
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    70
	size_t i;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    71
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i) {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    72
		size_t len = strlen(flags[i].name);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    73
		size_t narg = flags[i].narg;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    74
		if (memcmp(arg, flags[i].name, len) == 0) {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    75
			if (arg[len] == '\0') {  /* --flag (value) */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    76
				return narg + 1;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    77
			} else if (arg[len] == '=' && narg > 0) {  /* --flag=value */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    78
				return 1;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    79
			} else if (flags[i].name[1] != '-') {  /* short flag */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    80
				return 1;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    81
			}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    82
		}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    83
	}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    84
	return 0;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    85
}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    86
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    87
/*
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    88
 * Parse argv[] and put sensitive flags to opts->args
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    89
 */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    90
static void setcmdserverargs(struct cmdserveropts *opts,
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    91
			     int argc, const char *argv[])
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    92
{
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    93
	size_t i, step;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    94
	opts->argsize = 0;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    95
	for (i = 0, step = 1; i < (size_t)argc; i += step, step = 1) {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    96
		if (!argv[i])
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    97
			continue;  /* pass clang-analyse */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    98
		if (strcmp(argv[i], "--") == 0)
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    99
			break;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   100
		size_t n = testsensitiveflag(argv[i]);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   101
		if (n == 0 || i + n > (size_t)argc)
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   102
			continue;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   103
		opts->args = reallocx(opts->args,
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   104
				      (n + opts->argsize) * sizeof(char *));
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   105
		memcpy(opts->args + opts->argsize, argv + i,
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   106
		       sizeof(char *) * n);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   107
		opts->argsize += n;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   108
		step = n;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   109
	}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   110
}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   111
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   112
static void preparesockdir(const char *sockdir)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   113
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   114
	int r;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   115
	r = mkdir(sockdir, 0700);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   116
	if (r < 0 && errno != EEXIST)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   117
		abortmsg("cannot create sockdir %s (errno = %d)",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   118
			 sockdir, errno);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   119
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   120
	struct stat st;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   121
	r = lstat(sockdir, &st);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   122
	if (r < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   123
		abortmsg("cannot stat %s (errno = %d)", sockdir, errno);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   124
	if (!S_ISDIR(st.st_mode))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   125
		abortmsg("cannot create sockdir %s (file exists)", sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   126
	if (st.st_uid != geteuid() || st.st_mode & 0077)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   127
		abortmsg("insecure sockdir %s", sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   128
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   129
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   130
static void setcmdserveropts(struct cmdserveropts *opts)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   131
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   132
	int r;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   133
	char sockdir[UNIX_PATH_MAX];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   134
	const char *envsockname = getenv("CHGSOCKNAME");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   135
	if (!envsockname) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   136
		/* by default, put socket file in secure directory
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   137
		 * (permission of socket file may be ignored on some Unices) */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   138
		const char *tmpdir = getenv("TMPDIR");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   139
		if (!tmpdir)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   140
			tmpdir = "/tmp";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   141
		r = snprintf(sockdir, sizeof(sockdir), "%s/chg%d",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   142
			     tmpdir, geteuid());
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   143
		if (r < 0 || (size_t)r >= sizeof(sockdir))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   144
			abortmsg("too long TMPDIR (r = %d)", r);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   145
		preparesockdir(sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   146
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   147
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   148
	const char *basename = (envsockname) ? envsockname : sockdir;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   149
	const char *sockfmt = (envsockname) ? "%s" : "%s/server";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   150
	const char *lockfmt = (envsockname) ? "%s.lock" : "%s/lock";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   151
	const char *pidfmt = (envsockname) ? "%s.pid" : "%s/pid";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   152
	r = snprintf(opts->sockname, sizeof(opts->sockname), sockfmt, basename);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   153
	if (r < 0 || (size_t)r >= sizeof(opts->sockname))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   154
		abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   155
	r = snprintf(opts->lockfile, sizeof(opts->lockfile), lockfmt, basename);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   156
	if (r < 0 || (size_t)r >= sizeof(opts->lockfile))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   157
		abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   158
	r = snprintf(opts->pidfile, sizeof(opts->pidfile), pidfmt, basename);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   159
	if (r < 0 || (size_t)r >= sizeof(opts->pidfile))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   160
		abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   161
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   162
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   163
/*
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   164
 * Acquire a file lock that indicates a client is trying to start and connect
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   165
 * to a server, before executing a command. The lock is released upon exit or
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   166
 * explicit unlock. Will block if the lock is held by another process.
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   167
 */
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   168
static void lockcmdserver(struct cmdserveropts *opts)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   169
{
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   170
	if (opts->lockfd == -1) {
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   171
		opts->lockfd = open(opts->lockfile, O_RDWR | O_CREAT | O_NOFOLLOW, 0600);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   172
		if (opts->lockfd == -1)
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   173
			abortmsg("cannot create lock file %s", opts->lockfile);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   174
	}
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   175
	int r = flock(opts->lockfd, LOCK_EX);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   176
	if (r == -1)
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   177
		abortmsg("cannot acquire lock");
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   178
}
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   179
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   180
/*
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   181
 * Release the file lock held by calling lockcmdserver. Will do nothing if
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   182
 * lockcmdserver is not called.
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   183
 */
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   184
static void unlockcmdserver(struct cmdserveropts *opts)
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   185
{
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   186
	if (opts->lockfd == -1)
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   187
		return;
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   188
	flock(opts->lockfd, LOCK_UN);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   189
	close(opts->lockfd);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   190
	opts->lockfd = -1;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   191
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   192
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   193
static void execcmdserver(const struct cmdserveropts *opts)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   194
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   195
	const char *hgcmd = getenv("CHGHG");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   196
	if (!hgcmd || hgcmd[0] == '\0')
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   197
		hgcmd = getenv("HG");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   198
	if (!hgcmd || hgcmd[0] == '\0')
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   199
		hgcmd = "hg";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   200
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   201
	const char *baseargv[] = {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   202
		hgcmd,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   203
		"serve",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   204
		"--cwd", "/",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   205
		"--cmdserver", "chgunix",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   206
		"--address", opts->sockname,
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   207
		"--daemon-postexec", "none",
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   208
		"--pid-file", opts->pidfile,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   209
		"--config", "extensions.chgserver=",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   210
		/* wrap root ui so that it can be disabled/enabled by config */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   211
		"--config", "progress.assume-tty=1",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   212
	};
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   213
	size_t baseargvsize = sizeof(baseargv) / sizeof(baseargv[0]);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   214
	size_t argsize = baseargvsize + opts->argsize + 1;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   215
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   216
	const char **argv = mallocx(sizeof(char *) * argsize);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   217
	memcpy(argv, baseargv, sizeof(baseargv));
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   218
	memcpy(argv + baseargvsize, opts->args, sizeof(char *) * opts->argsize);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   219
	argv[argsize - 1] = NULL;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   220
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   221
	if (execvp(hgcmd, (char **)argv) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   222
		abortmsg("failed to exec cmdserver (errno = %d)", errno);
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   223
	free(argv);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   224
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   225
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   226
/* Retry until we can connect to the server. Give up after some time. */
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   227
static hgclient_t *retryconnectcmdserver(struct cmdserveropts *opts, pid_t pid)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   228
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   229
	static const struct timespec sleepreq = {0, 10 * 1000000};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   230
	int pst = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   231
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   232
	for (unsigned int i = 0; i < 10 * 100; i++) {
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   233
		hgclient_t *hgc = hgc_open(opts->sockname);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   234
		if (hgc)
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   235
			return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   236
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   237
		if (pid > 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   238
			/* collect zombie if child process fails to start */
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   239
			int r = waitpid(pid, &pst, WNOHANG);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   240
			if (r != 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   241
				goto cleanup;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   242
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   243
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   244
		nanosleep(&sleepreq, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   245
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   246
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   247
	abortmsg("timed out waiting for cmdserver %s", opts->sockname);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   248
	return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   249
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   250
cleanup:
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   251
	if (WIFEXITED(pst)) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   252
		abortmsg("cmdserver exited with status %d", WEXITSTATUS(pst));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   253
	} else if (WIFSIGNALED(pst)) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   254
		abortmsg("cmdserver killed by signal %d", WTERMSIG(pst));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   255
	} else {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   256
		abortmsg("error white waiting cmdserver");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   257
	}
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   258
	return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   259
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   260
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   261
/* Connect to a cmdserver. Will start a new server on demand. */
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   262
static hgclient_t *connectcmdserver(struct cmdserveropts *opts)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   263
{
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   264
	hgclient_t *hgc = hgc_open(opts->sockname);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   265
	if (hgc)
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   266
		return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   267
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   268
	lockcmdserver(opts);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   269
	hgc = hgc_open(opts->sockname);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   270
	if (hgc) {
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   271
		unlockcmdserver(opts);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   272
		debugmsg("cmdserver is started by another process");
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   273
		return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   274
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   275
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   276
	debugmsg("start cmdserver at %s", opts->sockname);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   277
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   278
	pid_t pid = fork();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   279
	if (pid < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   280
		abortmsg("failed to fork cmdserver process");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   281
	if (pid == 0) {
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   282
		/* do not leak lockfd to hg */
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   283
		close(opts->lockfd);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   284
		/* bypass uisetup() of pager extension */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   285
		int nullfd = open("/dev/null", O_WRONLY);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   286
		if (nullfd >= 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   287
			dup2(nullfd, fileno(stdout));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   288
			close(nullfd);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   289
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   290
		execcmdserver(opts);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   291
	} else {
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   292
		hgc = retryconnectcmdserver(opts, pid);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   293
	}
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   294
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   295
	unlockcmdserver(opts);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   296
	return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   297
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   298
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   299
static void killcmdserver(const struct cmdserveropts *opts, int sig)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   300
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   301
	FILE *fp = fopen(opts->pidfile, "r");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   302
	if (!fp)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   303
		abortmsg("cannot open %s (errno = %d)", opts->pidfile, errno);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   304
	int pid = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   305
	int n = fscanf(fp, "%d", &pid);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   306
	fclose(fp);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   307
	if (n != 1 || pid <= 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   308
		abortmsg("cannot read pid from %s", opts->pidfile);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   309
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   310
	if (kill((pid_t)pid, sig) < 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   311
		if (errno == ESRCH)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   312
			return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   313
		abortmsg("cannot kill %d (errno = %d)", pid, errno);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   314
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   315
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   316
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   317
static pid_t peerpid = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   318
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   319
static void forwardsignal(int sig)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   320
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   321
	assert(peerpid > 0);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   322
	if (kill(peerpid, sig) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   323
		abortmsg("cannot kill %d (errno = %d)", peerpid, errno);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   324
	debugmsg("forward signal %d", sig);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   325
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   326
28086
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   327
static void handlestopsignal(int sig)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   328
{
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   329
	sigset_t unblockset, oldset;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   330
	struct sigaction sa, oldsa;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   331
	if (sigemptyset(&unblockset) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   332
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   333
	if (sigaddset(&unblockset, sig) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   334
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   335
	memset(&sa, 0, sizeof(sa));
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   336
	sa.sa_handler = SIG_DFL;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   337
	sa.sa_flags = SA_RESTART;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   338
	if (sigemptyset(&sa.sa_mask) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   339
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   340
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   341
	forwardsignal(sig);
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   342
	if (raise(sig) < 0)  /* resend to self */
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   343
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   344
	if (sigaction(sig, &sa, &oldsa) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   345
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   346
	if (sigprocmask(SIG_UNBLOCK, &unblockset, &oldset) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   347
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   348
	/* resent signal will be handled before sigprocmask() returns */
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   349
	if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   350
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   351
	if (sigaction(sig, &oldsa, NULL) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   352
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   353
	return;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   354
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   355
error:
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   356
	abortmsg("failed to handle stop signal (errno = %d)", errno);
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   357
}
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   358
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   359
static void setupsignalhandler(pid_t pid)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   360
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   361
	if (pid <= 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   362
		return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   363
	peerpid = pid;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   364
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   365
	struct sigaction sa;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   366
	memset(&sa, 0, sizeof(sa));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   367
	sa.sa_handler = forwardsignal;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   368
	sa.sa_flags = SA_RESTART;
28085
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   369
	if (sigemptyset(&sa.sa_mask) < 0)
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   370
		goto error;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   371
28085
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   372
	if (sigaction(SIGHUP, &sa, NULL) < 0)
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   373
		goto error;
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   374
	if (sigaction(SIGINT, &sa, NULL) < 0)
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   375
		goto error;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   376
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   377
	/* terminate frontend by double SIGTERM in case of server freeze */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   378
	sa.sa_flags |= SA_RESETHAND;
28085
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   379
	if (sigaction(SIGTERM, &sa, NULL) < 0)
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   380
		goto error;
28086
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   381
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   382
	/* propagate job control requests to worker */
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   383
	sa.sa_handler = forwardsignal;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   384
	sa.sa_flags = SA_RESTART;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   385
	if (sigaction(SIGCONT, &sa, NULL) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   386
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   387
	sa.sa_handler = handlestopsignal;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   388
	sa.sa_flags = SA_RESTART;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   389
	if (sigaction(SIGTSTP, &sa, NULL) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   390
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   391
28085
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   392
	return;
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   393
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   394
error:
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   395
	abortmsg("failed to set up signal handlers (errno = %d)", errno);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   396
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   397
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   398
/* This implementation is based on hgext/pager.py (pre 369741ef7253) */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   399
static void setuppager(hgclient_t *hgc, const char *const args[],
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   400
		       size_t argsize)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   401
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   402
	const char *pagercmd = hgc_getpager(hgc, args, argsize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   403
	if (!pagercmd)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   404
		return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   405
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   406
	int pipefds[2];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   407
	if (pipe(pipefds) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   408
		return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   409
	pid_t pid = fork();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   410
	if (pid < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   411
		goto error;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   412
	if (pid == 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   413
		close(pipefds[0]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   414
		if (dup2(pipefds[1], fileno(stdout)) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   415
			goto error;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   416
		if (isatty(fileno(stderr))) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   417
			if (dup2(pipefds[1], fileno(stderr)) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   418
				goto error;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   419
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   420
		close(pipefds[1]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   421
		hgc_attachio(hgc);  /* reattach to pager */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   422
		return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   423
	} else {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   424
		dup2(pipefds[0], fileno(stdin));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   425
		close(pipefds[0]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   426
		close(pipefds[1]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   427
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   428
		int r = execlp("/bin/sh", "/bin/sh", "-c", pagercmd, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   429
		if (r < 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   430
			abortmsg("cannot start pager '%s' (errno = %d)",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   431
				 pagercmd, errno);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   432
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   433
		return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   434
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   435
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   436
error:
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   437
	close(pipefds[0]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   438
	close(pipefds[1]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   439
	abortmsg("failed to prepare pager (errno = %d)", errno);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   440
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   441
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   442
int main(int argc, const char *argv[], const char *envp[])
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   443
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   444
	if (getenv("CHGDEBUG"))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   445
		enabledebugmsg();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   446
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   447
	struct cmdserveropts opts;
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   448
	initcmdserveropts(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   449
	setcmdserveropts(&opts);
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   450
	setcmdserverargs(&opts, argc, argv);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   451
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   452
	if (argc == 2) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   453
		int sig = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   454
		if (strcmp(argv[1], "--kill-chg-daemon") == 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   455
			sig = SIGTERM;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   456
		if (strcmp(argv[1], "--reload-chg-daemon") == 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   457
			sig = SIGHUP;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   458
		if (sig > 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   459
			killcmdserver(&opts, sig);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   460
			return 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   461
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   462
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   463
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   464
	hgclient_t *hgc = connectcmdserver(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   465
	if (!hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   466
		abortmsg("cannot open hg client");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   467
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   468
	setupsignalhandler(hgc_peerpid(hgc));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   469
	hgc_setenv(hgc, envp);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   470
	setuppager(hgc, argv + 1, argc - 1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   471
	int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   472
	hgc_close(hgc);
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   473
	freecmdserveropts(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   474
	return exitcode;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   475
}