git

Форк
0
/
connect.c 
1526 строк · 37.5 Кб
1
#define USE_THE_REPOSITORY_VARIABLE
2

3
#include "git-compat-util.h"
4
#include "config.h"
5
#include "environment.h"
6
#include "gettext.h"
7
#include "hex.h"
8
#include "pkt-line.h"
9
#include "quote.h"
10
#include "refs.h"
11
#include "run-command.h"
12
#include "remote.h"
13
#include "connect.h"
14
#include "url.h"
15
#include "string-list.h"
16
#include "oid-array.h"
17
#include "path.h"
18
#include "transport.h"
19
#include "trace2.h"
20
#include "strbuf.h"
21
#include "version.h"
22
#include "protocol.h"
23
#include "alias.h"
24
#include "bundle-uri.h"
25

26
static char *server_capabilities_v1;
27
static struct strvec server_capabilities_v2 = STRVEC_INIT;
28
static const char *next_server_feature_value(const char *feature, size_t *len, size_t *offset);
29

30
static int check_ref(const char *name, unsigned int flags)
31
{
32
	if (!flags)
33
		return 1;
34

35
	if (!skip_prefix(name, "refs/", &name))
36
		return 0;
37

38
	/* REF_NORMAL means that we don't want the magic fake tag refs */
39
	if ((flags & REF_NORMAL) && check_refname_format(name,
40
							 REFNAME_ALLOW_ONELEVEL))
41
		return 0;
42

43
	/* REF_BRANCHES means that we want regular branch heads */
44
	if ((flags & REF_BRANCHES) && starts_with(name, "heads/"))
45
		return 1;
46

47
	/* REF_TAGS means that we want tags */
48
	if ((flags & REF_TAGS) && starts_with(name, "tags/"))
49
		return 1;
50

51
	/* All type bits clear means that we are ok with anything */
52
	return !(flags & ~REF_NORMAL);
53
}
54

55
int check_ref_type(const struct ref *ref, int flags)
56
{
57
	return check_ref(ref->name, flags);
58
}
59

60
static NORETURN void die_initial_contact(int unexpected)
61
{
62
	/*
63
	 * A hang-up after seeing some response from the other end
64
	 * means that it is unexpected, as we know the other end is
65
	 * willing to talk to us.  A hang-up before seeing any
66
	 * response does not necessarily mean an ACL problem, though.
67
	 */
68
	if (unexpected)
69
		die(_("the remote end hung up upon initial contact"));
70
	else
71
		die(_("Could not read from remote repository.\n\n"
72
		      "Please make sure you have the correct access rights\n"
73
		      "and the repository exists."));
74
}
75

76
/* Checks if the server supports the capability 'c' */
77
int server_supports_v2(const char *c)
78
{
79
	int i;
80

81
	for (i = 0; i < server_capabilities_v2.nr; i++) {
82
		const char *out;
83
		if (skip_prefix(server_capabilities_v2.v[i], c, &out) &&
84
		    (!*out || *out == '='))
85
			return 1;
86
	}
87
	return 0;
88
}
89

90
void ensure_server_supports_v2(const char *c)
91
{
92
	if (!server_supports_v2(c))
93
		die(_("server doesn't support '%s'"), c);
94
}
95

96
int server_feature_v2(const char *c, const char **v)
97
{
98
	int i;
99

100
	for (i = 0; i < server_capabilities_v2.nr; i++) {
101
		const char *out;
102
		if (skip_prefix(server_capabilities_v2.v[i], c, &out) &&
103
		    (*out == '=')) {
104
			*v = out + 1;
105
			return 1;
106
		}
107
	}
108
	return 0;
109
}
110

111
int server_supports_feature(const char *c, const char *feature,
112
			    int die_on_error)
113
{
114
	int i;
115

116
	for (i = 0; i < server_capabilities_v2.nr; i++) {
117
		const char *out;
118
		if (skip_prefix(server_capabilities_v2.v[i], c, &out) &&
119
		    (!*out || *(out++) == '=')) {
120
			if (parse_feature_request(out, feature))
121
				return 1;
122
			else
123
				break;
124
		}
125
	}
126

127
	if (die_on_error)
128
		die(_("server doesn't support feature '%s'"), feature);
129

130
	return 0;
131
}
132

133
static void process_capabilities_v2(struct packet_reader *reader)
134
{
135
	while (packet_reader_read(reader) == PACKET_READ_NORMAL)
136
		strvec_push(&server_capabilities_v2, reader->line);
137

138
	if (reader->status != PACKET_READ_FLUSH)
139
		die(_("expected flush after capabilities"));
140
}
141

142
enum protocol_version discover_version(struct packet_reader *reader)
143
{
144
	enum protocol_version version = protocol_unknown_version;
145

146
	/*
147
	 * Peek the first line of the server's response to
148
	 * determine the protocol version the server is speaking.
149
	 */
150
	switch (packet_reader_peek(reader)) {
151
	case PACKET_READ_EOF:
152
		die_initial_contact(0);
153
	case PACKET_READ_FLUSH:
154
	case PACKET_READ_DELIM:
155
	case PACKET_READ_RESPONSE_END:
156
		version = protocol_v0;
157
		break;
158
	case PACKET_READ_NORMAL:
159
		version = determine_protocol_version_client(reader->line);
160
		break;
161
	}
162

163
	switch (version) {
164
	case protocol_v2:
165
		process_capabilities_v2(reader);
166
		break;
167
	case protocol_v1:
168
		/* Read the peeked version line */
169
		packet_reader_read(reader);
170
		break;
171
	case protocol_v0:
172
		break;
173
	case protocol_unknown_version:
174
		BUG("unknown protocol version");
175
	}
176

177
	trace2_data_intmax("transfer", NULL, "negotiated-version", version);
178

179
	return version;
180
}
181

182
static void parse_one_symref_info(struct string_list *symref, const char *val, int len)
183
{
184
	char *sym, *target;
185
	struct string_list_item *item;
186

187
	if (!len)
188
		return; /* just "symref" */
189
	/* e.g. "symref=HEAD:refs/heads/master" */
190
	sym = xmemdupz(val, len);
191
	target = strchr(sym, ':');
192
	if (!target)
193
		/* just "symref=something" */
194
		goto reject;
195
	*(target++) = '\0';
196
	if (check_refname_format(sym, REFNAME_ALLOW_ONELEVEL) ||
197
	    check_refname_format(target, REFNAME_ALLOW_ONELEVEL))
198
		/* "symref=bogus:pair */
199
		goto reject;
200
	item = string_list_append_nodup(symref, sym);
201
	item->util = target;
202
	return;
203
reject:
204
	free(sym);
205
	return;
206
}
207

208
static void annotate_refs_with_symref_info(struct ref *ref)
209
{
210
	struct string_list symref = STRING_LIST_INIT_DUP;
211
	size_t offset = 0;
212

213
	while (1) {
214
		size_t len;
215
		const char *val;
216

217
		val = next_server_feature_value("symref", &len, &offset);
218
		if (!val)
219
			break;
220
		parse_one_symref_info(&symref, val, len);
221
	}
222
	string_list_sort(&symref);
223

224
	for (; ref; ref = ref->next) {
225
		struct string_list_item *item;
226
		item = string_list_lookup(&symref, ref->name);
227
		if (!item)
228
			continue;
229
		ref->symref = xstrdup((char *)item->util);
230
	}
231
	string_list_clear(&symref, 0);
232
}
233

234
static void process_capabilities(struct packet_reader *reader, int *linelen)
235
{
236
	const char *feat_val;
237
	size_t feat_len;
238
	const char *line = reader->line;
239
	int nul_location = strlen(line);
240
	if (nul_location == *linelen)
241
		return;
242
	server_capabilities_v1 = xstrdup(line + nul_location + 1);
243
	*linelen = nul_location;
244

245
	feat_val = server_feature_value("object-format", &feat_len);
246
	if (feat_val) {
247
		char *hash_name = xstrndup(feat_val, feat_len);
248
		int hash_algo = hash_algo_by_name(hash_name);
249
		if (hash_algo != GIT_HASH_UNKNOWN)
250
			reader->hash_algo = &hash_algos[hash_algo];
251
		free(hash_name);
252
	} else {
253
		reader->hash_algo = &hash_algos[GIT_HASH_SHA1];
254
	}
255
}
256

257
static int process_dummy_ref(const struct packet_reader *reader)
258
{
259
	const char *line = reader->line;
260
	struct object_id oid;
261
	const char *name;
262

263
	if (parse_oid_hex_algop(line, &oid, &name, reader->hash_algo))
264
		return 0;
265
	if (*name != ' ')
266
		return 0;
267
	name++;
268

269
	return oideq(reader->hash_algo->null_oid, &oid) &&
270
		!strcmp(name, "capabilities^{}");
271
}
272

273
static void check_no_capabilities(const char *line, int len)
274
{
275
	if (strlen(line) != len)
276
		warning(_("ignoring capabilities after first line '%s'"),
277
			line + strlen(line));
278
}
279

280
static int process_ref(const struct packet_reader *reader, int len,
281
		       struct ref ***list, unsigned int flags,
282
		       struct oid_array *extra_have)
283
{
284
	const char *line = reader->line;
285
	struct object_id old_oid;
286
	const char *name;
287

288
	if (parse_oid_hex_algop(line, &old_oid, &name, reader->hash_algo))
289
		return 0;
290
	if (*name != ' ')
291
		return 0;
292
	name++;
293

294
	if (extra_have && !strcmp(name, ".have")) {
295
		oid_array_append(extra_have, &old_oid);
296
	} else if (!strcmp(name, "capabilities^{}")) {
297
		die(_("protocol error: unexpected capabilities^{}"));
298
	} else if (check_ref(name, flags)) {
299
		struct ref *ref = alloc_ref(name);
300
		oidcpy(&ref->old_oid, &old_oid);
301
		**list = ref;
302
		*list = &ref->next;
303
	}
304
	check_no_capabilities(line, len);
305
	return 1;
306
}
307

308
static int process_shallow(const struct packet_reader *reader, int len,
309
			   struct oid_array *shallow_points)
310
{
311
	const char *line = reader->line;
312
	const char *arg;
313
	struct object_id old_oid;
314

315
	if (!skip_prefix(line, "shallow ", &arg))
316
		return 0;
317

318
	if (get_oid_hex_algop(arg, &old_oid, reader->hash_algo))
319
		die(_("protocol error: expected shallow sha-1, got '%s'"), arg);
320
	if (!shallow_points)
321
		die(_("repository on the other end cannot be shallow"));
322
	oid_array_append(shallow_points, &old_oid);
323
	check_no_capabilities(line, len);
324
	return 1;
325
}
326

327
enum get_remote_heads_state {
328
	EXPECTING_FIRST_REF = 0,
329
	EXPECTING_REF,
330
	EXPECTING_SHALLOW,
331
	EXPECTING_DONE,
332
};
333

334
/*
335
 * Read all the refs from the other end
336
 */
337
struct ref **get_remote_heads(struct packet_reader *reader,
338
			      struct ref **list, unsigned int flags,
339
			      struct oid_array *extra_have,
340
			      struct oid_array *shallow_points)
341
{
342
	struct ref **orig_list = list;
343
	int len = 0;
344
	enum get_remote_heads_state state = EXPECTING_FIRST_REF;
345

346
	*list = NULL;
347

348
	while (state != EXPECTING_DONE) {
349
		switch (packet_reader_read(reader)) {
350
		case PACKET_READ_EOF:
351
			die_initial_contact(1);
352
		case PACKET_READ_NORMAL:
353
			len = reader->pktlen;
354
			break;
355
		case PACKET_READ_FLUSH:
356
			state = EXPECTING_DONE;
357
			break;
358
		case PACKET_READ_DELIM:
359
		case PACKET_READ_RESPONSE_END:
360
			die(_("invalid packet"));
361
		}
362

363
		switch (state) {
364
		case EXPECTING_FIRST_REF:
365
			process_capabilities(reader, &len);
366
			if (process_dummy_ref(reader)) {
367
				state = EXPECTING_SHALLOW;
368
				break;
369
			}
370
			state = EXPECTING_REF;
371
			/* fallthrough */
372
		case EXPECTING_REF:
373
			if (process_ref(reader, len, &list, flags, extra_have))
374
				break;
375
			state = EXPECTING_SHALLOW;
376
			/* fallthrough */
377
		case EXPECTING_SHALLOW:
378
			if (process_shallow(reader, len, shallow_points))
379
				break;
380
			die(_("protocol error: unexpected '%s'"), reader->line);
381
		case EXPECTING_DONE:
382
			break;
383
		}
384
	}
385

386
	annotate_refs_with_symref_info(*orig_list);
387

388
	return list;
389
}
390

391
/* Returns 1 when a valid ref has been added to `list`, 0 otherwise */
392
static int process_ref_v2(struct packet_reader *reader, struct ref ***list,
393
			  const char **unborn_head_target)
394
{
395
	int ret = 1;
396
	int i = 0;
397
	struct object_id old_oid;
398
	struct ref *ref;
399
	struct string_list line_sections = STRING_LIST_INIT_DUP;
400
	const char *end;
401
	const char *line = reader->line;
402

403
	/*
404
	 * Ref lines have a number of fields which are space deliminated.  The
405
	 * first field is the OID of the ref.  The second field is the ref
406
	 * name.  Subsequent fields (symref-target and peeled) are optional and
407
	 * don't have a particular order.
408
	 */
409
	if (string_list_split(&line_sections, line, ' ', -1) < 2) {
410
		ret = 0;
411
		goto out;
412
	}
413

414
	if (!strcmp("unborn", line_sections.items[i].string)) {
415
		i++;
416
		if (unborn_head_target &&
417
		    !strcmp("HEAD", line_sections.items[i++].string)) {
418
			/*
419
			 * Look for the symref target (if any). If found,
420
			 * return it to the caller.
421
			 */
422
			for (; i < line_sections.nr; i++) {
423
				const char *arg = line_sections.items[i].string;
424

425
				if (skip_prefix(arg, "symref-target:", &arg)) {
426
					*unborn_head_target = xstrdup(arg);
427
					break;
428
				}
429
			}
430
		}
431
		goto out;
432
	}
433
	if (parse_oid_hex_algop(line_sections.items[i++].string, &old_oid, &end, reader->hash_algo) ||
434
	    *end) {
435
		ret = 0;
436
		goto out;
437
	}
438

439
	ref = alloc_ref(line_sections.items[i++].string);
440

441
	memcpy(ref->old_oid.hash, old_oid.hash, reader->hash_algo->rawsz);
442
	**list = ref;
443
	*list = &ref->next;
444

445
	for (; i < line_sections.nr; i++) {
446
		const char *arg = line_sections.items[i].string;
447
		if (skip_prefix(arg, "symref-target:", &arg))
448
			ref->symref = xstrdup(arg);
449

450
		if (skip_prefix(arg, "peeled:", &arg)) {
451
			struct object_id peeled_oid;
452
			char *peeled_name;
453
			struct ref *peeled;
454
			if (parse_oid_hex_algop(arg, &peeled_oid, &end,
455
						reader->hash_algo) || *end) {
456
				ret = 0;
457
				goto out;
458
			}
459

460
			peeled_name = xstrfmt("%s^{}", ref->name);
461
			peeled = alloc_ref(peeled_name);
462

463
			memcpy(peeled->old_oid.hash, peeled_oid.hash,
464
			       reader->hash_algo->rawsz);
465
			**list = peeled;
466
			*list = &peeled->next;
467

468
			free(peeled_name);
469
		}
470
	}
471

472
out:
473
	string_list_clear(&line_sections, 0);
474
	return ret;
475
}
476

477
void check_stateless_delimiter(int stateless_rpc,
478
			      struct packet_reader *reader,
479
			      const char *error)
480
{
481
	if (!stateless_rpc)
482
		return; /* not in stateless mode, no delimiter expected */
483
	if (packet_reader_read(reader) != PACKET_READ_RESPONSE_END)
484
		die("%s", error);
485
}
486

487
static void send_capabilities(int fd_out, struct packet_reader *reader)
488
{
489
	const char *hash_name;
490

491
	if (server_supports_v2("agent"))
492
		packet_write_fmt(fd_out, "agent=%s", git_user_agent_sanitized());
493

494
	if (server_feature_v2("object-format", &hash_name)) {
495
		int hash_algo = hash_algo_by_name(hash_name);
496
		if (hash_algo == GIT_HASH_UNKNOWN)
497
			die(_("unknown object format '%s' specified by server"), hash_name);
498
		reader->hash_algo = &hash_algos[hash_algo];
499
		packet_write_fmt(fd_out, "object-format=%s", reader->hash_algo->name);
500
	} else {
501
		reader->hash_algo = &hash_algos[GIT_HASH_SHA1];
502
	}
503
}
504

505
int get_remote_bundle_uri(int fd_out, struct packet_reader *reader,
506
			  struct bundle_list *bundles, int stateless_rpc)
507
{
508
	int line_nr = 1;
509

510
	/* Assert bundle-uri support */
511
	ensure_server_supports_v2("bundle-uri");
512

513
	/* (Re-)send capabilities */
514
	send_capabilities(fd_out, reader);
515

516
	/* Send command */
517
	packet_write_fmt(fd_out, "command=bundle-uri\n");
518
	packet_delim(fd_out);
519

520
	packet_flush(fd_out);
521

522
	/* Process response from server */
523
	while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
524
		const char *line = reader->line;
525
		line_nr++;
526

527
		if (!bundle_uri_parse_line(bundles, line))
528
			continue;
529

530
		return error(_("error on bundle-uri response line %d: %s"),
531
			     line_nr, line);
532
	}
533

534
	if (reader->status != PACKET_READ_FLUSH)
535
		return error(_("expected flush after bundle-uri listing"));
536

537
	/*
538
	 * Might die(), but obscure enough that that's OK, e.g. in
539
	 * serve.c we'll call BUG() on its equivalent (the
540
	 * PACKET_READ_RESPONSE_END check).
541
	 */
542
	check_stateless_delimiter(stateless_rpc, reader,
543
				  _("expected response end packet after ref listing"));
544

545
	return 0;
546
}
547

548
struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
549
			     struct ref **list, int for_push,
550
			     struct transport_ls_refs_options *transport_options,
551
			     const struct string_list *server_options,
552
			     int stateless_rpc)
553
{
554
	int i;
555
	struct strvec *ref_prefixes = transport_options ?
556
		&transport_options->ref_prefixes : NULL;
557
	const char **unborn_head_target = transport_options ?
558
		&transport_options->unborn_head_target : NULL;
559
	*list = NULL;
560

561
	ensure_server_supports_v2("ls-refs");
562
	packet_write_fmt(fd_out, "command=ls-refs\n");
563

564
	/* Send capabilities */
565
	send_capabilities(fd_out, reader);
566

567
	if (server_options && server_options->nr) {
568
		ensure_server_supports_v2("server-option");
569
		for (i = 0; i < server_options->nr; i++)
570
			packet_write_fmt(fd_out, "server-option=%s",
571
					 server_options->items[i].string);
572
	}
573

574
	packet_delim(fd_out);
575
	/* When pushing we don't want to request the peeled tags */
576
	if (!for_push)
577
		packet_write_fmt(fd_out, "peel\n");
578
	packet_write_fmt(fd_out, "symrefs\n");
579
	if (server_supports_feature("ls-refs", "unborn", 0))
580
		packet_write_fmt(fd_out, "unborn\n");
581
	for (i = 0; ref_prefixes && i < ref_prefixes->nr; i++) {
582
		packet_write_fmt(fd_out, "ref-prefix %s\n",
583
				 ref_prefixes->v[i]);
584
	}
585
	packet_flush(fd_out);
586

587
	/* Process response from server */
588
	while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
589
		if (!process_ref_v2(reader, &list, unborn_head_target))
590
			die(_("invalid ls-refs response: %s"), reader->line);
591
	}
592

593
	if (reader->status != PACKET_READ_FLUSH)
594
		die(_("expected flush after ref listing"));
595

596
	check_stateless_delimiter(stateless_rpc, reader,
597
				  _("expected response end packet after ref listing"));
598

599
	return list;
600
}
601

602
const char *parse_feature_value(const char *feature_list, const char *feature, size_t *lenp, size_t *offset)
603
{
604
	const char *orig_start = feature_list;
605
	size_t len;
606

607
	if (!feature_list)
608
		return NULL;
609

610
	len = strlen(feature);
611
	if (offset)
612
		feature_list += *offset;
613
	while (*feature_list) {
614
		const char *found = strstr(feature_list, feature);
615
		if (!found)
616
			return NULL;
617
		if (feature_list == found || isspace(found[-1])) {
618
			const char *value = found + len;
619
			/* feature with no value (e.g., "thin-pack") */
620
			if (!*value || isspace(*value)) {
621
				if (lenp)
622
					*lenp = 0;
623
				if (offset)
624
					*offset = found + len - orig_start;
625
				return value;
626
			}
627
			/* feature with a value (e.g., "agent=git/1.2.3") */
628
			else if (*value == '=') {
629
				size_t end;
630

631
				value++;
632
				end = strcspn(value, " \t\n");
633
				if (lenp)
634
					*lenp = end;
635
				if (offset)
636
					*offset = value + end - orig_start;
637
				return value;
638
			}
639
			/*
640
			 * otherwise we matched a substring of another feature;
641
			 * keep looking
642
			 */
643
		}
644
		feature_list = found + 1;
645
	}
646
	return NULL;
647
}
648

649
int server_supports_hash(const char *desired, int *feature_supported)
650
{
651
	size_t offset = 0;
652
	size_t len;
653
	const char *hash;
654

655
	hash = next_server_feature_value("object-format", &len, &offset);
656
	if (feature_supported)
657
		*feature_supported = !!hash;
658
	if (!hash) {
659
		hash = hash_algos[GIT_HASH_SHA1].name;
660
		len = strlen(hash);
661
	}
662
	while (hash) {
663
		if (!xstrncmpz(desired, hash, len))
664
			return 1;
665

666
		hash = next_server_feature_value("object-format", &len, &offset);
667
	}
668
	return 0;
669
}
670

671
int parse_feature_request(const char *feature_list, const char *feature)
672
{
673
	return !!parse_feature_value(feature_list, feature, NULL, NULL);
674
}
675

676
static const char *next_server_feature_value(const char *feature, size_t *len, size_t *offset)
677
{
678
	return parse_feature_value(server_capabilities_v1, feature, len, offset);
679
}
680

681
const char *server_feature_value(const char *feature, size_t *len)
682
{
683
	return parse_feature_value(server_capabilities_v1, feature, len, NULL);
684
}
685

686
int server_supports(const char *feature)
687
{
688
	return !!server_feature_value(feature, NULL);
689
}
690

691
enum protocol {
692
	PROTO_LOCAL = 1,
693
	PROTO_FILE,
694
	PROTO_SSH,
695
	PROTO_GIT
696
};
697

698
int url_is_local_not_ssh(const char *url)
699
{
700
	const char *colon = strchr(url, ':');
701
	const char *slash = strchr(url, '/');
702
	return !colon || (slash && slash < colon) ||
703
		(has_dos_drive_prefix(url) && is_valid_path(url));
704
}
705

706
static const char *prot_name(enum protocol protocol)
707
{
708
	switch (protocol) {
709
		case PROTO_LOCAL:
710
		case PROTO_FILE:
711
			return "file";
712
		case PROTO_SSH:
713
			return "ssh";
714
		case PROTO_GIT:
715
			return "git";
716
		default:
717
			return "unknown protocol";
718
	}
719
}
720

721
static enum protocol get_protocol(const char *name)
722
{
723
	if (!strcmp(name, "ssh"))
724
		return PROTO_SSH;
725
	if (!strcmp(name, "git"))
726
		return PROTO_GIT;
727
	if (!strcmp(name, "git+ssh")) /* deprecated - do not use */
728
		return PROTO_SSH;
729
	if (!strcmp(name, "ssh+git")) /* deprecated - do not use */
730
		return PROTO_SSH;
731
	if (!strcmp(name, "file"))
732
		return PROTO_FILE;
733
	die(_("protocol '%s' is not supported"), name);
734
}
735

736
static char *host_end(char **hoststart, int removebrackets)
737
{
738
	char *host = *hoststart;
739
	char *end;
740
	char *start = strstr(host, "@[");
741
	if (start)
742
		start++; /* Jump over '@' */
743
	else
744
		start = host;
745
	if (start[0] == '[') {
746
		end = strchr(start + 1, ']');
747
		if (end) {
748
			if (removebrackets) {
749
				*end = 0;
750
				memmove(start, start + 1, end - start);
751
				end++;
752
			}
753
		} else
754
			end = host;
755
	} else
756
		end = host;
757
	return end;
758
}
759

760
#define STR_(s)	# s
761
#define STR(s)	STR_(s)
762

763
static void get_host_and_port(char **host, const char **port)
764
{
765
	char *colon, *end;
766
	end = host_end(host, 1);
767
	colon = strchr(end, ':');
768
	if (colon) {
769
		long portnr = strtol(colon + 1, &end, 10);
770
		if (end != colon + 1 && *end == '\0' && 0 <= portnr && portnr < 65536) {
771
			*colon = 0;
772
			*port = colon + 1;
773
		} else if (!colon[1]) {
774
			*colon = 0;
775
		}
776
	}
777
}
778

779
static void enable_keepalive(int sockfd)
780
{
781
	int ka = 1;
782

783
	if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &ka, sizeof(ka)) < 0)
784
		error_errno(_("unable to set SO_KEEPALIVE on socket"));
785
}
786

787
#ifndef NO_IPV6
788

789
static const char *ai_name(const struct addrinfo *ai)
790
{
791
	static char addr[NI_MAXHOST];
792
	if (getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, sizeof(addr), NULL, 0,
793
			NI_NUMERICHOST) != 0)
794
		xsnprintf(addr, sizeof(addr), "(unknown)");
795

796
	return addr;
797
}
798

799
/*
800
 * Returns a connected socket() fd, or else die()s.
801
 */
802
static int git_tcp_connect_sock(char *host, int flags)
803
{
804
	struct strbuf error_message = STRBUF_INIT;
805
	int sockfd = -1;
806
	const char *port = STR(DEFAULT_GIT_PORT);
807
	struct addrinfo hints, *ai0, *ai;
808
	int gai;
809
	int cnt = 0;
810

811
	get_host_and_port(&host, &port);
812
	if (!*port)
813
		port = "<none>";
814

815
	memset(&hints, 0, sizeof(hints));
816
	if (flags & CONNECT_IPV4)
817
		hints.ai_family = AF_INET;
818
	else if (flags & CONNECT_IPV6)
819
		hints.ai_family = AF_INET6;
820
	hints.ai_socktype = SOCK_STREAM;
821
	hints.ai_protocol = IPPROTO_TCP;
822

823
	if (flags & CONNECT_VERBOSE)
824
		fprintf(stderr, _("Looking up %s ... "), host);
825

826
	gai = getaddrinfo(host, port, &hints, &ai);
827
	if (gai)
828
		die(_("unable to look up %s (port %s) (%s)"), host, port, gai_strerror(gai));
829

830
	if (flags & CONNECT_VERBOSE)
831
		/* TRANSLATORS: this is the end of "Looking up %s ... " */
832
		fprintf(stderr, _("done.\nConnecting to %s (port %s) ... "), host, port);
833

834
	for (ai0 = ai; ai; ai = ai->ai_next, cnt++) {
835
		sockfd = socket(ai->ai_family,
836
				ai->ai_socktype, ai->ai_protocol);
837
		if ((sockfd < 0) ||
838
		    (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0)) {
839
			strbuf_addf(&error_message, "%s[%d: %s]: errno=%s\n",
840
				    host, cnt, ai_name(ai), strerror(errno));
841
			if (0 <= sockfd)
842
				close(sockfd);
843
			sockfd = -1;
844
			continue;
845
		}
846
		if (flags & CONNECT_VERBOSE)
847
			fprintf(stderr, "%s ", ai_name(ai));
848
		break;
849
	}
850

851
	freeaddrinfo(ai0);
852

853
	if (sockfd < 0)
854
		die(_("unable to connect to %s:\n%s"), host, error_message.buf);
855

856
	enable_keepalive(sockfd);
857

858
	if (flags & CONNECT_VERBOSE)
859
		/* TRANSLATORS: this is the end of "Connecting to %s (port %s) ... " */
860
		fprintf_ln(stderr, _("done."));
861

862
	strbuf_release(&error_message);
863

864
	return sockfd;
865
}
866

867
#else /* NO_IPV6 */
868

869
/*
870
 * Returns a connected socket() fd, or else die()s.
871
 */
872
static int git_tcp_connect_sock(char *host, int flags)
873
{
874
	struct strbuf error_message = STRBUF_INIT;
875
	int sockfd = -1;
876
	const char *port = STR(DEFAULT_GIT_PORT);
877
	char *ep;
878
	struct hostent *he;
879
	struct sockaddr_in sa;
880
	char **ap;
881
	unsigned int nport;
882
	int cnt;
883

884
	get_host_and_port(&host, &port);
885

886
	if (flags & CONNECT_VERBOSE)
887
		fprintf(stderr, _("Looking up %s ... "), host);
888

889
	he = gethostbyname(host);
890
	if (!he)
891
		die(_("unable to look up %s (%s)"), host, hstrerror(h_errno));
892
	nport = strtoul(port, &ep, 10);
893
	if ( ep == port || *ep ) {
894
		/* Not numeric */
895
		struct servent *se = getservbyname(port,"tcp");
896
		if ( !se )
897
			die(_("unknown port %s"), port);
898
		nport = se->s_port;
899
	}
900

901
	if (flags & CONNECT_VERBOSE)
902
		/* TRANSLATORS: this is the end of "Looking up %s ... " */
903
		fprintf(stderr, _("done.\nConnecting to %s (port %s) ... "), host, port);
904

905
	for (cnt = 0, ap = he->h_addr_list; *ap; ap++, cnt++) {
906
		memset(&sa, 0, sizeof sa);
907
		sa.sin_family = he->h_addrtype;
908
		sa.sin_port = htons(nport);
909
		memcpy(&sa.sin_addr, *ap, he->h_length);
910

911
		sockfd = socket(he->h_addrtype, SOCK_STREAM, 0);
912
		if ((sockfd < 0) ||
913
		    connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
914
			strbuf_addf(&error_message, "%s[%d: %s]: errno=%s\n",
915
				host,
916
				cnt,
917
				inet_ntoa(*(struct in_addr *)&sa.sin_addr),
918
				strerror(errno));
919
			if (0 <= sockfd)
920
				close(sockfd);
921
			sockfd = -1;
922
			continue;
923
		}
924
		if (flags & CONNECT_VERBOSE)
925
			fprintf(stderr, "%s ",
926
				inet_ntoa(*(struct in_addr *)&sa.sin_addr));
927
		break;
928
	}
929

930
	if (sockfd < 0)
931
		die(_("unable to connect to %s:\n%s"), host, error_message.buf);
932

933
	enable_keepalive(sockfd);
934

935
	if (flags & CONNECT_VERBOSE)
936
		/* TRANSLATORS: this is the end of "Connecting to %s (port %s) ... " */
937
		fprintf_ln(stderr, _("done."));
938

939
	return sockfd;
940
}
941

942
#endif /* NO_IPV6 */
943

944

945
/*
946
 * Dummy child_process returned by git_connect() if the transport protocol
947
 * does not need fork(2).
948
 */
949
static struct child_process no_fork = CHILD_PROCESS_INIT;
950

951
int git_connection_is_socket(struct child_process *conn)
952
{
953
	return conn == &no_fork;
954
}
955

956
static struct child_process *git_tcp_connect(int fd[2], char *host, int flags)
957
{
958
	int sockfd = git_tcp_connect_sock(host, flags);
959

960
	fd[0] = sockfd;
961
	fd[1] = dup(sockfd);
962

963
	return &no_fork;
964
}
965

966

967
static char *git_proxy_command;
968

969
static int git_proxy_command_options(const char *var, const char *value,
970
		const struct config_context *ctx, void *cb)
971
{
972
	if (!strcmp(var, "core.gitproxy")) {
973
		const char *for_pos;
974
		int matchlen = -1;
975
		int hostlen;
976
		const char *rhost_name = cb;
977
		int rhost_len = strlen(rhost_name);
978

979
		if (git_proxy_command)
980
			return 0;
981
		if (!value)
982
			return config_error_nonbool(var);
983
		/* [core]
984
		 * ;# matches www.kernel.org as well
985
		 * gitproxy = netcatter-1 for kernel.org
986
		 * gitproxy = netcatter-2 for sample.xz
987
		 * gitproxy = netcatter-default
988
		 */
989
		for_pos = strstr(value, " for ");
990
		if (!for_pos)
991
			/* matches everybody */
992
			matchlen = strlen(value);
993
		else {
994
			hostlen = strlen(for_pos + 5);
995
			if (rhost_len < hostlen)
996
				matchlen = -1;
997
			else if (!strncmp(for_pos + 5,
998
					  rhost_name + rhost_len - hostlen,
999
					  hostlen) &&
1000
				 ((rhost_len == hostlen) ||
1001
				  rhost_name[rhost_len - hostlen -1] == '.'))
1002
				matchlen = for_pos - value;
1003
			else
1004
				matchlen = -1;
1005
		}
1006
		if (0 <= matchlen) {
1007
			/* core.gitproxy = none for kernel.org */
1008
			if (matchlen == 4 &&
1009
			    !memcmp(value, "none", 4))
1010
				matchlen = 0;
1011
			git_proxy_command = xmemdupz(value, matchlen);
1012
		}
1013
		return 0;
1014
	}
1015

1016
	return git_default_config(var, value, ctx, cb);
1017
}
1018

1019
static int git_use_proxy(const char *host)
1020
{
1021
	git_proxy_command = getenv("GIT_PROXY_COMMAND");
1022
	git_config(git_proxy_command_options, (void*)host);
1023
	return (git_proxy_command && *git_proxy_command);
1024
}
1025

1026
static struct child_process *git_proxy_connect(int fd[2], char *host)
1027
{
1028
	const char *port = STR(DEFAULT_GIT_PORT);
1029
	struct child_process *proxy;
1030

1031
	get_host_and_port(&host, &port);
1032

1033
	if (looks_like_command_line_option(host))
1034
		die(_("strange hostname '%s' blocked"), host);
1035
	if (looks_like_command_line_option(port))
1036
		die(_("strange port '%s' blocked"), port);
1037

1038
	proxy = xmalloc(sizeof(*proxy));
1039
	child_process_init(proxy);
1040
	strvec_push(&proxy->args, git_proxy_command);
1041
	strvec_push(&proxy->args, host);
1042
	strvec_push(&proxy->args, port);
1043
	proxy->in = -1;
1044
	proxy->out = -1;
1045
	if (start_command(proxy))
1046
		die(_("cannot start proxy %s"), git_proxy_command);
1047
	fd[0] = proxy->out; /* read from proxy stdout */
1048
	fd[1] = proxy->in;  /* write to proxy stdin */
1049
	return proxy;
1050
}
1051

1052
static char *get_port(char *host)
1053
{
1054
	char *end;
1055
	char *p = strchr(host, ':');
1056

1057
	if (p) {
1058
		long port = strtol(p + 1, &end, 10);
1059
		if (end != p + 1 && *end == '\0' && 0 <= port && port < 65536) {
1060
			*p = '\0';
1061
			return p+1;
1062
		}
1063
	}
1064

1065
	return NULL;
1066
}
1067

1068
/*
1069
 * Extract protocol and relevant parts from the specified connection URL.
1070
 * The caller must free() the returned strings.
1071
 */
1072
static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
1073
				       char **ret_path)
1074
{
1075
	char *url;
1076
	char *host, *path;
1077
	char *end;
1078
	int separator = '/';
1079
	enum protocol protocol = PROTO_LOCAL;
1080

1081
	if (is_url(url_orig))
1082
		url = url_decode(url_orig);
1083
	else
1084
		url = xstrdup(url_orig);
1085

1086
	host = strstr(url, "://");
1087
	if (host) {
1088
		*host = '\0';
1089
		protocol = get_protocol(url);
1090
		host += 3;
1091
	} else {
1092
		host = url;
1093
		if (!url_is_local_not_ssh(url)) {
1094
			protocol = PROTO_SSH;
1095
			separator = ':';
1096
		}
1097
	}
1098

1099
	/*
1100
	 * Don't do destructive transforms as protocol code does
1101
	 * '[]' unwrapping in get_host_and_port()
1102
	 */
1103
	end = host_end(&host, 0);
1104

1105
	if (protocol == PROTO_LOCAL)
1106
		path = end;
1107
	else if (protocol == PROTO_FILE && *host != '/' &&
1108
		 !has_dos_drive_prefix(host) &&
1109
		 offset_1st_component(host - 2) > 1)
1110
		path = host - 2; /* include the leading "//" */
1111
	else if (protocol == PROTO_FILE && has_dos_drive_prefix(end))
1112
		path = end; /* "file://$(pwd)" may be "file://C:/projects/repo" */
1113
	else
1114
		path = strchr(end, separator);
1115

1116
	if (!path || !*path)
1117
		die(_("no path specified; see 'git help pull' for valid url syntax"));
1118

1119
	/*
1120
	 * null-terminate hostname and point path to ~ for URL's like this:
1121
	 *    ssh://host.xz/~user/repo
1122
	 */
1123

1124
	end = path; /* Need to \0 terminate host here */
1125
	if (separator == ':')
1126
		path++; /* path starts after ':' */
1127
	if (protocol == PROTO_GIT || protocol == PROTO_SSH) {
1128
		if (path[1] == '~')
1129
			path++;
1130
	}
1131

1132
	path = xstrdup(path);
1133
	*end = '\0';
1134

1135
	*ret_host = xstrdup(host);
1136
	*ret_path = path;
1137
	free(url);
1138
	return protocol;
1139
}
1140

1141
static const char *get_ssh_command(void)
1142
{
1143
	const char *ssh;
1144

1145
	if ((ssh = getenv("GIT_SSH_COMMAND")))
1146
		return ssh;
1147

1148
	if (!git_config_get_string_tmp("core.sshcommand", &ssh))
1149
		return ssh;
1150

1151
	return NULL;
1152
}
1153

1154
enum ssh_variant {
1155
	VARIANT_AUTO,
1156
	VARIANT_SIMPLE,
1157
	VARIANT_SSH,
1158
	VARIANT_PLINK,
1159
	VARIANT_PUTTY,
1160
	VARIANT_TORTOISEPLINK,
1161
};
1162

1163
static void override_ssh_variant(enum ssh_variant *ssh_variant)
1164
{
1165
	const char *variant = getenv("GIT_SSH_VARIANT");
1166

1167
	if (!variant && git_config_get_string_tmp("ssh.variant", &variant))
1168
		return;
1169

1170
	if (!strcmp(variant, "auto"))
1171
		*ssh_variant = VARIANT_AUTO;
1172
	else if (!strcmp(variant, "plink"))
1173
		*ssh_variant = VARIANT_PLINK;
1174
	else if (!strcmp(variant, "putty"))
1175
		*ssh_variant = VARIANT_PUTTY;
1176
	else if (!strcmp(variant, "tortoiseplink"))
1177
		*ssh_variant = VARIANT_TORTOISEPLINK;
1178
	else if (!strcmp(variant, "simple"))
1179
		*ssh_variant = VARIANT_SIMPLE;
1180
	else
1181
		*ssh_variant = VARIANT_SSH;
1182
}
1183

1184
static enum ssh_variant determine_ssh_variant(const char *ssh_command,
1185
					      int is_cmdline)
1186
{
1187
	enum ssh_variant ssh_variant = VARIANT_AUTO;
1188
	const char *variant;
1189
	char *p = NULL;
1190

1191
	override_ssh_variant(&ssh_variant);
1192

1193
	if (ssh_variant != VARIANT_AUTO)
1194
		return ssh_variant;
1195

1196
	if (!is_cmdline) {
1197
		p = xstrdup(ssh_command);
1198
		variant = basename(p);
1199
	} else {
1200
		const char **ssh_argv;
1201

1202
		p = xstrdup(ssh_command);
1203
		if (split_cmdline(p, &ssh_argv) > 0) {
1204
			variant = basename((char *)ssh_argv[0]);
1205
			/*
1206
			 * At this point, variant points into the buffer
1207
			 * referenced by p, hence we do not need ssh_argv
1208
			 * any longer.
1209
			 */
1210
			free(ssh_argv);
1211
		} else {
1212
			free(p);
1213
			return ssh_variant;
1214
		}
1215
	}
1216

1217
	if (!strcasecmp(variant, "ssh") ||
1218
	    !strcasecmp(variant, "ssh.exe"))
1219
		ssh_variant = VARIANT_SSH;
1220
	else if (!strcasecmp(variant, "plink") ||
1221
		 !strcasecmp(variant, "plink.exe"))
1222
		ssh_variant = VARIANT_PLINK;
1223
	else if (!strcasecmp(variant, "tortoiseplink") ||
1224
		 !strcasecmp(variant, "tortoiseplink.exe"))
1225
		ssh_variant = VARIANT_TORTOISEPLINK;
1226

1227
	free(p);
1228
	return ssh_variant;
1229
}
1230

1231
/*
1232
 * Open a connection using Git's native protocol.
1233
 *
1234
 * The caller is responsible for freeing hostandport, but this function may
1235
 * modify it (for example, to truncate it to remove the port part).
1236
 */
1237
static struct child_process *git_connect_git(int fd[2], char *hostandport,
1238
					     const char *path, const char *prog,
1239
					     enum protocol_version version,
1240
					     int flags)
1241
{
1242
	struct child_process *conn;
1243
	struct strbuf request = STRBUF_INIT;
1244
	/*
1245
	 * Set up virtual host information based on where we will
1246
	 * connect, unless the user has overridden us in
1247
	 * the environment.
1248
	 */
1249
	char *target_host = getenv("GIT_OVERRIDE_VIRTUAL_HOST");
1250
	if (target_host)
1251
		target_host = xstrdup(target_host);
1252
	else
1253
		target_host = xstrdup(hostandport);
1254

1255
	transport_check_allowed("git");
1256
	if (strchr(target_host, '\n') || strchr(path, '\n'))
1257
		die(_("newline is forbidden in git:// hosts and repo paths"));
1258

1259
	/*
1260
	 * These underlying connection commands die() if they
1261
	 * cannot connect.
1262
	 */
1263
	if (git_use_proxy(hostandport))
1264
		conn = git_proxy_connect(fd, hostandport);
1265
	else
1266
		conn = git_tcp_connect(fd, hostandport, flags);
1267
	/*
1268
	 * Separate original protocol components prog and path
1269
	 * from extended host header with a NUL byte.
1270
	 *
1271
	 * Note: Do not add any other headers here!  Doing so
1272
	 * will cause older git-daemon servers to crash.
1273
	 */
1274
	strbuf_addf(&request,
1275
		    "%s %s%chost=%s%c",
1276
		    prog, path, 0,
1277
		    target_host, 0);
1278

1279
	/* If using a new version put that stuff here after a second null byte */
1280
	if (version > 0) {
1281
		strbuf_addch(&request, '\0');
1282
		strbuf_addf(&request, "version=%d%c",
1283
			    version, '\0');
1284
	}
1285

1286
	packet_write(fd[1], request.buf, request.len);
1287

1288
	free(target_host);
1289
	strbuf_release(&request);
1290
	return conn;
1291
}
1292

1293
/*
1294
 * Append the appropriate environment variables to `env` and options to
1295
 * `args` for running ssh in Git's SSH-tunneled transport.
1296
 */
1297
static void push_ssh_options(struct strvec *args, struct strvec *env,
1298
			     enum ssh_variant variant, const char *port,
1299
			     enum protocol_version version, int flags)
1300
{
1301
	if (variant == VARIANT_SSH &&
1302
	    version > 0) {
1303
		strvec_push(args, "-o");
1304
		strvec_push(args, "SendEnv=" GIT_PROTOCOL_ENVIRONMENT);
1305
		strvec_pushf(env, GIT_PROTOCOL_ENVIRONMENT "=version=%d",
1306
			     version);
1307
	}
1308

1309
	if (flags & CONNECT_IPV4) {
1310
		switch (variant) {
1311
		case VARIANT_AUTO:
1312
			BUG("VARIANT_AUTO passed to push_ssh_options");
1313
		case VARIANT_SIMPLE:
1314
			die(_("ssh variant 'simple' does not support -4"));
1315
		case VARIANT_SSH:
1316
		case VARIANT_PLINK:
1317
		case VARIANT_PUTTY:
1318
		case VARIANT_TORTOISEPLINK:
1319
			strvec_push(args, "-4");
1320
		}
1321
	} else if (flags & CONNECT_IPV6) {
1322
		switch (variant) {
1323
		case VARIANT_AUTO:
1324
			BUG("VARIANT_AUTO passed to push_ssh_options");
1325
		case VARIANT_SIMPLE:
1326
			die(_("ssh variant 'simple' does not support -6"));
1327
		case VARIANT_SSH:
1328
		case VARIANT_PLINK:
1329
		case VARIANT_PUTTY:
1330
		case VARIANT_TORTOISEPLINK:
1331
			strvec_push(args, "-6");
1332
		}
1333
	}
1334

1335
	if (variant == VARIANT_TORTOISEPLINK)
1336
		strvec_push(args, "-batch");
1337

1338
	if (port) {
1339
		switch (variant) {
1340
		case VARIANT_AUTO:
1341
			BUG("VARIANT_AUTO passed to push_ssh_options");
1342
		case VARIANT_SIMPLE:
1343
			die(_("ssh variant 'simple' does not support setting port"));
1344
		case VARIANT_SSH:
1345
			strvec_push(args, "-p");
1346
			break;
1347
		case VARIANT_PLINK:
1348
		case VARIANT_PUTTY:
1349
		case VARIANT_TORTOISEPLINK:
1350
			strvec_push(args, "-P");
1351
		}
1352

1353
		strvec_push(args, port);
1354
	}
1355
}
1356

1357
/* Prepare a child_process for use by Git's SSH-tunneled transport. */
1358
static void fill_ssh_args(struct child_process *conn, const char *ssh_host,
1359
			  const char *port, enum protocol_version version,
1360
			  int flags)
1361
{
1362
	const char *ssh;
1363
	enum ssh_variant variant;
1364

1365
	if (looks_like_command_line_option(ssh_host))
1366
		die(_("strange hostname '%s' blocked"), ssh_host);
1367

1368
	ssh = get_ssh_command();
1369
	if (ssh) {
1370
		variant = determine_ssh_variant(ssh, 1);
1371
	} else {
1372
		/*
1373
		 * GIT_SSH is the no-shell version of
1374
		 * GIT_SSH_COMMAND (and must remain so for
1375
		 * historical compatibility).
1376
		 */
1377
		conn->use_shell = 0;
1378

1379
		ssh = getenv("GIT_SSH");
1380
		if (!ssh)
1381
			ssh = "ssh";
1382
		variant = determine_ssh_variant(ssh, 0);
1383
	}
1384

1385
	if (variant == VARIANT_AUTO) {
1386
		struct child_process detect = CHILD_PROCESS_INIT;
1387

1388
		detect.use_shell = conn->use_shell;
1389
		detect.no_stdin = detect.no_stdout = detect.no_stderr = 1;
1390

1391
		strvec_push(&detect.args, ssh);
1392
		strvec_push(&detect.args, "-G");
1393
		push_ssh_options(&detect.args, &detect.env,
1394
				 VARIANT_SSH, port, version, flags);
1395
		strvec_push(&detect.args, ssh_host);
1396

1397
		variant = run_command(&detect) ? VARIANT_SIMPLE : VARIANT_SSH;
1398
	}
1399

1400
	strvec_push(&conn->args, ssh);
1401
	push_ssh_options(&conn->args, &conn->env, variant, port, version,
1402
			 flags);
1403
	strvec_push(&conn->args, ssh_host);
1404
}
1405

1406
/*
1407
 * This returns the dummy child_process `no_fork` if the transport protocol
1408
 * does not need fork(2), or a struct child_process object if it does.  Once
1409
 * done, finish the connection with finish_connect() with the value returned
1410
 * from this function (it is safe to call finish_connect() with NULL to
1411
 * support the former case).
1412
 *
1413
 * If it returns, the connect is successful; it just dies on errors (this
1414
 * will hopefully be changed in a libification effort, to return NULL when
1415
 * the connection failed).
1416
 */
1417
struct child_process *git_connect(int fd[2], const char *url,
1418
				  const char *name,
1419
				  const char *prog, int flags)
1420
{
1421
	char *hostandport, *path;
1422
	struct child_process *conn;
1423
	enum protocol protocol;
1424
	enum protocol_version version = get_protocol_version_config();
1425

1426
	/*
1427
	 * NEEDSWORK: If we are trying to use protocol v2 and we are planning
1428
	 * to perform any operation that doesn't involve upload-pack (i.e., a
1429
	 * fetch, ls-remote, etc), then fallback to v0 since we don't know how
1430
	 * to do anything else (like push or remote archive) via v2.
1431
	 */
1432
	if (version == protocol_v2 && strcmp("git-upload-pack", name))
1433
		version = protocol_v0;
1434

1435
	/* Without this we cannot rely on waitpid() to tell
1436
	 * what happened to our children.
1437
	 */
1438
	signal(SIGCHLD, SIG_DFL);
1439

1440
	protocol = parse_connect_url(url, &hostandport, &path);
1441
	if ((flags & CONNECT_DIAG_URL) && (protocol != PROTO_SSH)) {
1442
		printf("Diag: url=%s\n", url ? url : "NULL");
1443
		printf("Diag: protocol=%s\n", prot_name(protocol));
1444
		printf("Diag: hostandport=%s\n", hostandport ? hostandport : "NULL");
1445
		printf("Diag: path=%s\n", path ? path : "NULL");
1446
		conn = NULL;
1447
	} else if (protocol == PROTO_GIT) {
1448
		conn = git_connect_git(fd, hostandport, path, prog, version, flags);
1449
		conn->trace2_child_class = "transport/git";
1450
	} else {
1451
		struct strbuf cmd = STRBUF_INIT;
1452
		const char *const *var;
1453

1454
		conn = xmalloc(sizeof(*conn));
1455
		child_process_init(conn);
1456

1457
		if (looks_like_command_line_option(path))
1458
			die(_("strange pathname '%s' blocked"), path);
1459

1460
		strbuf_addstr(&cmd, prog);
1461
		strbuf_addch(&cmd, ' ');
1462
		sq_quote_buf(&cmd, path);
1463

1464
		/* remove repo-local variables from the environment */
1465
		for (var = local_repo_env; *var; var++)
1466
			strvec_push(&conn->env, *var);
1467

1468
		conn->use_shell = 1;
1469
		conn->in = conn->out = -1;
1470
		if (protocol == PROTO_SSH) {
1471
			char *ssh_host = hostandport;
1472
			const char *port = NULL;
1473
			transport_check_allowed("ssh");
1474
			get_host_and_port(&ssh_host, &port);
1475

1476
			if (!port)
1477
				port = get_port(ssh_host);
1478

1479
			if (flags & CONNECT_DIAG_URL) {
1480
				printf("Diag: url=%s\n", url ? url : "NULL");
1481
				printf("Diag: protocol=%s\n", prot_name(protocol));
1482
				printf("Diag: userandhost=%s\n", ssh_host ? ssh_host : "NULL");
1483
				printf("Diag: port=%s\n", port ? port : "NONE");
1484
				printf("Diag: path=%s\n", path ? path : "NULL");
1485

1486
				free(hostandport);
1487
				free(path);
1488
				free(conn);
1489
				strbuf_release(&cmd);
1490
				return NULL;
1491
			}
1492
			conn->trace2_child_class = "transport/ssh";
1493
			fill_ssh_args(conn, ssh_host, port, version, flags);
1494
		} else {
1495
			transport_check_allowed("file");
1496
			conn->trace2_child_class = "transport/file";
1497
			if (version > 0) {
1498
				strvec_pushf(&conn->env,
1499
					     GIT_PROTOCOL_ENVIRONMENT "=version=%d",
1500
					     version);
1501
			}
1502
		}
1503
		strvec_push(&conn->args, cmd.buf);
1504

1505
		if (start_command(conn))
1506
			die(_("unable to fork"));
1507

1508
		fd[0] = conn->out; /* read from child's stdout */
1509
		fd[1] = conn->in;  /* write to child's stdin */
1510
		strbuf_release(&cmd);
1511
	}
1512
	free(hostandport);
1513
	free(path);
1514
	return conn;
1515
}
1516

1517
int finish_connect(struct child_process *conn)
1518
{
1519
	int code;
1520
	if (!conn || git_connection_is_socket(conn))
1521
		return 0;
1522

1523
	code = finish_command(conn);
1524
	free(conn);
1525
	return code;
1526
}
1527

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.