contrib/chg/hgclient.c
author Arseniy Alekseyev <aalekseyev@janestreet.com>
Fri, 26 Apr 2024 19:10:35 +0100
changeset 51626 865efc020c33
parent 46177 0c320e6032f1
permissions -rw-r--r--
dirstate: remove the python-side whitelist of allowed matchers This whitelist is too permissive because it allows matchers that contain disallowed ones deep inside, for example through `intersectionmatcher`. It is also too restrictive because it doesn't pass through some of the matchers we support, such as `patternmatcher`. It's also unnecessary because unsupported matchers raise `FallbackError` and we fall back anyway. Making this change makes more of the tests use rust code path, and therefore subtly change behavior. For example, rust status in largefiles repos seems to have strange behavior.
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 command server client that uses Unix domain socket
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
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    10
#include <arpa/inet.h> /* for ntohl(), htonl() */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    11
#include <assert.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    12
#include <ctype.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    13
#include <errno.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    14
#include <fcntl.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    15
#include <signal.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    16
#include <stdint.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    17
#include <stdio.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    18
#include <stdlib.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    19
#include <string.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    20
#include <sys/socket.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    21
#include <sys/stat.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    22
#include <sys/un.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"
30738
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
    26
#include "procutil.h"
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    27
#include "util.h"
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    28
46177
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 41336
diff changeset
    29
enum {
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 41336
diff changeset
    30
	CAP_GETENCODING = 0x0001,
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 41336
diff changeset
    31
	CAP_RUNCOMMAND = 0x0002,
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 41336
diff changeset
    32
	/* cHg extension: */
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 41336
diff changeset
    33
	CAP_ATTACHIO = 0x0100,
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 41336
diff changeset
    34
	CAP_CHDIR = 0x0200,
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 41336
diff changeset
    35
	CAP_SETENV = 0x0800,
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 41336
diff changeset
    36
	CAP_SETUMASK2 = 0x1000,
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 41336
diff changeset
    37
	CAP_VALIDATE = 0x2000,
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 41336
diff changeset
    38
	CAP_SETPROCNAME = 0x4000,
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
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    41
typedef struct {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    42
	const char *name;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    43
	unsigned int flag;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    44
} cappair_t;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    45
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    46
static const cappair_t captable[] = {
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    47
    {"getencoding", CAP_GETENCODING},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    48
    {"runcommand", CAP_RUNCOMMAND},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    49
    {"attachio", CAP_ATTACHIO},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    50
    {"chdir", CAP_CHDIR},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    51
    {"setenv", CAP_SETENV},
40109
413b6b10fdd5 chg: upgrade client to use "setumask2" command
Yuya Nishihara <yuya@tcha.org>
parents: 35959
diff changeset
    52
    {"setumask2", CAP_SETUMASK2},
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    53
    {"validate", CAP_VALIDATE},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    54
    {"setprocname", CAP_SETPROCNAME},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    55
    {NULL, 0}, /* terminator */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    56
};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    57
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    58
typedef struct {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    59
	char ch;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    60
	char *data;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    61
	size_t maxdatasize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    62
	size_t datasize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    63
} context_t;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    64
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    65
struct hgclient_tag_ {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    66
	int sockfd;
29581
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    67
	pid_t pgid;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    68
	pid_t pid;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    69
	context_t ctx;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    70
	unsigned int capflags;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    71
};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    72
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    73
static const size_t defaultdatasize = 4096;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    74
30738
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
    75
static void attachio(hgclient_t *hgc);
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
    76
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    77
static void initcontext(context_t *ctx)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    78
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    79
	ctx->ch = '\0';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    80
	ctx->data = malloc(defaultdatasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    81
	ctx->maxdatasize = (ctx->data) ? defaultdatasize : 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    82
	ctx->datasize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    83
	debugmsg("initialize context buffer with size %zu", ctx->maxdatasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    84
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    85
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    86
static void enlargecontext(context_t *ctx, size_t newsize)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    87
{
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
    88
	if (newsize <= ctx->maxdatasize) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    89
		return;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
    90
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    91
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    92
	newsize = defaultdatasize *
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    93
	          ((newsize + defaultdatasize - 1) / defaultdatasize);
28166
c6e0c2533e5f chg: use mallocx and reallocx in hgclient
Jun Wu <quark@fb.com>
parents: 28160
diff changeset
    94
	ctx->data = reallocx(ctx->data, newsize);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    95
	ctx->maxdatasize = newsize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    96
	debugmsg("enlarge context buffer to %zu", ctx->maxdatasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    97
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    98
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    99
static void freecontext(context_t *ctx)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   100
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   101
	debugmsg("free context buffer");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   102
	free(ctx->data);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   103
	ctx->data = NULL;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   104
	ctx->maxdatasize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   105
	ctx->datasize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   106
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   107
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   108
/* Read channeled response from cmdserver */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   109
static void readchannel(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   110
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   111
	assert(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   112
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   113
	ssize_t rsize = recv(hgc->sockfd, &hgc->ctx.ch, sizeof(hgc->ctx.ch), 0);
28551
8e5312f8df30 chg: downgrade "failed to read channel" from abortmsg to debugmsg
Jun Wu <quark@fb.com>
parents: 28535
diff changeset
   114
	if (rsize != sizeof(hgc->ctx.ch)) {
8e5312f8df30 chg: downgrade "failed to read channel" from abortmsg to debugmsg
Jun Wu <quark@fb.com>
parents: 28535
diff changeset
   115
		/* server would have exception and traceback would be printed */
8e5312f8df30 chg: downgrade "failed to read channel" from abortmsg to debugmsg
Jun Wu <quark@fb.com>
parents: 28535
diff changeset
   116
		debugmsg("failed to read channel");
8e5312f8df30 chg: downgrade "failed to read channel" from abortmsg to debugmsg
Jun Wu <quark@fb.com>
parents: 28535
diff changeset
   117
		exit(255);
8e5312f8df30 chg: downgrade "failed to read channel" from abortmsg to debugmsg
Jun Wu <quark@fb.com>
parents: 28535
diff changeset
   118
	}
28060
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
	uint32_t datasize_n;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   121
	rsize = recv(hgc->sockfd, &datasize_n, sizeof(datasize_n), 0);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   122
	if (rsize != sizeof(datasize_n)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   123
		abortmsg("failed to read data size");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   124
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   125
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   126
	/* datasize denotes the maximum size to write if input request */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   127
	hgc->ctx.datasize = ntohl(datasize_n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   128
	enlargecontext(&hgc->ctx, hgc->ctx.datasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   129
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   130
	if (isupper(hgc->ctx.ch) && hgc->ctx.ch != 'S') {
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   131
		return; /* assumes input request */
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   132
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   133
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   134
	size_t cursize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   135
	while (cursize < hgc->ctx.datasize) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   136
		rsize = recv(hgc->sockfd, hgc->ctx.data + cursize,
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   137
		             hgc->ctx.datasize - cursize, 0);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   138
		if (rsize < 1) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   139
			abortmsg("failed to read data block");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   140
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   141
		cursize += rsize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   142
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   143
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   144
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   145
static void sendall(int sockfd, const void *data, size_t datasize)
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
	const char *p = data;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   148
	const char *const endp = p + datasize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   149
	while (p < endp) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   150
		ssize_t r = send(sockfd, p, endp - p, 0);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   151
		if (r < 0) {
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   152
			abortmsgerrno("cannot communicate");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   153
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   154
		p += r;
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
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   157
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   158
/* Write lengh-data block to cmdserver */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   159
static void writeblock(const hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   160
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   161
	assert(hgc);
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
	const uint32_t datasize_n = htonl(hgc->ctx.datasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   164
	sendall(hgc->sockfd, &datasize_n, sizeof(datasize_n));
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
	sendall(hgc->sockfd, hgc->ctx.data, hgc->ctx.datasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   167
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   168
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   169
static void writeblockrequest(const hgclient_t *hgc, const char *chcmd)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   170
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   171
	debugmsg("request %s, block size %zu", chcmd, hgc->ctx.datasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   172
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   173
	char buf[strlen(chcmd) + 1];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   174
	memcpy(buf, chcmd, sizeof(buf) - 1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   175
	buf[sizeof(buf) - 1] = '\n';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   176
	sendall(hgc->sockfd, buf, sizeof(buf));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   177
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   178
	writeblock(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   179
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   180
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   181
/* Build '\0'-separated list of args. argsize < 0 denotes that args are
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   182
 * terminated by NULL. */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   183
static void packcmdargs(context_t *ctx, const char *const args[],
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   184
                        ssize_t argsize)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   185
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   186
	ctx->datasize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   187
	const char *const *const end = (argsize >= 0) ? args + argsize : NULL;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   188
	for (const char *const *it = args; it != end && *it; ++it) {
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   189
		const size_t n = strlen(*it) + 1; /* include '\0' */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   190
		enlargecontext(ctx, ctx->datasize + n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   191
		memcpy(ctx->data + ctx->datasize, *it, n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   192
		ctx->datasize += n;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   193
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   194
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   195
	if (ctx->datasize > 0) {
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   196
		--ctx->datasize; /* strip last '\0' */
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   197
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   198
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   199
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   200
/* Extract '\0'-separated list of args to new buffer, terminated by NULL */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   201
static const char **unpackcmdargsnul(const context_t *ctx)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   202
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   203
	const char **args = NULL;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   204
	size_t nargs = 0, maxnargs = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   205
	const char *s = ctx->data;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   206
	const char *e = ctx->data + ctx->datasize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   207
	for (;;) {
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   208
		if (nargs + 1 >= maxnargs) { /* including last NULL */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   209
			maxnargs += 256;
28166
c6e0c2533e5f chg: use mallocx and reallocx in hgclient
Jun Wu <quark@fb.com>
parents: 28160
diff changeset
   210
			args = reallocx(args, maxnargs * sizeof(args[0]));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   211
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   212
		args[nargs] = s;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   213
		nargs++;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   214
		s = memchr(s, '\0', e - s);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   215
		if (!s) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   216
			break;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   217
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   218
		s++;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   219
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   220
	args[nargs] = NULL;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   221
	return args;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   222
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   223
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   224
static void handlereadrequest(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   225
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   226
	context_t *ctx = &hgc->ctx;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   227
	size_t r = fread(ctx->data, sizeof(ctx->data[0]), ctx->datasize, stdin);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   228
	ctx->datasize = r;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   229
	writeblock(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   230
}
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
/* Read single-line */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   233
static void handlereadlinerequest(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   234
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   235
	context_t *ctx = &hgc->ctx;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   236
	if (!fgets(ctx->data, ctx->datasize, stdin)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   237
		ctx->data[0] = '\0';
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   238
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   239
	ctx->datasize = strlen(ctx->data);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   240
	writeblock(hgc);
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
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   243
/* Execute the requested command and write exit code */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   244
static void handlesystemrequest(hgclient_t *hgc)
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
	context_t *ctx = &hgc->ctx;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   247
	enlargecontext(ctx, ctx->datasize + 1);
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   248
	ctx->data[ctx->datasize] = '\0'; /* terminate last string */
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
	const char **args = unpackcmdargsnul(ctx);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   251
	if (!args[0] || !args[1] || !args[2]) {
30726
dd897eb1699e chg: send type information via S channel (BC)
Jun Wu <quark@fb.com>
parents: 30679
diff changeset
   252
		abortmsg("missing type or command or cwd in system request");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   253
	}
30728
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   254
	if (strcmp(args[0], "system") == 0) {
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   255
		debugmsg("run '%s' at '%s'", args[1], args[2]);
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   256
		int32_t r = runshellcmd(args[1], args + 3, args[2]);
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   257
		free(args);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   258
30728
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   259
		uint32_t r_n = htonl(r);
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   260
		memcpy(ctx->data, &r_n, sizeof(r_n));
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   261
		ctx->datasize = sizeof(r_n);
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   262
		writeblock(hgc);
30738
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   263
	} else if (strcmp(args[0], "pager") == 0) {
31941
ac5527021097 chg: respect environment variables for pager
Jun Wu <quark@fb.com>
parents: 30756
diff changeset
   264
		setuppager(args[1], args + 3);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   265
		if (hgc->capflags & CAP_ATTACHIO) {
30738
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   266
			attachio(hgc);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   267
		}
30738
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   268
		/* unblock the server */
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   269
		static const char emptycmd[] = "\n";
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   270
		sendall(hgc->sockfd, emptycmd, sizeof(emptycmd) - 1);
30728
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   271
	} else {
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   272
		abortmsg("unknown type in system request: %s", args[0]);
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   273
	}
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
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   276
/* Read response of command execution until receiving 'r'-esult */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   277
static void handleresponse(hgclient_t *hgc)
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
	for (;;) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   280
		readchannel(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   281
		context_t *ctx = &hgc->ctx;
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   282
		debugmsg("response read from channel %c, size %zu", ctx->ch,
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   283
		         ctx->datasize);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   284
		switch (ctx->ch) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   285
		case 'o':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   286
			fwrite(ctx->data, sizeof(ctx->data[0]), ctx->datasize,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   287
			       stdout);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   288
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   289
		case 'e':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   290
			fwrite(ctx->data, sizeof(ctx->data[0]), ctx->datasize,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   291
			       stderr);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   292
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   293
		case 'd':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   294
			/* assumes last char is '\n' */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   295
			ctx->data[ctx->datasize - 1] = '\0';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   296
			debugmsg("server: %s", ctx->data);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   297
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   298
		case 'r':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   299
			return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   300
		case 'I':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   301
			handlereadrequest(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   302
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   303
		case 'L':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   304
			handlereadlinerequest(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   305
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   306
		case 'S':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   307
			handlesystemrequest(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   308
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   309
		default:
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   310
			if (isupper(ctx->ch)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   311
				abortmsg("cannot handle response (ch = %c)",
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   312
				         ctx->ch);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   313
			}
28060
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
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   318
static unsigned int parsecapabilities(const char *s, const char *e)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   319
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   320
	unsigned int flags = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   321
	while (s < e) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   322
		const char *t = strchr(s, ' ');
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   323
		if (!t || t > e) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   324
			t = e;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   325
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   326
		const cappair_t *cap;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   327
		for (cap = captable; cap->flag; ++cap) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   328
			size_t n = t - s;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   329
			if (strncmp(s, cap->name, n) == 0 &&
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   330
			    strlen(cap->name) == n) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   331
				flags |= cap->flag;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   332
				break;
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
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   335
		s = t + 1;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   336
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   337
	return flags;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   338
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   339
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   340
static void readhello(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   341
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   342
	readchannel(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   343
	context_t *ctx = &hgc->ctx;
28512
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   344
	if (ctx->ch != 'o') {
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   345
		char ch = ctx->ch;
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   346
		if (ch == 'e') {
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   347
			/* write early error and will exit */
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   348
			fwrite(ctx->data, sizeof(ctx->data[0]), ctx->datasize,
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   349
			       stderr);
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   350
			handleresponse(hgc);
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   351
		}
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   352
		abortmsg("unexpected channel of hello message (ch = %c)", ch);
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   353
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   354
	enlargecontext(ctx, ctx->datasize + 1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   355
	ctx->data[ctx->datasize] = '\0';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   356
	debugmsg("hello received: %s (size = %zu)", ctx->data, ctx->datasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   357
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   358
	const char *s = ctx->data;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   359
	const char *const dataend = ctx->data + ctx->datasize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   360
	while (s < dataend) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   361
		const char *t = strchr(s, ':');
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   362
		if (!t || t[1] != ' ') {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   363
			break;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   364
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   365
		const char *u = strchr(t + 2, '\n');
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   366
		if (!u) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   367
			u = dataend;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   368
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   369
		if (strncmp(s, "capabilities:", t - s + 1) == 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   370
			hgc->capflags = parsecapabilities(t + 2, u);
29581
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   371
		} else if (strncmp(s, "pgid:", t - s + 1) == 0) {
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   372
			hgc->pgid = strtol(t + 2, NULL, 10);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   373
		} else if (strncmp(s, "pid:", t - s + 1) == 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   374
			hgc->pid = strtol(t + 2, NULL, 10);
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
		s = u + 1;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   377
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   378
	debugmsg("capflags=0x%04x, pid=%d", hgc->capflags, hgc->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
30751
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   381
static void updateprocname(hgclient_t *hgc)
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   382
{
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   383
	int r = snprintf(hgc->ctx.data, hgc->ctx.maxdatasize, "chg[worker/%d]",
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   384
	                 (int)getpid());
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   385
	if (r < 0 || (size_t)r >= hgc->ctx.maxdatasize) {
30756
1f9684fe94cc chg: check snprintf result strictly
Jun Wu <quark@fb.com>
parents: 30751
diff changeset
   386
		abortmsg("insufficient buffer to write procname (r = %d)", r);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   387
	}
30756
1f9684fe94cc chg: check snprintf result strictly
Jun Wu <quark@fb.com>
parents: 30751
diff changeset
   388
	hgc->ctx.datasize = (size_t)r;
30751
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   389
	writeblockrequest(hgc, "setprocname");
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   390
}
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   391
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   392
static void attachio(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   393
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   394
	debugmsg("request attachio");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   395
	static const char chcmd[] = "attachio\n";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   396
	sendall(hgc->sockfd, chcmd, sizeof(chcmd) - 1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   397
	readchannel(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   398
	context_t *ctx = &hgc->ctx;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   399
	if (ctx->ch != 'I') {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   400
		abortmsg("unexpected response for attachio (ch = %c)", ctx->ch);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   401
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   402
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   403
	static const int fds[3] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   404
	struct msghdr msgh;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   405
	memset(&msgh, 0, sizeof(msgh));
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   406
	struct iovec iov = {ctx->data, ctx->datasize}; /* dummy payload */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   407
	msgh.msg_iov = &iov;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   408
	msgh.msg_iovlen = 1;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   409
	char fdbuf[CMSG_SPACE(sizeof(fds))];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   410
	msgh.msg_control = fdbuf;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   411
	msgh.msg_controllen = sizeof(fdbuf);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   412
	struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msgh);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   413
	cmsg->cmsg_level = SOL_SOCKET;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   414
	cmsg->cmsg_type = SCM_RIGHTS;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   415
	cmsg->cmsg_len = CMSG_LEN(sizeof(fds));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   416
	memcpy(CMSG_DATA(cmsg), fds, sizeof(fds));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   417
	msgh.msg_controllen = cmsg->cmsg_len;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   418
	ssize_t r = sendmsg(hgc->sockfd, &msgh, 0);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   419
	if (r < 0) {
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   420
		abortmsgerrno("sendmsg failed");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   421
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   422
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   423
	handleresponse(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   424
	int32_t n;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   425
	if (ctx->datasize != sizeof(n)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   426
		abortmsg("unexpected size of attachio result");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   427
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   428
	memcpy(&n, ctx->data, sizeof(n));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   429
	n = ntohl(n);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   430
	if (n != sizeof(fds) / sizeof(fds[0])) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   431
		abortmsg("failed to send fds (n = %d)", n);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   432
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   433
}
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
static void chdirtocwd(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   436
{
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   437
	if (!getcwd(hgc->ctx.data, hgc->ctx.maxdatasize)) {
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   438
		abortmsgerrno("failed to getcwd");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   439
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   440
	hgc->ctx.datasize = strlen(hgc->ctx.data);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   441
	writeblockrequest(hgc, "chdir");
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
28160
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   444
static void forwardumask(hgclient_t *hgc)
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   445
{
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   446
	mode_t mask = umask(0);
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   447
	umask(mask);
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   448
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   449
	uint32_t data = htonl(mask);
40109
413b6b10fdd5 chg: upgrade client to use "setumask2" command
Yuya Nishihara <yuya@tcha.org>
parents: 35959
diff changeset
   450
	enlargecontext(&hgc->ctx, sizeof(data));
413b6b10fdd5 chg: upgrade client to use "setumask2" command
Yuya Nishihara <yuya@tcha.org>
parents: 35959
diff changeset
   451
	memcpy(hgc->ctx.data, &data, sizeof(data));
413b6b10fdd5 chg: upgrade client to use "setumask2" command
Yuya Nishihara <yuya@tcha.org>
parents: 35959
diff changeset
   452
	hgc->ctx.datasize = sizeof(data);
413b6b10fdd5 chg: upgrade client to use "setumask2" command
Yuya Nishihara <yuya@tcha.org>
parents: 35959
diff changeset
   453
	writeblockrequest(hgc, "setumask2");
28160
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   454
}
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   455
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   456
/*!
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   457
 * Open connection to per-user cmdserver
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   458
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   459
 * If no background server running, returns NULL.
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   460
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   461
hgclient_t *hgc_open(const char *sockname)
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
	int fd = socket(AF_UNIX, SOCK_STREAM, 0);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   464
	if (fd < 0) {
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   465
		abortmsgerrno("cannot create socket");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   466
	}
28060
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
	/* don't keep fd on fork(), so that it can be closed when the parent
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   469
	 * process get terminated. */
28855
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
   470
	fsetcloexec(fd);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   471
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   472
	struct sockaddr_un addr;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   473
	addr.sun_family = AF_UNIX;
30675
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   474
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   475
	/* use chdir to workaround small sizeof(sun_path) */
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   476
	int bakfd = -1;
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   477
	const char *basename = sockname;
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   478
	{
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   479
		const char *split = strrchr(sockname, '/');
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   480
		if (split && split != sockname) {
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   481
			if (split[1] == '\0') {
30675
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   482
				abortmsg("sockname cannot end with a slash");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   483
			}
30675
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   484
			size_t len = split - sockname;
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   485
			char sockdir[len + 1];
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   486
			memcpy(sockdir, sockname, len);
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   487
			sockdir[len] = '\0';
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   488
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   489
			bakfd = open(".", O_DIRECTORY);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   490
			if (bakfd == -1) {
30675
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   491
				abortmsgerrno("cannot open cwd");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   492
			}
30675
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   493
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   494
			int r = chdir(sockdir);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   495
			if (r != 0) {
30675
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   496
				abortmsgerrno("cannot chdir %s", sockdir);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   497
			}
30675
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   498
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   499
			basename = split + 1;
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   500
		}
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   501
	}
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   502
	if (strlen(basename) >= sizeof(addr.sun_path)) {
30675
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   503
		abortmsg("sockname is too long: %s", basename);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   504
	}
30675
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   505
	strncpy(addr.sun_path, basename, sizeof(addr.sun_path));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   506
	addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   507
30675
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   508
	/* real connect */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   509
	int r = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
30679
fe11f466880d chg: handle connect failure before errno gets overridden
Jun Wu <quark@fb.com>
parents: 30675
diff changeset
   510
	if (r < 0) {
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   511
		if (errno != ENOENT && errno != ECONNREFUSED) {
30679
fe11f466880d chg: handle connect failure before errno gets overridden
Jun Wu <quark@fb.com>
parents: 30675
diff changeset
   512
			abortmsgerrno("cannot connect to %s", sockname);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   513
		}
30679
fe11f466880d chg: handle connect failure before errno gets overridden
Jun Wu <quark@fb.com>
parents: 30675
diff changeset
   514
	}
30675
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   515
	if (bakfd != -1) {
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   516
		fchdirx(bakfd);
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   517
		close(bakfd);
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29719
diff changeset
   518
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   519
	if (r < 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   520
		close(fd);
30679
fe11f466880d chg: handle connect failure before errno gets overridden
Jun Wu <quark@fb.com>
parents: 30675
diff changeset
   521
		return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   522
	}
28769
222f482930c8 chg: make connect debug message less repetitive
Jun Wu <quark@fb.com>
parents: 28551
diff changeset
   523
	debugmsg("connected to %s", addr.sun_path);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   524
28166
c6e0c2533e5f chg: use mallocx and reallocx in hgclient
Jun Wu <quark@fb.com>
parents: 28160
diff changeset
   525
	hgclient_t *hgc = mallocx(sizeof(hgclient_t));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   526
	memset(hgc, 0, sizeof(*hgc));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   527
	hgc->sockfd = fd;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   528
	initcontext(&hgc->ctx);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   529
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   530
	readhello(hgc);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   531
	if (!(hgc->capflags & CAP_RUNCOMMAND)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   532
		abortmsg("insufficient capability: runcommand");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   533
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   534
	if (hgc->capflags & CAP_SETPROCNAME) {
30751
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   535
		updateprocname(hgc);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   536
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   537
	if (hgc->capflags & CAP_ATTACHIO) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   538
		attachio(hgc);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   539
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   540
	if (hgc->capflags & CAP_CHDIR) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   541
		chdirtocwd(hgc);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   542
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   543
	if (hgc->capflags & CAP_SETUMASK2) {
28160
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   544
		forwardumask(hgc);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   545
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   546
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   547
	return hgc;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   548
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   549
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
 * Close connection and free allocated memory
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   552
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   553
void hgc_close(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   554
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   555
	assert(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   556
	freecontext(&hgc->ctx);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   557
	close(hgc->sockfd);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   558
	free(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   559
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   560
29581
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   561
pid_t hgc_peerpgid(const hgclient_t *hgc)
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   562
{
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   563
	assert(hgc);
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   564
	return hgc->pgid;
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   565
}
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   566
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   567
pid_t hgc_peerpid(const hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   568
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   569
	assert(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   570
	return hgc->pid;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   571
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   572
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   573
/*!
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   574
 * Send command line arguments to let the server load the repo config and check
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   575
 * whether it can process our request directly or not.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   576
 * Make sure hgc_setenv is called before calling this.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   577
 *
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   578
 * @return - NULL, the server believes it can handle our request, or does not
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   579
 *           support "validate" command.
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28512
diff changeset
   580
 *         - a list of strings, the server probably cannot handle our request
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28512
diff changeset
   581
 *           and it sent instructions telling us what to do next. See
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   582
 *           chgserver.py for possible instruction formats.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   583
 *           the list should be freed by the caller.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   584
 *           the last string is guaranteed to be NULL.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   585
 */
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   586
const char **hgc_validate(hgclient_t *hgc, const char *const args[],
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   587
                          size_t argsize)
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   588
{
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   589
	assert(hgc);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   590
	if (!(hgc->capflags & CAP_VALIDATE)) {
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   591
		return NULL;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   592
	}
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   593
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   594
	packcmdargs(&hgc->ctx, args, argsize);
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   595
	writeblockrequest(hgc, "validate");
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   596
	handleresponse(hgc);
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   597
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   598
	/* the server returns '\0' if it can handle our request */
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   599
	if (hgc->ctx.datasize <= 1) {
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   600
		return NULL;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   601
	}
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   602
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   603
	/* make sure the buffer is '\0' terminated */
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   604
	enlargecontext(&hgc->ctx, hgc->ctx.datasize + 1);
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   605
	hgc->ctx.data[hgc->ctx.datasize] = '\0';
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   606
	return unpackcmdargsnul(&hgc->ctx);
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   607
}
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   608
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   609
/*!
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   610
 * Execute the specified Mercurial command
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   611
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   612
 * @return result code
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   613
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   614
int hgc_runcommand(hgclient_t *hgc, const char *const args[], size_t argsize)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   615
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   616
	assert(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   617
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   618
	packcmdargs(&hgc->ctx, args, argsize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   619
	writeblockrequest(hgc, "runcommand");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   620
	handleresponse(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   621
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   622
	int32_t exitcode_n;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   623
	if (hgc->ctx.datasize != sizeof(exitcode_n)) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   624
		abortmsg("unexpected size of exitcode");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   625
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   626
	memcpy(&exitcode_n, hgc->ctx.data, sizeof(exitcode_n));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   627
	return ntohl(exitcode_n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   628
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   629
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   630
/*!
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   631
 * (Re-)send client's stdio channels so that the server can access to tty
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   632
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   633
void hgc_attachio(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   634
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   635
	assert(hgc);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   636
	if (!(hgc->capflags & CAP_ATTACHIO)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   637
		return;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   638
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   639
	attachio(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   640
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   641
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   642
/*!
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   643
 * Update server's environment variables
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   644
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   645
 * @param envp  list of environment variables in "NAME=VALUE" format,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   646
 *              terminated by NULL.
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   647
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   648
void hgc_setenv(hgclient_t *hgc, const char *const envp[])
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   649
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   650
	assert(hgc && envp);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   651
	if (!(hgc->capflags & CAP_SETENV)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   652
		return;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40109
diff changeset
   653
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   654
	packcmdargs(&hgc->ctx, envp, /*argsize*/ -1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   655
	writeblockrequest(hgc, "setenv");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   656
}