contrib/chg/hgclient.c
author Gregory Szorc <gregory.szorc@gmail.com>
Fri, 06 Apr 2018 17:21:16 -0700
changeset 37536 2003da12f49b
parent 35998 9724f54923ec
child 40110 413b6b10fdd5
permissions -rw-r--r--
wireproto: only expose "clonebundles" to version 1 transports This may make a comeback in wire protocol version 2. The feature definitely needs to be carried forward. But at this juncture, I'm flirting with the idea of implementing this via a "redirect" mechanism at the command response level itself rather than something that requires one-off client support for querying and handling. i.e. I want to make it so servers can say "fetch this first and then come back" and clients handle that automatically. This would not only support clone bundles, but would also support piece-meal "pull bundles." Whatever happens, we can deal with it down the road. Differential Revision: https://phab.mercurial-scm.org/D3203
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,
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    35
       CAP_SETUMASK = 0x1000,
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},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    51
    {"setumask", CAP_SETUMASK},
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
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    87
	if (newsize <= ctx->maxdatasize)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    88
		return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    89
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    90
	newsize = defaultdatasize *
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    91
	          ((newsize + defaultdatasize - 1) / defaultdatasize);
28166
c6e0c2533e5f chg: use mallocx and reallocx in hgclient
Jun Wu <quark@fb.com>
parents: 28160
diff changeset
    92
	ctx->data = reallocx(ctx->data, newsize);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    93
	ctx->maxdatasize = newsize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    94
	debugmsg("enlarge context buffer to %zu", ctx->maxdatasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    95
}
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
static void freecontext(context_t *ctx)
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
	debugmsg("free context buffer");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   100
	free(ctx->data);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   101
	ctx->data = NULL;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   102
	ctx->maxdatasize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   103
	ctx->datasize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   104
}
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
/* Read channeled response from cmdserver */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   107
static void readchannel(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   108
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   109
	assert(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
	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
   112
	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
   113
		/* 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
   114
		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
   115
		exit(255);
8e5312f8df30 chg: downgrade "failed to read channel" from abortmsg to debugmsg
Jun Wu <quark@fb.com>
parents: 28535
diff changeset
   116
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   117
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   118
	uint32_t datasize_n;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   119
	rsize = recv(hgc->sockfd, &datasize_n, sizeof(datasize_n), 0);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   120
	if (rsize != sizeof(datasize_n))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   121
		abortmsg("failed to read data size");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   122
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   123
	/* datasize denotes the maximum size to write if input request */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   124
	hgc->ctx.datasize = ntohl(datasize_n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   125
	enlargecontext(&hgc->ctx, hgc->ctx.datasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   126
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   127
	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
   128
		return; /* assumes input request */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   129
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   130
	size_t cursize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   131
	while (cursize < hgc->ctx.datasize) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   132
		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
   133
		             hgc->ctx.datasize - cursize, 0);
29731
acf27be56d26 chg: just take it as EOF if recv() returns 0
Yuya Nishihara <yuya@tcha.org>
parents: 29602
diff changeset
   134
		if (rsize < 1)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   135
			abortmsg("failed to read data block");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   136
		cursize += rsize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   137
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   138
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   139
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   140
static void sendall(int sockfd, const void *data, size_t datasize)
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
	const char *p = data;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   143
	const char *const endp = p + datasize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   144
	while (p < endp) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   145
		ssize_t r = send(sockfd, p, endp - p, 0);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   146
		if (r < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   147
			abortmsgerrno("cannot communicate");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   148
		p += r;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   149
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   150
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   151
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   152
/* Write lengh-data block to cmdserver */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   153
static void writeblock(const hgclient_t *hgc)
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
	assert(hgc);
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
	const uint32_t datasize_n = htonl(hgc->ctx.datasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   158
	sendall(hgc->sockfd, &datasize_n, sizeof(datasize_n));
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
	sendall(hgc->sockfd, hgc->ctx.data, hgc->ctx.datasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   161
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   162
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   163
static void writeblockrequest(const hgclient_t *hgc, const char *chcmd)
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
	debugmsg("request %s, block size %zu", chcmd, 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
	char buf[strlen(chcmd) + 1];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   168
	memcpy(buf, chcmd, sizeof(buf) - 1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   169
	buf[sizeof(buf) - 1] = '\n';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   170
	sendall(hgc->sockfd, buf, sizeof(buf));
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
	writeblock(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   173
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   174
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   175
/* 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
   176
 * terminated by NULL. */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   177
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
   178
                        ssize_t argsize)
28060
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
	ctx->datasize = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   181
	const char *const *const end = (argsize >= 0) ? args + argsize : NULL;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   182
	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
   183
		const size_t n = strlen(*it) + 1; /* include '\0' */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   184
		enlargecontext(ctx, ctx->datasize + n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   185
		memcpy(ctx->data + ctx->datasize, *it, n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   186
		ctx->datasize += n;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   187
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   188
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   189
	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
   190
		--ctx->datasize; /* strip last '\0' */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   191
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   192
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   193
/* 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
   194
static const char **unpackcmdargsnul(const context_t *ctx)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   195
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   196
	const char **args = NULL;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   197
	size_t nargs = 0, maxnargs = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   198
	const char *s = ctx->data;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   199
	const char *e = ctx->data + ctx->datasize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   200
	for (;;) {
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   201
		if (nargs + 1 >= maxnargs) { /* including last NULL */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   202
			maxnargs += 256;
28166
c6e0c2533e5f chg: use mallocx and reallocx in hgclient
Jun Wu <quark@fb.com>
parents: 28160
diff changeset
   203
			args = reallocx(args, maxnargs * sizeof(args[0]));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   204
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   205
		args[nargs] = s;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   206
		nargs++;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   207
		s = memchr(s, '\0', e - s);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   208
		if (!s)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   209
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   210
		s++;
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] = NULL;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   213
	return args;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   214
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   215
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   216
static void handlereadrequest(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   217
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   218
	context_t *ctx = &hgc->ctx;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   219
	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
   220
	ctx->datasize = r;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   221
	writeblock(hgc);
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
/* Read single-line */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   225
static void handlereadlinerequest(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   226
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   227
	context_t *ctx = &hgc->ctx;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   228
	if (!fgets(ctx->data, ctx->datasize, stdin))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   229
		ctx->data[0] = '\0';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   230
	ctx->datasize = strlen(ctx->data);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   231
	writeblock(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   232
}
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
/* Execute the requested command and write exit code */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   235
static void handlesystemrequest(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   236
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   237
	context_t *ctx = &hgc->ctx;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   238
	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
   239
	ctx->data[ctx->datasize] = '\0'; /* terminate last string */
28060
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
	const char **args = unpackcmdargsnul(ctx);
30726
dd897eb1699e chg: send type information via S channel (BC)
Jun Wu <quark@fb.com>
parents: 30682
diff changeset
   242
	if (!args[0] || !args[1] || !args[2])
dd897eb1699e chg: send type information via S channel (BC)
Jun Wu <quark@fb.com>
parents: 30682
diff changeset
   243
		abortmsg("missing type or command or cwd in system request");
30728
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   244
	if (strcmp(args[0], "system") == 0) {
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   245
		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
   246
		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
   247
		free(args);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   248
30728
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   249
		uint32_t r_n = htonl(r);
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   250
		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
   251
		ctx->datasize = sizeof(r_n);
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   252
		writeblock(hgc);
30738
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   253
	} else if (strcmp(args[0], "pager") == 0) {
31941
ac5527021097 chg: respect environment variables for pager
Jun Wu <quark@fb.com>
parents: 30756
diff changeset
   254
		setuppager(args[1], args + 3);
30738
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   255
		if (hgc->capflags & CAP_ATTACHIO)
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   256
			attachio(hgc);
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   257
		/* unblock the server */
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   258
		static const char emptycmd[] = "\n";
a45c0f42271f chg: handle pager request client-side
Jun Wu <quark@fb.com>
parents: 30728
diff changeset
   259
		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
   260
	} else {
7438cb35979a chg: check type read from S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   261
		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
   262
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   263
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   264
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   265
/* Read response of command execution until receiving 'r'-esult */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   266
static void handleresponse(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   267
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   268
	for (;;) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   269
		readchannel(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   270
		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
   271
		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
   272
		         ctx->datasize);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   273
		switch (ctx->ch) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   274
		case 'o':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   275
			fwrite(ctx->data, sizeof(ctx->data[0]), ctx->datasize,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   276
			       stdout);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   277
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   278
		case 'e':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   279
			fwrite(ctx->data, sizeof(ctx->data[0]), ctx->datasize,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   280
			       stderr);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   281
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   282
		case 'd':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   283
			/* assumes last char is '\n' */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   284
			ctx->data[ctx->datasize - 1] = '\0';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   285
			debugmsg("server: %s", ctx->data);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   286
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   287
		case 'r':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   288
			return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   289
		case 'I':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   290
			handlereadrequest(hgc);
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 'L':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   293
			handlereadlinerequest(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   294
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   295
		case 'S':
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   296
			handlesystemrequest(hgc);
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
		default:
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   299
			if (isupper(ctx->ch))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   300
				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
   301
				         ctx->ch);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   302
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   303
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   304
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   305
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   306
static unsigned int parsecapabilities(const char *s, const char *e)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   307
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   308
	unsigned int flags = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   309
	while (s < e) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   310
		const char *t = strchr(s, ' ');
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   311
		if (!t || t > e)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   312
			t = e;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   313
		const cappair_t *cap;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   314
		for (cap = captable; cap->flag; ++cap) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   315
			size_t n = t - s;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   316
			if (strncmp(s, cap->name, n) == 0 &&
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   317
			    strlen(cap->name) == n) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   318
				flags |= cap->flag;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   319
				break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   320
			}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   321
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   322
		s = t + 1;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   323
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   324
	return flags;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   325
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   326
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   327
static void readhello(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   328
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   329
	readchannel(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   330
	context_t *ctx = &hgc->ctx;
28512
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   331
	if (ctx->ch != 'o') {
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   332
		char ch = ctx->ch;
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   333
		if (ch == 'e') {
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   334
			/* write early error and will exit */
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   335
			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
   336
			       stderr);
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   337
			handleresponse(hgc);
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   338
		}
b957b4c6cad8 chg: provide early exception to user
Yuya Nishihara <yuya@tcha.org>
parents: 28356
diff changeset
   339
		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
   340
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   341
	enlargecontext(ctx, ctx->datasize + 1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   342
	ctx->data[ctx->datasize] = '\0';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   343
	debugmsg("hello received: %s (size = %zu)", ctx->data, ctx->datasize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   344
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   345
	const char *s = ctx->data;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   346
	const char *const dataend = ctx->data + ctx->datasize;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   347
	while (s < dataend) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   348
		const char *t = strchr(s, ':');
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   349
		if (!t || t[1] != ' ')
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   350
			break;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   351
		const char *u = strchr(t + 2, '\n');
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   352
		if (!u)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   353
			u = dataend;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   354
		if (strncmp(s, "capabilities:", t - s + 1) == 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   355
			hgc->capflags = parsecapabilities(t + 2, u);
29581
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   356
		} 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
   357
			hgc->pgid = strtol(t + 2, NULL, 10);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   358
		} else if (strncmp(s, "pid:", t - s + 1) == 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   359
			hgc->pid = strtol(t + 2, NULL, 10);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   360
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   361
		s = u + 1;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   362
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   363
	debugmsg("capflags=0x%04x, pid=%d", hgc->capflags, hgc->pid);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   364
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   365
30751
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   366
static void updateprocname(hgclient_t *hgc)
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   367
{
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   368
	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
   369
	                 (int)getpid());
30756
1f9684fe94cc chg: check snprintf result strictly
Jun Wu <quark@fb.com>
parents: 30751
diff changeset
   370
	if (r < 0 || (size_t)r >= hgc->ctx.maxdatasize)
1f9684fe94cc chg: check snprintf result strictly
Jun Wu <quark@fb.com>
parents: 30751
diff changeset
   371
		abortmsg("insufficient buffer to write procname (r = %d)", r);
1f9684fe94cc chg: check snprintf result strictly
Jun Wu <quark@fb.com>
parents: 30751
diff changeset
   372
	hgc->ctx.datasize = (size_t)r;
30751
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   373
	writeblockrequest(hgc, "setprocname");
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   374
}
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   375
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   376
static void attachio(hgclient_t *hgc)
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("request attachio");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   379
	static const char chcmd[] = "attachio\n";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   380
	sendall(hgc->sockfd, chcmd, sizeof(chcmd) - 1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   381
	readchannel(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   382
	context_t *ctx = &hgc->ctx;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   383
	if (ctx->ch != 'I')
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   384
		abortmsg("unexpected response for attachio (ch = %c)", ctx->ch);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   385
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   386
	static const int fds[3] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   387
	struct msghdr msgh;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   388
	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
   389
	struct iovec iov = {ctx->data, ctx->datasize}; /* dummy payload */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   390
	msgh.msg_iov = &iov;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   391
	msgh.msg_iovlen = 1;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   392
	char fdbuf[CMSG_SPACE(sizeof(fds))];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   393
	msgh.msg_control = fdbuf;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   394
	msgh.msg_controllen = sizeof(fdbuf);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   395
	struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msgh);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   396
	cmsg->cmsg_level = SOL_SOCKET;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   397
	cmsg->cmsg_type = SCM_RIGHTS;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   398
	cmsg->cmsg_len = CMSG_LEN(sizeof(fds));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   399
	memcpy(CMSG_DATA(cmsg), fds, sizeof(fds));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   400
	msgh.msg_controllen = cmsg->cmsg_len;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   401
	ssize_t r = sendmsg(hgc->sockfd, &msgh, 0);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   402
	if (r < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   403
		abortmsgerrno("sendmsg failed");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   404
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   405
	handleresponse(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   406
	int32_t n;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   407
	if (ctx->datasize != sizeof(n))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   408
		abortmsg("unexpected size of attachio result");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   409
	memcpy(&n, ctx->data, sizeof(n));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   410
	n = ntohl(n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   411
	if (n != sizeof(fds) / sizeof(fds[0]))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   412
		abortmsg("failed to send fds (n = %d)", n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   413
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   414
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   415
static void chdirtocwd(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   416
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   417
	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
   418
		abortmsgerrno("failed to getcwd");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   419
	hgc->ctx.datasize = strlen(hgc->ctx.data);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   420
	writeblockrequest(hgc, "chdir");
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
28160
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   423
static void forwardumask(hgclient_t *hgc)
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   424
{
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   425
	mode_t mask = umask(0);
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   426
	umask(mask);
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   427
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   428
	static const char command[] = "setumask\n";
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   429
	sendall(hgc->sockfd, command, sizeof(command) - 1);
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   430
	uint32_t data = htonl(mask);
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   431
	sendall(hgc->sockfd, &data, sizeof(data));
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   432
}
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   433
28060
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
 * Open connection to per-user cmdserver
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   436
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   437
 * If no background server running, returns NULL.
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   438
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   439
hgclient_t *hgc_open(const char *sockname)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   440
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   441
	int fd = socket(AF_UNIX, SOCK_STREAM, 0);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   442
	if (fd < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   443
		abortmsgerrno("cannot create socket");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   444
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   445
	/* 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
   446
	 * 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
   447
	fsetcloexec(fd);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   448
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   449
	struct sockaddr_un addr;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   450
	addr.sun_family = AF_UNIX;
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   451
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   452
	/* 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
   453
	int bakfd = -1;
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   454
	const char *basename = sockname;
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   455
	{
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   456
		const char *split = strrchr(sockname, '/');
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   457
		if (split && split != sockname) {
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   458
			if (split[1] == '\0')
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   459
				abortmsg("sockname cannot end with a slash");
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   460
			size_t len = split - sockname;
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   461
			char sockdir[len + 1];
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   462
			memcpy(sockdir, sockname, len);
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   463
			sockdir[len] = '\0';
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   464
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   465
			bakfd = open(".", O_DIRECTORY);
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   466
			if (bakfd == -1)
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   467
				abortmsgerrno("cannot open cwd");
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   468
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   469
			int r = chdir(sockdir);
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   470
			if (r != 0)
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   471
				abortmsgerrno("cannot chdir %s", sockdir);
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   472
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   473
			basename = split + 1;
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   474
		}
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   475
	}
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   476
	if (strlen(basename) >= sizeof(addr.sun_path))
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   477
		abortmsg("sockname is too long: %s", basename);
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   478
	strncpy(addr.sun_path, basename, sizeof(addr.sun_path));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   479
	addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   480
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   481
	/* real connect */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   482
	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
   483
	if (r < 0) {
fe11f466880d chg: handle connect failure before errno gets overridden
Jun Wu <quark@fb.com>
parents: 30678
diff changeset
   484
		if (errno != ENOENT && errno != ECONNREFUSED)
fe11f466880d chg: handle connect failure before errno gets overridden
Jun Wu <quark@fb.com>
parents: 30678
diff changeset
   485
			abortmsgerrno("cannot connect to %s", sockname);
fe11f466880d chg: handle connect failure before errno gets overridden
Jun Wu <quark@fb.com>
parents: 30678
diff changeset
   486
	}
30678
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   487
	if (bakfd != -1) {
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   488
		fchdirx(bakfd);
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   489
		close(bakfd);
112915e9a363 chg: let hgc_open support long path
Jun Wu <quark@fb.com>
parents: 29731
diff changeset
   490
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   491
	if (r < 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   492
		close(fd);
30682
fe11f466880d chg: handle connect failure before errno gets overridden
Jun Wu <quark@fb.com>
parents: 30678
diff changeset
   493
		return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   494
	}
28769
222f482930c8 chg: make connect debug message less repetitive
Jun Wu <quark@fb.com>
parents: 28551
diff changeset
   495
	debugmsg("connected to %s", addr.sun_path);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   496
28166
c6e0c2533e5f chg: use mallocx and reallocx in hgclient
Jun Wu <quark@fb.com>
parents: 28160
diff changeset
   497
	hgclient_t *hgc = mallocx(sizeof(hgclient_t));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   498
	memset(hgc, 0, sizeof(*hgc));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   499
	hgc->sockfd = fd;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   500
	initcontext(&hgc->ctx);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   501
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   502
	readhello(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   503
	if (!(hgc->capflags & CAP_RUNCOMMAND))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   504
		abortmsg("insufficient capability: runcommand");
30751
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   505
	if (hgc->capflags & CAP_SETPROCNAME)
e882c7bb5a0b chg: change server's process title
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   506
		updateprocname(hgc);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   507
	if (hgc->capflags & CAP_ATTACHIO)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   508
		attachio(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   509
	if (hgc->capflags & CAP_CHDIR)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   510
		chdirtocwd(hgc);
28160
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   511
	if (hgc->capflags & CAP_SETUMASK)
098cb7bd46a7 chg: forward umask from client to server
Jun Wu <quark@fb.com>
parents: 28060
diff changeset
   512
		forwardumask(hgc);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   513
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   514
	return hgc;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   515
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   516
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   517
/*!
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   518
 * Close connection and free allocated memory
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   519
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   520
void hgc_close(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   521
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   522
	assert(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   523
	freecontext(&hgc->ctx);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   524
	close(hgc->sockfd);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   525
	free(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   526
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   527
29581
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   528
pid_t hgc_peerpgid(const hgclient_t *hgc)
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   529
{
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   530
	assert(hgc);
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   531
	return hgc->pgid;
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   532
}
c66bc06f1bf6 chg: add pgid to hgclient struct
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
   533
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   534
pid_t hgc_peerpid(const hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   535
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   536
	assert(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   537
	return hgc->pid;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   538
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   539
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   540
/*!
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   541
 * 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
   542
 * whether it can process our request directly or not.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   543
 * Make sure hgc_setenv is called before calling this.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   544
 *
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   545
 * @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
   546
 *           support "validate" command.
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28512
diff changeset
   547
 *         - 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
   548
 *           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
   549
 *           chgserver.py for possible instruction formats.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   550
 *           the list should be freed by the caller.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   551
 *           the last string is guaranteed to be NULL.
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   552
 */
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   553
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
   554
                          size_t argsize)
28356
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   555
{
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   556
	assert(hgc);
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   557
	if (!(hgc->capflags & CAP_VALIDATE))
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   558
		return NULL;
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   559
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   560
	packcmdargs(&hgc->ctx, args, argsize);
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   561
	writeblockrequest(hgc, "validate");
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   562
	handleresponse(hgc);
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   563
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   564
	/* the server returns '\0' if it can handle our request */
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   565
	if (hgc->ctx.datasize <= 1)
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   566
		return NULL;
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   567
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   568
	/* make sure the buffer is '\0' terminated */
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   569
	enlargecontext(&hgc->ctx, hgc->ctx.datasize + 1);
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   570
	hgc->ctx.data[hgc->ctx.datasize] = '\0';
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   571
	return unpackcmdargsnul(&hgc->ctx);
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   572
}
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   573
a5c773acb018 chg: implement validate in hgclient
Jun Wu <quark@fb.com>
parents: 28166
diff changeset
   574
/*!
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   575
 * Execute the specified Mercurial command
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   576
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   577
 * @return result code
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   578
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   579
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
   580
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   581
	assert(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   582
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   583
	packcmdargs(&hgc->ctx, args, argsize);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   584
	writeblockrequest(hgc, "runcommand");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   585
	handleresponse(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   586
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   587
	int32_t exitcode_n;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   588
	if (hgc->ctx.datasize != sizeof(exitcode_n)) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   589
		abortmsg("unexpected size of exitcode");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   590
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   591
	memcpy(&exitcode_n, hgc->ctx.data, sizeof(exitcode_n));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   592
	return ntohl(exitcode_n);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   593
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   594
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   595
/*!
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   596
 * (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
   597
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   598
void hgc_attachio(hgclient_t *hgc)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   599
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   600
	assert(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   601
	if (!(hgc->capflags & CAP_ATTACHIO))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   602
		return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   603
	attachio(hgc);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   604
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   605
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   606
/*!
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   607
 * Update server's environment variables
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   608
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   609
 * @param envp  list of environment variables in "NAME=VALUE" format,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   610
 *              terminated by NULL.
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
void hgc_setenv(hgclient_t *hgc, const char *const envp[])
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
	assert(hgc && envp);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   615
	if (!(hgc->capflags & CAP_SETENV))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   616
		return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   617
	packcmdargs(&hgc->ctx, envp, /*argsize*/ -1);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   618
	writeblockrequest(hgc, "setenv");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   619
}