annotate contrib/chg/chg.c @ 28852:7b5f5a1b4b41

chg: add sockdirfd to cmdserveropts As part of the series to support long socket paths, we need to add the fd of the directory to the cmdserveropts structure so we can use basenames instead of full paths for sockname, redirectsockname, and lockfile.
author Jun Wu <quark@fb.com>
date Sun, 10 Apr 2016 23:56:00 +0100
parents 584e0716c7af
children d11548b4ae45
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
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];
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
34 char redirectsockname[UNIX_PATH_MAX];
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
35 char lockfile[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;
28852
7b5f5a1b4b41 chg: add sockdirfd to cmdserveropts
Jun Wu <quark@fb.com>
parents: 28851
diff changeset
39 int sockdirfd;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
40 };
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
41
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
42 static void initcmdserveropts(struct cmdserveropts *opts) {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
43 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
44 opts->lockfd = -1;
28852
7b5f5a1b4b41 chg: add sockdirfd to cmdserveropts
Jun Wu <quark@fb.com>
parents: 28851
diff changeset
45 opts->sockdirfd = AT_FDCWD;
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
46 }
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
47
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
48 static void freecmdserveropts(struct cmdserveropts *opts) {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
49 free(opts->args);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
50 opts->args = NULL;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
51 opts->argsize = 0;
28852
7b5f5a1b4b41 chg: add sockdirfd to cmdserveropts
Jun Wu <quark@fb.com>
parents: 28851
diff changeset
52 if (opts->sockdirfd != AT_FDCWD) {
7b5f5a1b4b41 chg: add sockdirfd to cmdserveropts
Jun Wu <quark@fb.com>
parents: 28851
diff changeset
53 close(opts->sockdirfd);
7b5f5a1b4b41 chg: add sockdirfd to cmdserveropts
Jun Wu <quark@fb.com>
parents: 28851
diff changeset
54 opts->sockdirfd = AT_FDCWD;
7b5f5a1b4b41 chg: add sockdirfd to cmdserveropts
Jun Wu <quark@fb.com>
parents: 28851
diff changeset
55 }
28167
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
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 * 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
60 * 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
61 * 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
62 */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
63 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
64 {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
65 static const struct {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
66 const char *name;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
67 size_t narg;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
68 } flags[] = {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
69 {"--config", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
70 {"--cwd", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
71 {"--repo", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
72 {"--repository", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
73 {"--traceback", 0},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
74 {"-R", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
75 };
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
76 size_t i;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
77 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
78 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
79 size_t narg = flags[i].narg;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
80 if (memcmp(arg, flags[i].name, len) == 0) {
28790
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
81 if (arg[len] == '\0') {
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
82 /* --flag (value) */
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
83 return narg + 1;
28790
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
84 } else if (arg[len] == '=' && narg > 0) {
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
85 /* --flag=value */
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
86 return 1;
28790
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
87 } else if (flags[i].name[1] != '-') {
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
88 /* short flag */
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
89 return 1;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
90 }
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
91 }
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 return 0;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
94 }
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
95
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
96 /*
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
97 * 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
98 */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
99 static void setcmdserverargs(struct cmdserveropts *opts,
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
100 int argc, const char *argv[])
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
101 {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
102 size_t i, step;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
103 opts->argsize = 0;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
104 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
105 if (!argv[i])
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
106 continue; /* pass clang-analyse */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
107 if (strcmp(argv[i], "--") == 0)
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
108 break;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
109 size_t n = testsensitiveflag(argv[i]);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
110 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
111 continue;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
112 opts->args = reallocx(opts->args,
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
113 (n + opts->argsize) * sizeof(char *));
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
114 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
115 sizeof(char *) * n);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
116 opts->argsize += n;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
117 step = n;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
118 }
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
119 }
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
120
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
121 static void preparesockdir(const char *sockdir)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
122 {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
123 int r;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
124 r = mkdir(sockdir, 0700);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
125 if (r < 0 && errno != EEXIST)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
126 abortmsgerrno("cannot create sockdir %s", sockdir);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
127
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
128 struct stat st;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
129 r = lstat(sockdir, &st);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
130 if (r < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
131 abortmsgerrno("cannot stat %s", sockdir);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
132 if (!S_ISDIR(st.st_mode))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
133 abortmsg("cannot create sockdir %s (file exists)", sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
134 if (st.st_uid != geteuid() || st.st_mode & 0077)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
135 abortmsg("insecure sockdir %s", sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
136 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
137
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
138 static void setcmdserveropts(struct cmdserveropts *opts)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
139 {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
140 int r;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
141 char sockdir[UNIX_PATH_MAX];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
142 const char *envsockname = getenv("CHGSOCKNAME");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
143 if (!envsockname) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
144 /* by default, put socket file in secure directory
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
145 * (permission of socket file may be ignored on some Unices) */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
146 const char *tmpdir = getenv("TMPDIR");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
147 if (!tmpdir)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
148 tmpdir = "/tmp";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
149 r = snprintf(sockdir, sizeof(sockdir), "%s/chg%d",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
150 tmpdir, geteuid());
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
151 if (r < 0 || (size_t)r >= sizeof(sockdir))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
152 abortmsg("too long TMPDIR (r = %d)", r);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
153 preparesockdir(sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
154 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
155
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
156 const char *basename = (envsockname) ? envsockname : sockdir;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
157 const char *sockfmt = (envsockname) ? "%s" : "%s/server";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
158 const char *lockfmt = (envsockname) ? "%s.lock" : "%s/lock";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
159 r = snprintf(opts->sockname, sizeof(opts->sockname), sockfmt, basename);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
160 if (r < 0 || (size_t)r >= sizeof(opts->sockname))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
161 abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
162 r = snprintf(opts->lockfile, sizeof(opts->lockfile), lockfmt, basename);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
163 if (r < 0 || (size_t)r >= sizeof(opts->lockfile))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
164 abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
165 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
166
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 * 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
169 * 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
170 * 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
171 */
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
172 static void lockcmdserver(struct cmdserveropts *opts)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
173 {
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
174 if (opts->lockfd == -1) {
28790
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
175 opts->lockfd = open(opts->lockfile,
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
176 O_RDWR | O_CREAT | O_NOFOLLOW, 0600);
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
177 if (opts->lockfd == -1)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
178 abortmsgerrno("cannot create lock file %s",
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
179 opts->lockfile);
28196
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 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
182 if (r == -1)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
183 abortmsgerrno("cannot acquire lock");
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
184 }
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 /*
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
187 * 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
188 * lockcmdserver is not called.
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
189 */
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
190 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
191 {
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
192 if (opts->lockfd == -1)
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
193 return;
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
194 flock(opts->lockfd, LOCK_UN);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
195 close(opts->lockfd);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
196 opts->lockfd = -1;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
197 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
198
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
199 static const char *gethgcmd(void)
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
200 {
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
201 static const char *hgcmd = NULL;
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
202 if (!hgcmd) {
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
203 hgcmd = getenv("CHGHG");
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
204 if (!hgcmd || hgcmd[0] == '\0')
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
205 hgcmd = getenv("HG");
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
206 if (!hgcmd || hgcmd[0] == '\0')
28605
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
207 #ifdef HGPATH
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
208 hgcmd = (HGPATH);
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
209 #else
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
210 hgcmd = "hg";
28605
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
211 #endif
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
212 }
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
213 return hgcmd;
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
214 }
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
215
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
216 static void execcmdserver(const struct cmdserveropts *opts)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
217 {
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
218 const char *hgcmd = gethgcmd();
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
219
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
220 const char *baseargv[] = {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
221 hgcmd,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
222 "serve",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
223 "--cmdserver", "chgunix",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
224 "--address", opts->sockname,
28453
8a7110e351ec chg: use --daemon-postexec chdir:/ instead of --cwd /
Jun Wu <quark@fb.com>
parents: 28358
diff changeset
225 "--daemon-postexec", "chdir:/",
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
226 "--config", "extensions.chgserver=",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
227 };
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
228 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
229 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
230
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
231 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
232 memcpy(argv, baseargv, sizeof(baseargv));
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
233 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
234 argv[argsize - 1] = NULL;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
235
28261
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
236 if (putenv("CHGINTERNALMARK=") != 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
237 abortmsgerrno("failed to putenv");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
238 if (execvp(hgcmd, (char **)argv) < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
239 abortmsgerrno("failed to exec cmdserver");
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
240 free(argv);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
241 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
242
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
243 /* 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
244 static hgclient_t *retryconnectcmdserver(struct cmdserveropts *opts, pid_t pid)
28060
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 static const struct timespec sleepreq = {0, 10 * 1000000};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
247 int pst = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
248
28769
222f482930c8 chg: make connect debug message less repetitive
Jun Wu <quark@fb.com>
parents: 28605
diff changeset
249 debugmsg("try connect to %s repeatedly", opts->sockname);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
250 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
251 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
252 if (hgc)
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
253 return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
254
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
255 if (pid > 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
256 /* 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
257 int r = waitpid(pid, &pst, WNOHANG);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
258 if (r != 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
259 goto cleanup;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
260 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
261
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
262 nanosleep(&sleepreq, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
263 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
264
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
265 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
266 return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
267
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
268 cleanup:
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
269 if (WIFEXITED(pst)) {
28477
194a6cd873cd chg: silently inherit server exit code
Jun Wu <quark@fb.com>
parents: 28455
diff changeset
270 debugmsg("cmdserver exited with status %d", WEXITSTATUS(pst));
194a6cd873cd chg: silently inherit server exit code
Jun Wu <quark@fb.com>
parents: 28455
diff changeset
271 exit(WEXITSTATUS(pst));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
272 } else if (WIFSIGNALED(pst)) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
273 abortmsg("cmdserver killed by signal %d", WTERMSIG(pst));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
274 } else {
28851
584e0716c7af chg: fix spelling in the error message about error waiting for cmdserver
Jun Wu <quark@fb.com>
parents: 28790
diff changeset
275 abortmsg("error while waiting for cmdserver");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
276 }
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
277 return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
278 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
279
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
280 /* 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
281 static hgclient_t *connectcmdserver(struct cmdserveropts *opts)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
282 {
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
283 const char *sockname = opts->redirectsockname[0] ?
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
284 opts->redirectsockname : opts->sockname;
28769
222f482930c8 chg: make connect debug message less repetitive
Jun Wu <quark@fb.com>
parents: 28605
diff changeset
285 debugmsg("try connect to %s", sockname);
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
286 hgclient_t *hgc = hgc_open(sockname);
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
287 if (hgc)
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
288 return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
289
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
290 lockcmdserver(opts);
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
291 hgc = hgc_open(sockname);
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
292 if (hgc) {
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
293 unlockcmdserver(opts);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
294 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
295 return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
296 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
297
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
298 /* prevent us from being connected to an outdated server: we were
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
299 * told by a server to redirect to opts->redirectsockname and that
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
300 * address does not work. we do not want to connect to the server
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
301 * again because it will probably tell us the same thing. */
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
302 if (sockname == opts->redirectsockname)
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
303 unlink(opts->sockname);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
304
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
305 debugmsg("start cmdserver at %s", opts->sockname);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
306
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
307 pid_t pid = fork();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
308 if (pid < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
309 abortmsg("failed to fork cmdserver process");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
310 if (pid == 0) {
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
311 /* 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
312 close(opts->lockfd);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
313 execcmdserver(opts);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
314 } else {
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
315 hgc = retryconnectcmdserver(opts, pid);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
316 }
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
317
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
318 unlockcmdserver(opts);
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
319 return hgc;
28060
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
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
322 static void killcmdserver(const struct cmdserveropts *opts)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
323 {
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
324 /* resolve config hash */
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
325 char *resolvedpath = realpath(opts->sockname, NULL);
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
326 if (resolvedpath) {
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
327 unlink(resolvedpath);
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
328 free(resolvedpath);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
329 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
330 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
331
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
332 static pid_t peerpid = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
333
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
334 static void forwardsignal(int sig)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
335 {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
336 assert(peerpid > 0);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
337 if (kill(peerpid, sig) < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
338 abortmsgerrno("cannot kill %d", peerpid);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
339 debugmsg("forward signal %d", sig);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
340 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
341
28086
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
342 static void handlestopsignal(int sig)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
343 {
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
344 sigset_t unblockset, oldset;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
345 struct sigaction sa, oldsa;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
346 if (sigemptyset(&unblockset) < 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 if (sigaddset(&unblockset, sig) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
349 goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
350 memset(&sa, 0, sizeof(sa));
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
351 sa.sa_handler = SIG_DFL;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
352 sa.sa_flags = SA_RESTART;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
353 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
354 goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
355
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
356 forwardsignal(sig);
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
357 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
358 goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
359 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
360 goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
361 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
362 goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
363 /* 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
364 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
365 goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
366 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
367 goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
368 return;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
369
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
370 error:
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
371 abortmsgerrno("failed to handle stop signal");
28086
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
372 }
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
373
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
374 static void setupsignalhandler(pid_t pid)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
375 {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
376 if (pid <= 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
377 return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
378 peerpid = pid;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
379
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
380 struct sigaction sa;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
381 memset(&sa, 0, sizeof(sa));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
382 sa.sa_handler = forwardsignal;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
383 sa.sa_flags = SA_RESTART;
28085
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
384 if (sigemptyset(&sa.sa_mask) < 0)
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
385 goto error;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
386
28085
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
387 if (sigaction(SIGHUP, &sa, NULL) < 0)
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
388 goto error;
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
389 if (sigaction(SIGINT, &sa, NULL) < 0)
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
390 goto error;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
391
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
392 /* terminate frontend by double SIGTERM in case of server freeze */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
393 sa.sa_flags |= SA_RESETHAND;
28085
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
394 if (sigaction(SIGTERM, &sa, NULL) < 0)
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
395 goto error;
28086
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
396
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
397 /* 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
398 sa.sa_handler = forwardsignal;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
399 sa.sa_flags = SA_RESTART;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
400 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
401 goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
402 sa.sa_handler = handlestopsignal;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
403 sa.sa_flags = SA_RESTART;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
404 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
405 goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
406
28085
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
407 return;
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
408
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
409 error:
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
410 abortmsgerrno("failed to set up signal handlers");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
411 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
412
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
413 /* This implementation is based on hgext/pager.py (pre 369741ef7253) */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
414 static void setuppager(hgclient_t *hgc, const char *const args[],
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
415 size_t argsize)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
416 {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
417 const char *pagercmd = hgc_getpager(hgc, args, argsize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
418 if (!pagercmd)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
419 return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
420
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
421 int pipefds[2];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
422 if (pipe(pipefds) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
423 return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
424 pid_t pid = fork();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
425 if (pid < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
426 goto error;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
427 if (pid == 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
428 close(pipefds[0]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
429 if (dup2(pipefds[1], fileno(stdout)) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
430 goto error;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
431 if (isatty(fileno(stderr))) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
432 if (dup2(pipefds[1], fileno(stderr)) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
433 goto error;
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 close(pipefds[1]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
436 hgc_attachio(hgc); /* reattach to pager */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
437 return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
438 } else {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
439 dup2(pipefds[0], fileno(stdin));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
440 close(pipefds[0]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
441 close(pipefds[1]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
442
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
443 int r = execlp("/bin/sh", "/bin/sh", "-c", pagercmd, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
444 if (r < 0) {
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
445 abortmsgerrno("cannot start pager '%s'", pagercmd);
28060
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 return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
448 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
449
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
450 error:
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
451 close(pipefds[0]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
452 close(pipefds[1]);
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
453 abortmsgerrno("failed to prepare pager");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
454 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
455
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
456 /* Run instructions sent from the server like unlink and set redirect path
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
457 * Return 1 if reconnect is needed, otherwise 0 */
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
458 static int runinstructions(struct cmdserveropts *opts, const char **insts)
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
459 {
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
460 int needreconnect = 0;
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
461 if (!insts)
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
462 return needreconnect;
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
463
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
464 assert(insts);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
465 opts->redirectsockname[0] = '\0';
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
466 const char **pinst;
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
467 for (pinst = insts; *pinst; pinst++) {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
468 debugmsg("instruction: %s", *pinst);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
469 if (strncmp(*pinst, "unlink ", 7) == 0) {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
470 unlink(*pinst + 7);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
471 } else if (strncmp(*pinst, "redirect ", 9) == 0) {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
472 int r = snprintf(opts->redirectsockname,
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
473 sizeof(opts->redirectsockname),
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
474 "%s", *pinst + 9);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
475 if (r < 0 || r >= (int)sizeof(opts->redirectsockname))
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
476 abortmsg("redirect path is too long (%d)", r);
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
477 needreconnect = 1;
28516
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
478 } else if (strncmp(*pinst, "exit ", 5) == 0) {
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
479 int n = 0;
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
480 if (sscanf(*pinst + 5, "%d", &n) != 1)
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
481 abortmsg("cannot read the exit code");
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
482 exit(n);
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
483 } else if (strcmp(*pinst, "reconnect") == 0) {
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
484 needreconnect = 1;
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
485 } else {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
486 abortmsg("unknown instruction: %s", *pinst);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
487 }
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
488 }
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
489 return needreconnect;
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
490 }
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
491
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
492 /*
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
493 * Test whether the command is unsupported or not. This is not designed to
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
494 * cover all cases. But it's fast, does not depend on the server and does
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
495 * not return false positives.
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
496 */
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
497 static int isunsupported(int argc, const char *argv[])
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
498 {
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
499 enum {
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
500 SERVE = 1,
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
501 DAEMON = 2,
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
502 SERVEDAEMON = SERVE | DAEMON,
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
503 TIME = 4,
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
504 };
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
505 unsigned int state = 0;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
506 int i;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
507 for (i = 0; i < argc; ++i) {
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
508 if (strcmp(argv[i], "--") == 0)
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
509 break;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
510 if (i == 0 && strcmp("serve", argv[i]) == 0)
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
511 state |= SERVE;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
512 else if (strcmp("-d", argv[i]) == 0 ||
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
513 strcmp("--daemon", argv[i]) == 0)
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
514 state |= DAEMON;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
515 else if (strcmp("--time", argv[i]) == 0)
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
516 state |= TIME;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
517 }
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
518 return (state & TIME) == TIME ||
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
519 (state & SERVEDAEMON) == SERVEDAEMON;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
520 }
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
521
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
522 static void execoriginalhg(const char *argv[])
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
523 {
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
524 debugmsg("execute original hg");
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
525 if (execvp(gethgcmd(), (char **)argv) < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
526 abortmsgerrno("failed to exec original hg");
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
527 }
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
528
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
529 int main(int argc, const char *argv[], const char *envp[])
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
530 {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
531 if (getenv("CHGDEBUG"))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
532 enabledebugmsg();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
533
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
534 if (!getenv("HGPLAIN") && isatty(fileno(stderr)))
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
535 enablecolor();
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
536
28261
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
537 if (getenv("CHGINTERNALMARK"))
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
538 abortmsg("chg started by chg detected.\n"
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
539 "Please make sure ${HG:-hg} is not a symlink or "
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
540 "wrapper to chg. Alternatively, set $CHGHG to the "
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
541 "path of real hg.");
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
542
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
543 if (isunsupported(argc - 1, argv + 1))
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
544 execoriginalhg(argv);
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
545
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
546 struct cmdserveropts opts;
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
547 initcmdserveropts(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
548 setcmdserveropts(&opts);
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
549 setcmdserverargs(&opts, argc, argv);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
550
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
551 if (argc == 2) {
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
552 if (strcmp(argv[1], "--kill-chg-daemon") == 0) {
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
553 killcmdserver(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
554 return 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
555 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
556 }
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
557
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
558 hgclient_t *hgc;
28358
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
559 size_t retry = 0;
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
560 while (1) {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
561 hgc = connectcmdserver(&opts);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
562 if (!hgc)
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
563 abortmsg("cannot open hg client");
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
564 hgc_setenv(hgc, envp);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
565 const char **insts = hgc_validate(hgc, argv + 1, argc - 1);
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
566 int needreconnect = runinstructions(&opts, insts);
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
567 free(insts);
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
568 if (!needreconnect)
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
569 break;
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
570 hgc_close(hgc);
28358
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
571 if (++retry > 10)
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
572 abortmsg("too many redirections.\n"
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
573 "Please make sure %s is not a wrapper which "
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
574 "changes sensitive environment variables "
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
575 "before executing hg. If you have to use a "
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
576 "wrapper, wrap chg instead of hg.",
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
577 gethgcmd());
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
578 }
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
579
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
580 setupsignalhandler(hgc_peerpid(hgc));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
581 setuppager(hgc, argv + 1, argc - 1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
582 int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
583 hgc_close(hgc);
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
584 freecmdserveropts(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
585 return exitcode;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
586 }