contrib/chg/hgclient.c
author Matt Harbison <matt_harbison@yahoo.com>
Tue, 08 Dec 2020 12:43:18 -0500
changeset 46098 1b5e0d0bdb05
parent 41361 763b45bc4483
child 46177 0c320e6032f1
permissions -rw-r--r--
hghave: update the check for virtualenv This started as `hghave --test-features` failing on Windows in `test-hghave.t`. IDK how this worked, as neither my Linux nor Windows machines have the old attribute with virtualenv 20.2.2, even on py2. I think this was noticed recently because 357d8415aa27 mentioned an AttributeError, and mitigated by making this py2 only. But as mentioned, this is also a problem on py2 (where the failure was observed). When I got this working by removing the attribute reference, the command in the test failed because the `--no-site-package` argument was removed some time ago. Therefore, this backs out 357d8415aa27 and references a known good attribute (which was done to suppress the warning about an unused import) that also ensures the command does not need the argument. Since there appears to be (minor) broken stuff on py3, manually apply the `no-py3` guard that was backed out of the check itself. Differential Revision: https://phab.mercurial-scm.org/D9547
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
35998
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
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    29
enum { CAP_GETENCODING = 0x0001,
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    30
       CAP_RUNCOMMAND = 0x0002,
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    31
       /* cHg extension: */
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    32
       CAP_ATTACHIO = 0x0100,
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    33
       CAP_CHDIR = 0x0200,
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    34
       CAP_SETENV = 0x0800,
40110
413b6b10fdd5 chg: upgrade client to use "setumask2" command
Yuya Nishihara <yuya@tcha.org>
parents: 35998
diff changeset
    35
       CAP_SETUMASK2 = 0x1000,
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    36
       CAP_VALIDATE = 0x2000,
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    37
       CAP_SETPROCNAME = 0x4000,
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    38
};
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
typedef struct {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    41
	const char *name;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    42
	unsigned int flag;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    43
} cappair_t;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    44
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    45
static const cappair_t captable[] = {
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    46
    {"getencoding", CAP_GETENCODING},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    47
    {"runcommand", CAP_RUNCOMMAND},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    48
    {"attachio", CAP_ATTACHIO},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    49
    {"chdir", CAP_CHDIR},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    50
    {"setenv", CAP_SETENV},
40110
413b6b10fdd5 chg: upgrade client to use "setumask2" command
Yuya Nishihara <yuya@tcha.org>
parents: 35998
diff changeset
    51
    {"setumask2", CAP_SETUMASK2},
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    52
    {"validate", CAP_VALIDATE},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    53
    {"setprocname", CAP_SETPROCNAME},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    54
    {NULL, 0}, /* terminator */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    55
};
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
typedef struct {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    58
	char ch;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    59
	char *data;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    60
	size_t maxdatasize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    61
	size_t datasize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    62
} context_t;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    63
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    64
struct hgclient_tag_ {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    65
	int sockfd;
29581
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    66
	pid_t pgid;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    67
	pid_t pid;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    68
	context_t ctx;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    69
	unsigned int capflags;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    70
};
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
static const size_t defaultdatasize = 4096;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    73
30738
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
    74
static void attachio(hgclient_t *hgc);
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
    75
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    76
static void initcontext(context_t *ctx)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    77
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    78
	ctx->ch = '\0';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    79
	ctx->data = malloc(defaultdatasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    80
	ctx->maxdatasize = (ctx->data) ? defaultdatasize : 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    81
	ctx->datasize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    82
	debugmsg("initialize context buffer with size %zu", ctx->maxdatasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    83
}
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
static void enlargecontext(context_t *ctx, size_t newsize)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    86
{
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
    87
	if (newsize <= ctx->maxdatasize) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    88
		return;
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
    89
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    90
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    91
	newsize = defaultdatasize *
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    92
	          ((newsize + defaultdatasize - 1) / defaultdatasize);
28166
c6e0c2533e5f chg: use mallocx and reallocx in hgclient
Jun Wu <quark@fb.com>
parents: 28160
diff changeset
    93
	ctx->data = reallocx(ctx->data, newsize);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    94
	ctx->maxdatasize = newsize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    95
	debugmsg("enlarge context buffer to %zu", ctx->maxdatasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    96
}
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
static void freecontext(context_t *ctx)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    99
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   100
	debugmsg("free context buffer");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   101
	free(ctx->data);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   102
	ctx->data = NULL;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   103
	ctx->maxdatasize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   104
	ctx->datasize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   105
}
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
/* Read channeled response from cmdserver */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   108
static void readchannel(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   109
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   110
	assert(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   111
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   112
	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
   113
	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
   114
		/* 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
   115
		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
   116
		exit(255);
8e5312f8df30 chg: downgrade "failed to read channel" from abortmsg to debugmsg
Jun Wu <quark@fb.com>
parents: 28535
diff changeset
   117
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   118
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   119
	uint32_t datasize_n;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   120
	rsize = recv(hgc->sockfd, &datasize_n, sizeof(datasize_n), 0);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   121
	if (rsize != sizeof(datasize_n)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   122
		abortmsg("failed to read data size");
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   123
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   124
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   125
	/* datasize denotes the maximum size to write if input request */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   126
	hgc->ctx.datasize = ntohl(datasize_n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   127
	enlargecontext(&hgc->ctx, hgc->ctx.datasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   128
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   129
	if (isupper(hgc->ctx.ch) && hgc->ctx.ch != 'S') {
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   130
		return; /* assumes input request */
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   131
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   132
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   133
	size_t cursize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   134
	while (cursize < hgc->ctx.datasize) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   135
		rsize = recv(hgc->sockfd, hgc->ctx.data + cursize,
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   136
		             hgc->ctx.datasize - cursize, 0);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   137
		if (rsize < 1) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   138
			abortmsg("failed to read data block");
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   139
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   140
		cursize += rsize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   141
	}
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
static void sendall(int sockfd, const void *data, size_t datasize)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   145
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   146
	const char *p = data;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   147
	const char *const endp = p + datasize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   148
	while (p < endp) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   149
		ssize_t r = send(sockfd, p, endp - p, 0);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   150
		if (r < 0) {
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   151
			abortmsgerrno("cannot communicate");
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   152
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   153
		p += r;
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
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   157
/* Write lengh-data block to cmdserver */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   158
static void writeblock(const hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   159
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   160
	assert(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   161
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   162
	const uint32_t datasize_n = htonl(hgc->ctx.datasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   163
	sendall(hgc->sockfd, &datasize_n, sizeof(datasize_n));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   164
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   165
	sendall(hgc->sockfd, hgc->ctx.data, hgc->ctx.datasize);
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
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   168
static void writeblockrequest(const hgclient_t *hgc, const char *chcmd)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   169
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   170
	debugmsg("request %s, block size %zu", chcmd, hgc->ctx.datasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   171
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   172
	char buf[strlen(chcmd) + 1];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   173
	memcpy(buf, chcmd, sizeof(buf) - 1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   174
	buf[sizeof(buf) - 1] = '\n';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   175
	sendall(hgc->sockfd, buf, sizeof(buf));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   176
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   177
	writeblock(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   178
}
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
/* 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
   181
 * terminated by NULL. */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   182
static void packcmdargs(context_t *ctx, const char *const args[],
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   183
                        ssize_t argsize)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   184
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   185
	ctx->datasize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   186
	const char *const *const end = (argsize >= 0) ? args + argsize : NULL;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   187
	for (const char *const *it = args; it != end && *it; ++it) {
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   188
		const size_t n = strlen(*it) + 1; /* include '\0' */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   189
		enlargecontext(ctx, ctx->datasize + n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   190
		memcpy(ctx->data + ctx->datasize, *it, n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   191
		ctx->datasize += n;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   192
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   193
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   194
	if (ctx->datasize > 0) {
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   195
		--ctx->datasize; /* strip last '\0' */
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   196
	}
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
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   199
/* 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
   200
static const char **unpackcmdargsnul(const context_t *ctx)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   201
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   202
	const char **args = NULL;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   203
	size_t nargs = 0, maxnargs = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   204
	const char *s = ctx->data;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   205
	const char *e = ctx->data + ctx->datasize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   206
	for (;;) {
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   207
		if (nargs + 1 >= maxnargs) { /* including last NULL */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   208
			maxnargs += 256;
28166
c6e0c2533e5f chg: use mallocx and reallocx in hgclient
Jun Wu <quark@fb.com>
parents: 28160
diff changeset
   209
			args = reallocx(args, maxnargs * sizeof(args[0]));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   210
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   211
		args[nargs] = s;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   212
		nargs++;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   213
		s = memchr(s, '\0', e - s);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   214
		if (!s) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   215
			break;
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   216
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   217
		s++;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   218
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   219
	args[nargs] = NULL;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   220
	return args;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   221
}
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
static void handlereadrequest(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   224
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   225
	context_t *ctx = &hgc->ctx;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   226
	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
   227
	ctx->datasize = r;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   228
	writeblock(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   229
}
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
/* Read single-line */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   232
static void handlereadlinerequest(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   233
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   234
	context_t *ctx = &hgc->ctx;
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   235
	if (!fgets(ctx->data, ctx->datasize, stdin)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   236
		ctx->data[0] = '\0';
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   237
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   238
	ctx->datasize = strlen(ctx->data);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   239
	writeblock(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   240
}
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
/* Execute the requested command and write exit code */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   243
static void handlesystemrequest(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   244
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   245
	context_t *ctx = &hgc->ctx;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   246
	enlargecontext(ctx, ctx->datasize + 1);
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   247
	ctx->data[ctx->datasize] = '\0'; /* terminate last string */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   248
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   249
	const char **args = unpackcmdargsnul(ctx);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   250
	if (!args[0] || !args[1] || !args[2]) {
30726
dd897eb1699e chg: send type information via S channel (BC)
Jun Wu <quark@fb.com>
parents: 30682
diff changeset
   251
		abortmsg("missing type or command or cwd in system request");
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   252
	}
30728
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   253
	if (strcmp(args[0], "system") == 0) {
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   254
		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
   255
		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
   256
		free(args);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   257
30728
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   258
		uint32_t r_n = htonl(r);
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   259
		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
   260
		ctx->datasize = sizeof(r_n);
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   261
		writeblock(hgc);
30738
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   262
	} else if (strcmp(args[0], "pager") == 0) {
31941
ac5527021097 chg: respect environment variables for pager
Jun Wu <quark@fb.com>
parents: 30756
diff changeset
   263
		setuppager(args[1], args + 3);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   264
		if (hgc->capflags & CAP_ATTACHIO) {
30738
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   265
			attachio(hgc);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   266
		}
30738
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   267
		/* unblock the server */
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   268
		static const char emptycmd[] = "\n";
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   269
		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
   270
	} else {
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   271
		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
   272
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   273
}
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
/* Read response of command execution until receiving 'r'-esult */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   276
static void handleresponse(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   277
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   278
	for (;;) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   279
		readchannel(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   280
		context_t *ctx = &hgc->ctx;
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   281
		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
   282
		         ctx->datasize);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   283
		switch (ctx->ch) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   284
		case 'o':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   285
			fwrite(ctx->data, sizeof(ctx->data[0]), ctx->datasize,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   286
			       stdout);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   287
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   288
		case 'e':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   289
			fwrite(ctx->data, sizeof(ctx->data[0]), ctx->datasize,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   290
			       stderr);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   291
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   292
		case 'd':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   293
			/* assumes last char is '\n' */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   294
			ctx->data[ctx->datasize - 1] = '\0';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   295
			debugmsg("server: %s", ctx->data);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   296
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   297
		case 'r':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   298
			return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   299
		case 'I':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   300
			handlereadrequest(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   301
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   302
		case 'L':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   303
			handlereadlinerequest(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   304
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   305
		case 'S':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   306
			handlesystemrequest(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   307
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   308
		default:
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   309
			if (isupper(ctx->ch)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   310
				abortmsg("cannot handle response (ch = %c)",
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   311
				         ctx->ch);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   312
			}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   313
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   314
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   315
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   316
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   317
static unsigned int parsecapabilities(const char *s, const char *e)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   318
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   319
	unsigned int flags = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   320
	while (s < e) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   321
		const char *t = strchr(s, ' ');
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   322
		if (!t || t > e) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   323
			t = e;
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   324
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   325
		const cappair_t *cap;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   326
		for (cap = captable; cap->flag; ++cap) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   327
			size_t n = t - s;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   328
			if (strncmp(s, cap->name, n) == 0 &&
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   329
			    strlen(cap->name) == n) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   330
				flags |= cap->flag;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   331
				break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   332
			}
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
		s = t + 1;
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
	return flags;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   337
}
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
static void readhello(hgclient_t *hgc)
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
	readchannel(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   342
	context_t *ctx = &hgc->ctx;
28512
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   343
	if (ctx->ch != 'o') {
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   344
		char ch = ctx->ch;
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   345
		if (ch == 'e') {
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   346
			/* write early error and will exit */
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   347
			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
   348
			       stderr);
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   349
			handleresponse(hgc);
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   350
		}
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   351
		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
   352
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   353
	enlargecontext(ctx, ctx->datasize + 1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   354
	ctx->data[ctx->datasize] = '\0';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   355
	debugmsg("hello received: %s (size = %zu)", ctx->data, ctx->datasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   356
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   357
	const char *s = ctx->data;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   358
	const char *const dataend = ctx->data + ctx->datasize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   359
	while (s < dataend) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   360
		const char *t = strchr(s, ':');
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   361
		if (!t || t[1] != ' ') {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   362
			break;
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   363
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   364
		const char *u = strchr(t + 2, '\n');
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   365
		if (!u) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   366
			u = dataend;
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   367
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   368
		if (strncmp(s, "capabilities:", t - s + 1) == 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   369
			hgc->capflags = parsecapabilities(t + 2, u);
29581
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   370
		} 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
   371
			hgc->pgid = strtol(t + 2, NULL, 10);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   372
		} else if (strncmp(s, "pid:", t - s + 1) == 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   373
			hgc->pid = strtol(t + 2, NULL, 10);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   374
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   375
		s = u + 1;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   376
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   377
	debugmsg("capflags=0x%04x, pid=%d", hgc->capflags, hgc->pid);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   378
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   379
30751
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   380
static void updateprocname(hgclient_t *hgc)
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   381
{
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   382
	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
   383
	                 (int)getpid());
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   384
	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
   385
		abortmsg("insufficient buffer to write procname (r = %d)", r);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   386
	}
30756
1f9684fe94cc chg: check snprintf result strictly
Jun Wu <quark@fb.com>
parents: 30751
diff changeset
   387
	hgc->ctx.datasize = (size_t)r;
30751
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   388
	writeblockrequest(hgc, "setprocname");
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   389
}
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   390
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   391
static void attachio(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   392
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   393
	debugmsg("request attachio");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   394
	static const char chcmd[] = "attachio\n";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   395
	sendall(hgc->sockfd, chcmd, sizeof(chcmd) - 1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   396
	readchannel(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   397
	context_t *ctx = &hgc->ctx;
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   398
	if (ctx->ch != 'I') {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   399
		abortmsg("unexpected response for attachio (ch = %c)", ctx->ch);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   400
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   401
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   402
	static const int fds[3] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   403
	struct msghdr msgh;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   404
	memset(&msgh, 0, sizeof(msgh));
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   405
	struct iovec iov = {ctx->data, ctx->datasize}; /* dummy payload */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   406
	msgh.msg_iov = &iov;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   407
	msgh.msg_iovlen = 1;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   408
	char fdbuf[CMSG_SPACE(sizeof(fds))];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   409
	msgh.msg_control = fdbuf;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   410
	msgh.msg_controllen = sizeof(fdbuf);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   411
	struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msgh);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   412
	cmsg->cmsg_level = SOL_SOCKET;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   413
	cmsg->cmsg_type = SCM_RIGHTS;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   414
	cmsg->cmsg_len = CMSG_LEN(sizeof(fds));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   415
	memcpy(CMSG_DATA(cmsg), fds, sizeof(fds));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   416
	msgh.msg_controllen = cmsg->cmsg_len;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   417
	ssize_t r = sendmsg(hgc->sockfd, &msgh, 0);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   418
	if (r < 0) {
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   419
		abortmsgerrno("sendmsg failed");
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   420
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   421
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   422
	handleresponse(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   423
	int32_t n;
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   424
	if (ctx->datasize != sizeof(n)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   425
		abortmsg("unexpected size of attachio result");
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   426
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   427
	memcpy(&n, ctx->data, sizeof(n));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   428
	n = ntohl(n);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   429
	if (n != sizeof(fds) / sizeof(fds[0])) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   430
		abortmsg("failed to send fds (n = %d)", n);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   431
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   432
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   433
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   434
static void chdirtocwd(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   435
{
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   436
	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
   437
		abortmsgerrno("failed to getcwd");
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   438
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   439
	hgc->ctx.datasize = strlen(hgc->ctx.data);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   440
	writeblockrequest(hgc, "chdir");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   441
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   442
28160
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   443
static void forwardumask(hgclient_t *hgc)
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   444
{
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   445
	mode_t mask = umask(0);
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   446
	umask(mask);
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   447
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   448
	uint32_t data = htonl(mask);
40110
413b6b10fdd5 chg: upgrade client to use "setumask2" command
Yuya Nishihara <yuya@tcha.org>
parents: 35998
diff changeset
   449
	enlargecontext(&hgc->ctx, sizeof(data));
413b6b10fdd5 chg: upgrade client to use "setumask2" command
Yuya Nishihara <yuya@tcha.org>
parents: 35998
diff changeset
   450
	memcpy(hgc->ctx.data, &data, sizeof(data));
413b6b10fdd5 chg: upgrade client to use "setumask2" command
Yuya Nishihara <yuya@tcha.org>
parents: 35998
diff changeset
   451
	hgc->ctx.datasize = sizeof(data);
413b6b10fdd5 chg: upgrade client to use "setumask2" command
Yuya Nishihara <yuya@tcha.org>
parents: 35998
diff changeset
   452
	writeblockrequest(hgc, "setumask2");
28160
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   453
}
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   454
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   455
/*!
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   456
 * Open connection to per-user cmdserver
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   457
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   458
 * If no background server running, returns NULL.
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   459
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   460
hgclient_t *hgc_open(const char *sockname)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   461
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   462
	int fd = socket(AF_UNIX, SOCK_STREAM, 0);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   463
	if (fd < 0) {
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   464
		abortmsgerrno("cannot create socket");
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   465
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   466
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   467
	/* 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
   468
	 * 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
   469
	fsetcloexec(fd);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   470
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   471
	struct sockaddr_un addr;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   472
	addr.sun_family = AF_UNIX;
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   473
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   474
	/* use chdir to workaround small sizeof(sun_path) */
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   475
	int bakfd = -1;
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   476
	const char *basename = sockname;
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   477
	{
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   478
		const char *split = strrchr(sockname, '/');
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   479
		if (split && split != sockname) {
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   480
			if (split[1] == '\0') {
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   481
				abortmsg("sockname cannot end with a slash");
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   482
			}
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   483
			size_t len = split - sockname;
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   484
			char sockdir[len + 1];
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   485
			memcpy(sockdir, sockname, len);
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   486
			sockdir[len] = '\0';
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   487
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   488
			bakfd = open(".", O_DIRECTORY);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   489
			if (bakfd == -1) {
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   490
				abortmsgerrno("cannot open cwd");
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   491
			}
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   492
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   493
			int r = chdir(sockdir);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   494
			if (r != 0) {
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   495
				abortmsgerrno("cannot chdir %s", sockdir);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   496
			}
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   497
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   498
			basename = split + 1;
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   499
		}
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   500
	}
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   501
	if (strlen(basename) >= sizeof(addr.sun_path)) {
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   502
		abortmsg("sockname is too long: %s", basename);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   503
	}
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   504
	strncpy(addr.sun_path, basename, sizeof(addr.sun_path));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   505
	addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   506
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   507
	/* real connect */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   508
	int r = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
30682
fe11f466880d chg: handle connect failure before errno gets overridden
Jun Wu <quark@fb.com>
parents: 30678
diff changeset
   509
	if (r < 0) {
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   510
		if (errno != ENOENT && errno != ECONNREFUSED) {
30682
fe11f466880d chg: handle connect failure before errno gets overridden
Jun Wu <quark@fb.com>
parents: 30678
diff changeset
   511
			abortmsgerrno("cannot connect to %s", sockname);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   512
		}
30682
fe11f466880d chg: handle connect failure before errno gets overridden
Jun Wu <quark@fb.com>
parents: 30678
diff changeset
   513
	}
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   514
	if (bakfd != -1) {
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   515
		fchdirx(bakfd);
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   516
		close(bakfd);
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   517
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   518
	if (r < 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   519
		close(fd);
30682
fe11f466880d chg: handle connect failure before errno gets overridden
Jun Wu <quark@fb.com>
parents: 30678
diff changeset
   520
		return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   521
	}
28769
222f482930c8 chg: make connect debug message less repetitive
Jun Wu <quark@fb.com>
parents: 28551
diff changeset
   522
	debugmsg("connected to %s", addr.sun_path);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   523
28166
c6e0c2533e5f chg: use mallocx and reallocx in hgclient
Jun Wu <quark@fb.com>
parents: 28160
diff changeset
   524
	hgclient_t *hgc = mallocx(sizeof(hgclient_t));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   525
	memset(hgc, 0, sizeof(*hgc));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   526
	hgc->sockfd = fd;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   527
	initcontext(&hgc->ctx);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   528
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   529
	readhello(hgc);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   530
	if (!(hgc->capflags & CAP_RUNCOMMAND)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   531
		abortmsg("insufficient capability: runcommand");
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   532
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   533
	if (hgc->capflags & CAP_SETPROCNAME) {
30751
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   534
		updateprocname(hgc);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   535
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   536
	if (hgc->capflags & CAP_ATTACHIO) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   537
		attachio(hgc);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   538
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   539
	if (hgc->capflags & CAP_CHDIR) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   540
		chdirtocwd(hgc);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   541
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   542
	if (hgc->capflags & CAP_SETUMASK2) {
28160
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   543
		forwardumask(hgc);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   544
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   545
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   546
	return hgc;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   547
}
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
 * Close connection and free allocated memory
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   551
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   552
void hgc_close(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   553
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   554
	assert(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   555
	freecontext(&hgc->ctx);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   556
	close(hgc->sockfd);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   557
	free(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   558
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   559
29581
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   560
pid_t hgc_peerpgid(const hgclient_t *hgc)
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   561
{
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   562
	assert(hgc);
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   563
	return hgc->pgid;
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   564
}
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   565
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   566
pid_t hgc_peerpid(const hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   567
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   568
	assert(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   569
	return hgc->pid;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   570
}
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
/*!
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   573
 * 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
   574
 * whether it can process our request directly or not.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   575
 * Make sure hgc_setenv is called before calling this.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   576
 *
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   577
 * @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
   578
 *           support "validate" command.
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28512
diff changeset
   579
 *         - 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
   580
 *           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
   581
 *           chgserver.py for possible instruction formats.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   582
 *           the list should be freed by the caller.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   583
 *           the last string is guaranteed to be NULL.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   584
 */
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   585
const char **hgc_validate(hgclient_t *hgc, const char *const args[],
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   586
                          size_t argsize)
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   587
{
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   588
	assert(hgc);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   589
	if (!(hgc->capflags & CAP_VALIDATE)) {
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   590
		return NULL;
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   591
	}
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   592
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   593
	packcmdargs(&hgc->ctx, args, argsize);
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   594
	writeblockrequest(hgc, "validate");
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   595
	handleresponse(hgc);
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   596
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   597
	/* the server returns '\0' if it can handle our request */
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   598
	if (hgc->ctx.datasize <= 1) {
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   599
		return NULL;
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   600
	}
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   601
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   602
	/* make sure the buffer is '\0' terminated */
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   603
	enlargecontext(&hgc->ctx, hgc->ctx.datasize + 1);
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   604
	hgc->ctx.data[hgc->ctx.datasize] = '\0';
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   605
	return unpackcmdargsnul(&hgc->ctx);
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   606
}
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
/*!
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   609
 * Execute the specified Mercurial command
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   610
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   611
 * @return result code
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   612
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   613
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
   614
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   615
	assert(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   616
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   617
	packcmdargs(&hgc->ctx, args, argsize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   618
	writeblockrequest(hgc, "runcommand");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   619
	handleresponse(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   620
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   621
	int32_t exitcode_n;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   622
	if (hgc->ctx.datasize != sizeof(exitcode_n)) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   623
		abortmsg("unexpected size of exitcode");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   624
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   625
	memcpy(&exitcode_n, hgc->ctx.data, sizeof(exitcode_n));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   626
	return ntohl(exitcode_n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   627
}
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
 * (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
   631
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   632
void hgc_attachio(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   633
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   634
	assert(hgc);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   635
	if (!(hgc->capflags & CAP_ATTACHIO)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   636
		return;
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   637
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   638
	attachio(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   639
}
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
 * Update server's environment variables
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   643
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   644
 * @param envp  list of environment variables in "NAME=VALUE" format,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   645
 *              terminated by NULL.
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   646
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   647
void hgc_setenv(hgclient_t *hgc, const char *const envp[])
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   648
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   649
	assert(hgc && envp);
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   650
	if (!(hgc->capflags & CAP_SETENV)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   651
		return;
41361
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 40110
diff changeset
   652
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   653
	packcmdargs(&hgc->ctx, envp, /*argsize*/ -1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   654
	writeblockrequest(hgc, "setenv");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   655
}