Bug Summary

File:src/gnu/usr.bin/cvs/src/client.c
Warning:line 3701, column 42
Access to field 'h_addr_list' results in a dereference of a null pointer (loaded from variable 'hostinfo')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name client.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/cvs/obj/src -resource-dir /usr/local/lib/clang/13.0.0 -D HAVE_CONFIG_H -I . -I /usr/src/gnu/usr.bin/cvs/src -I .. -I . -I /usr/src/gnu/usr.bin/cvs/lib -I /usr/src/gnu/usr.bin/cvs/diff -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/gnu/usr.bin/cvs/obj/src -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/gnu/usr.bin/cvs/src/client.c
1/* JT thinks BeOS is worth the trouble. */
2
3/* CVS client-related stuff.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details. */
14
15#ifdef HAVE_CONFIG_H1
16#include "config.h"
17#endif /* HAVE_CONFIG_H */
18
19#include <assert.h>
20#include "cvs.h"
21#include "getline.h"
22#include "edit.h"
23#include "buffer.h"
24
25#ifdef CLIENT_SUPPORT1
26
27#include "md5.h"
28
29#if defined(AUTH_CLIENT_SUPPORT1) || HAVE_KERBEROS || defined(SOCK_ERRNO(*__errno())) || defined(SOCK_STRERRORstrerror)
30# ifdef HAVE_WINSOCK_H
31# include <winsock.h>
32# else /* No winsock.h */
33# include <sys/socket.h>
34# include <netinet/in.h>
35# include <arpa/inet.h>
36# include <netdb.h>
37# endif /* No winsock.h */
38#endif
39
40/* If SOCK_ERRNO is defined, then send()/recv() and other socket calls
41 do not set errno, but that this macro should be used to obtain an
42 error code. This probably doesn't make sense unless
43 NO_SOCKET_TO_FD is also defined. */
44#ifndef SOCK_ERRNO(*__errno())
45#define SOCK_ERRNO(*__errno()) errno(*__errno())
46#endif
47
48/* If SOCK_STRERROR is defined, then the error codes returned by
49 socket operations are not known to strerror, and this macro must be
50 used instead to convert those error codes to strings. */
51#ifndef SOCK_STRERRORstrerror
52# define SOCK_STRERRORstrerror strerror
53
54# if STDC_HEADERS1
55# include <string.h>
56# endif
57
58# ifndef strerror
59extern char *strerror ();
60# endif
61#endif /* ! SOCK_STRERROR */
62
63#if HAVE_KERBEROS
64#define CVS_PORT 1999
65
66#include <krb.h>
67
68extern char *krb_realmofhost ();
69#ifndef HAVE_KRB_GET_ERR_TEXT
70#define krb_get_err_text(status) krb_err_txt[status]
71#endif /* HAVE_KRB_GET_ERR_TEXT */
72
73/* Information we need if we are going to use Kerberos encryption. */
74static C_Block kblock;
75static Key_schedule sched;
76
77#endif /* HAVE_KERBEROS */
78
79#ifdef HAVE_GSSAPI
80
81# include "xgssapi.h"
82
83/* This is needed for GSSAPI encryption. */
84static gss_ctx_id_t gcontext;
85
86static int connect_to_gserver PROTO((int, const char *))(int, const char *);
87
88#endif /* HAVE_GSSAPI */
89
90static void add_prune_candidate PROTO((char *))(char *);
91
92/* All the commands. */
93int add PROTO((int argc, char **argv))(int argc, char **argv);
94int admin PROTO((int argc, char **argv))(int argc, char **argv);
95int checkout PROTO((int argc, char **argv))(int argc, char **argv);
96int commit PROTO((int argc, char **argv))(int argc, char **argv);
97int diff PROTO((int argc, char **argv))(int argc, char **argv);
98int history PROTO((int argc, char **argv))(int argc, char **argv);
99int import PROTO((int argc, char **argv))(int argc, char **argv);
100int cvslog PROTO((int argc, char **argv))(int argc, char **argv);
101int patch PROTO((int argc, char **argv))(int argc, char **argv);
102int release PROTO((int argc, char **argv))(int argc, char **argv);
103int cvsremove PROTO((int argc, char **argv))(int argc, char **argv);
104int rtag PROTO((int argc, char **argv))(int argc, char **argv);
105int status PROTO((int argc, char **argv))(int argc, char **argv);
106int tag PROTO((int argc, char **argv))(int argc, char **argv);
107int update PROTO((int argc, char **argv))(int argc, char **argv);
108
109/* All the response handling functions. */
110static void handle_ok PROTO((char *, int))(char *, int);
111static void handle_error PROTO((char *, int))(char *, int);
112static void handle_valid_requests PROTO((char *, int))(char *, int);
113static void handle_checked_in PROTO((char *, int))(char *, int);
114static void handle_new_entry PROTO((char *, int))(char *, int);
115static void handle_checksum PROTO((char *, int))(char *, int);
116static void handle_copy_file PROTO((char *, int))(char *, int);
117static void handle_updated PROTO((char *, int))(char *, int);
118static void handle_merged PROTO((char *, int))(char *, int);
119static void handle_patched PROTO((char *, int))(char *, int);
120static void handle_rcs_diff PROTO((char *, int))(char *, int);
121static void handle_removed PROTO((char *, int))(char *, int);
122static void handle_remove_entry PROTO((char *, int))(char *, int);
123static void handle_set_static_directory PROTO((char *, int))(char *, int);
124static void handle_clear_static_directory PROTO((char *, int))(char *, int);
125static void handle_set_sticky PROTO((char *, int))(char *, int);
126static void handle_clear_sticky PROTO((char *, int))(char *, int);
127static void handle_set_checkin_prog PROTO((char *, int))(char *, int);
128static void handle_set_update_prog PROTO((char *, int))(char *, int);
129static void handle_module_expansion PROTO((char *, int))(char *, int);
130static void handle_wrapper_rcs_option PROTO((char *, int))(char *, int);
131static void handle_m PROTO((char *, int))(char *, int);
132static void handle_e PROTO((char *, int))(char *, int);
133static void handle_f PROTO((char *, int))(char *, int);
134static void handle_notified PROTO((char *, int))(char *, int);
135
136static size_t try_read_from_server PROTO ((char *, size_t))(char *, size_t);
137#endif /* CLIENT_SUPPORT */
138
139#ifdef CLIENT_SUPPORT1
140
141/* We need to keep track of the list of directories we've sent to the
142 server. This list, along with the current CVSROOT, will help us
143 decide which command-line arguments to send. */
144List *dirs_sent_to_server = NULL((void*)0);
145
146static int is_arg_a_parent_or_listed_dir PROTO((Node *, void *))(Node *, void *);
147
148static int
149is_arg_a_parent_or_listed_dir (n, d)
150 Node *n;
151 void *d;
152{
153 char *directory = n->key; /* name of the dir sent to server */
154 char *this_argv_elem = (char *) d; /* this argv element */
155
156 /* Say we should send this argument if the argument matches the
157 beginning of a directory name sent to the server. This way,
158 the server will know to start at the top of that directory
159 hierarchy and descend. */
160
161 if (strncmp (directory, this_argv_elem, strlen (this_argv_elem)) == 0)
162 return 1;
163
164 return 0;
165}
166
167static int arg_should_not_be_sent_to_server PROTO((char *))(char *);
168
169/* Return nonzero if this argument should not be sent to the
170 server. */
171
172static int
173arg_should_not_be_sent_to_server (arg)
174 char *arg;
175{
176 /* Decide if we should send this directory name to the server. We
177 should always send argv[i] if:
178
179 1) the list of directories sent to the server is empty (as it
180 will be for checkout, etc.).
181
182 2) the argument is "."
183
184 3) the argument is a file in the cwd and the cwd is checked out
185 from the current root
186
187 4) the argument lies within one of the paths in
188 dirs_sent_to_server.
189
190 */
191
192 if (list_isempty (dirs_sent_to_server))
193 return 0; /* always send it */
194
195 if (strcmp (arg, ".") == 0)
196 return 0; /* always send it */
197
198 /* We should send arg if it is one of the directories sent to the
199 server or the parent of one; this tells the server to descend
200 the hierarchy starting at this level. */
201 if (isdir (arg))
202 {
203 if (walklist (dirs_sent_to_server, is_arg_a_parent_or_listed_dir, arg))
204 return 0;
205
206 /* If arg wasn't a parent, we don't know anything about it (we
207 would have seen something related to it during the
208 send_files phase). Don't send it. */
209 return 1;
210 }
211
212 /* Try to decide whether we should send arg to the server by
213 checking the contents of the corresponding CVSADM directory. */
214 {
215 char *t, *this_root;
216
217 /* Calculate "dirname arg" */
218 for (t = arg + strlen (arg) - 1; t >= arg; t--)
219 {
220 if (ISDIRSEP(*t)((*t) == '/'))
221 break;
222 }
223
224 /* Now we're either poiting to the beginning of the
225 string, or we found a path separator. */
226 if (t >= arg)
227 {
228 /* Found a path separator. */
229 char c = *t;
230 *t = '\0';
231
232 /* First, check to see if we sent this directory to the
233 server, because it takes less time than actually
234 opening the stuff in the CVSADM directory. */
235 if (walklist (dirs_sent_to_server, is_arg_a_parent_or_listed_dir,
236 arg))
237 {
238 *t = c; /* make sure to un-truncate the arg */
239 return 0;
240 }
241
242 /* Since we didn't find it in the list, check the CVSADM
243 files on disk. */
244 this_root = Name_Root (arg, (char *) NULL((void*)0));
245 *t = c;
246 }
247 else
248 {
249 /* We're at the beginning of the string. Look at the
250 CVSADM files in cwd. */
251 this_root = Name_Root ((char *) NULL((void*)0), (char *) NULL((void*)0));
252 }
253
254 /*
255 * This is so bogus! Means if you have checked out from
256 * a replica of a repository, and then when you want to
257 * check it in to the real (read/write) repository, the
258 * file will be skipped!
259 */
260#if 0
261 /* Now check the value for root. */
262 if (this_root && current_parsed_root
263 && (strcmp (this_root, current_parsed_root->original) != 0))
264 {
265 /* Don't send this, since the CVSROOTs don't match. */
266 free (this_root);
267 return 1;
268 }
269#endif
270 free (this_root);
271 }
272
273 /* OK, let's send it. */
274 return 0;
275}
276
277
278#endif /* CLIENT_SUPPORT */
279
280#if defined(CLIENT_SUPPORT1) || defined(SERVER_SUPPORT1)
281
282/* Shared with server. */
283
284/*
285 * Return a malloc'd, '\0'-terminated string
286 * corresponding to the mode in SB.
287 */
288char *
289#ifdef __STDC__1
290mode_to_string (mode_t mode)
291#else /* ! __STDC__ */
292mode_to_string (mode)
293 mode_t mode;
294#endif /* __STDC__ */
295{
296 char buf[18], u[4], g[4], o[4];
297 int i;
298
299 i = 0;
300 if (mode & S_IRUSR0000400) u[i++] = 'r';
301 if (mode & S_IWUSR0000200) u[i++] = 'w';
302 if (mode & S_IXUSR0000100) u[i++] = 'x';
303 u[i] = '\0';
304
305 i = 0;
306 if (mode & S_IRGRP0000040) g[i++] = 'r';
307 if (mode & S_IWGRP0000020) g[i++] = 'w';
308 if (mode & S_IXGRP0000010) g[i++] = 'x';
309 g[i] = '\0';
310
311 i = 0;
312 if (mode & S_IROTH0000004) o[i++] = 'r';
313 if (mode & S_IWOTH0000002) o[i++] = 'w';
314 if (mode & S_IXOTH0000001) o[i++] = 'x';
315 o[i] = '\0';
316
317 sprintf(buf, "u=%s,g=%s,o=%s", u, g, o);
318 return xstrdup(buf);
319}
320
321/*
322 * Change mode of FILENAME to MODE_STRING.
323 * Returns 0 for success or errno code.
324 * If RESPECT_UMASK is set, then honor the umask.
325 */
326int
327change_mode (filename, mode_string, respect_umask)
328 char *filename;
329 char *mode_string;
330 int respect_umask;
331{
332#ifdef CHMOD_BROKEN
333 char *p;
334 int writeable = 0;
335
336 /* We can only distinguish between
337 1) readable
338 2) writeable
339 3) Picasso's "Blue Period"
340 We handle the first two. */
341 p = mode_string;
342 while (*p != '\0')
343 {
344 if ((p[0] == 'u' || p[0] == 'g' || p[0] == 'o') && p[1] == '=')
345 {
346 char *q = p + 2;
347 while (*q != ',' && *q != '\0')
348 {
349 if (*q == 'w')
350 writeable = 1;
351 ++q;
352 }
353 }
354 /* Skip to the next field. */
355 while (*p != ',' && *p != '\0')
356 ++p;
357 if (*p == ',')
358 ++p;
359 }
360
361 /* xchmod honors the umask for us. In the !respect_umask case, we
362 don't try to cope with it (probably to handle that well, the server
363 needs to deal with modes in data structures, rather than via the
364 modes in temporary files). */
365 xchmod (filename, writeable);
366 return 0;
367
368#else /* ! CHMOD_BROKEN */
369
370 char *p;
371 mode_t mode = 0;
372 mode_t oumask;
373
374 p = mode_string;
375 while (*p != '\0')
376 {
377 if ((p[0] == 'u' || p[0] == 'g' || p[0] == 'o') && p[1] == '=')
378 {
379 int can_read = 0, can_write = 0, can_execute = 0;
380 char *q = p + 2;
381 while (*q != ',' && *q != '\0')
382 {
383 if (*q == 'r')
384 can_read = 1;
385 else if (*q == 'w')
386 can_write = 1;
387 else if (*q == 'x')
388 can_execute = 1;
389 ++q;
390 }
391 if (p[0] == 'u')
392 {
393 if (can_read)
394 mode |= S_IRUSR0000400;
395 if (can_write)
396 mode |= S_IWUSR0000200;
397 if (can_execute)
398 mode |= S_IXUSR0000100;
399 }
400 else if (p[0] == 'g')
401 {
402 if (can_read)
403 mode |= S_IRGRP0000040;
404 if (can_write)
405 mode |= S_IWGRP0000020;
406 if (can_execute)
407 mode |= S_IXGRP0000010;
408 }
409 else if (p[0] == 'o')
410 {
411 if (can_read)
412 mode |= S_IROTH0000004;
413 if (can_write)
414 mode |= S_IWOTH0000002;
415 if (can_execute)
416 mode |= S_IXOTH0000001;
417 }
418 }
419 /* Skip to the next field. */
420 while (*p != ',' && *p != '\0')
421 ++p;
422 if (*p == ',')
423 ++p;
424 }
425
426 if (respect_umask)
427 {
428 oumask = umask (0);
429 (void) umask (oumask);
430 mode &= ~oumask;
431 }
432
433 if (chmod (filename, mode) < 0)
434 return errno(*__errno());
435 return 0;
436#endif /* ! CHMOD_BROKEN */
437}
438
439#endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
440
441#ifdef CLIENT_SUPPORT1
442
443int client_prune_dirs;
444
445static List *ignlist = (List *) NULL((void*)0);
446
447/* Buffer to write to the server. */
448static struct buffer *to_server;
449/* The stream underlying to_server, if we are using a stream. */
450static FILE *to_server_fp;
451
452/* Buffer used to read from the server. */
453static struct buffer *from_server;
454/* The stream underlying from_server, if we are using a stream. */
455static FILE *from_server_fp;
456
457/* Process ID of rsh subprocess. */
458static int rsh_pid = -1;
459
460
461/* We want to be able to log data sent between us and the server. We
462 do it using log buffers. Each log buffer has another buffer which
463 handles the actual I/O, and a file to log information to.
464
465 This structure is the closure field of a log buffer. */
466
467struct log_buffer
468{
469 /* The underlying buffer. */
470 struct buffer *buf;
471 /* The file to log information to. */
472 FILE *log;
473};
474
475static struct buffer *log_buffer_initialize
476 PROTO((struct buffer *, FILE *, int, void (*) (struct buffer *)))(struct buffer *, FILE *, int, void (*) (struct buffer *));
477static int log_buffer_input PROTO((void *, char *, int, int, int *))(void *, char *, int, int, int *);
478static int log_buffer_output PROTO((void *, const char *, int, int *))(void *, const char *, int, int *);
479static int log_buffer_flush PROTO((void *))(void *);
480static int log_buffer_block PROTO((void *, int))(void *, int);
481static int log_buffer_shutdown PROTO((void *))(void *);
482
483/* Create a log buffer. */
484
485static struct buffer *
486log_buffer_initialize (buf, fp, input, memory)
487 struct buffer *buf;
488 FILE *fp;
489 int input;
490 void (*memory) PROTO((struct buffer *))(struct buffer *);
491{
492 struct log_buffer *n;
493
494 n = (struct log_buffer *) xmalloc (sizeof *n);
495 n->buf = buf;
496 n->log = fp;
497 return buf_initialize (input ? log_buffer_input : NULL((void*)0),
498 input ? NULL((void*)0) : log_buffer_output,
499 input ? NULL((void*)0) : log_buffer_flush,
500 log_buffer_block,
501 log_buffer_shutdown,
502 memory,
503 n);
504}
505
506/* The input function for a log buffer. */
507
508static int
509log_buffer_input (closure, data, need, size, got)
510 void *closure;
511 char *data;
512 int need;
513 int size;
514 int *got;
515{
516 struct log_buffer *lb = (struct log_buffer *) closure;
517 int status;
518 size_t n_to_write;
519
520 if (lb->buf->input == NULL((void*)0))
521 abort ();
522
523 status = (*lb->buf->input) (lb->buf->closure, data, need, size, got);
524 if (status != 0)
525 return status;
526
527 if (*got > 0)
528 {
529 n_to_write = *got;
530 if (fwrite (data, 1, n_to_write, lb->log) != n_to_write)
531 error (0, errno(*__errno()), "writing to log file");
532 }
533
534 return 0;
535}
536
537/* The output function for a log buffer. */
538
539static int
540log_buffer_output (closure, data, have, wrote)
541 void *closure;
542 const char *data;
543 int have;
544 int *wrote;
545{
546 struct log_buffer *lb = (struct log_buffer *) closure;
547 int status;
548 size_t n_to_write;
549
550 if (lb->buf->output == NULL((void*)0))
551 abort ();
552
553 status = (*lb->buf->output) (lb->buf->closure, data, have, wrote);
554 if (status != 0)
555 return status;
556
557 if (*wrote > 0)
558 {
559 n_to_write = *wrote;
560 if (fwrite (data, 1, n_to_write, lb->log) != n_to_write)
561 error (0, errno(*__errno()), "writing to log file");
562 }
563
564 return 0;
565}
566
567/* The flush function for a log buffer. */
568
569static int
570log_buffer_flush (closure)
571 void *closure;
572{
573 struct log_buffer *lb = (struct log_buffer *) closure;
574
575 if (lb->buf->flush == NULL((void*)0))
576 abort ();
577
578 /* We don't really have to flush the log file here, but doing it
579 will let tail -f on the log file show what is sent to the
580 network as it is sent. */
581 if (fflush (lb->log) != 0)
582 error (0, errno(*__errno()), "flushing log file");
583
584 return (*lb->buf->flush) (lb->buf->closure);
585}
586
587/* The block function for a log buffer. */
588
589static int
590log_buffer_block (closure, block)
591 void *closure;
592 int block;
593{
594 struct log_buffer *lb = (struct log_buffer *) closure;
595
596 if (block)
597 return set_block (lb->buf);
598 else
599 return set_nonblock (lb->buf);
600}
601
602/* The shutdown function for a log buffer. */
603
604static int
605log_buffer_shutdown (closure)
606 void *closure;
607{
608 struct log_buffer *lb = (struct log_buffer *) closure;
609 int retval;
610
611 retval = buf_shutdown (lb->buf);
612 if (fclose (lb->log) < 0)
613 error (0, errno(*__errno()), "closing log file");
614 return retval;
615}
616
617#ifdef NO_SOCKET_TO_FD
618
619/* Under certain circumstances, we must communicate with the server
620 via a socket using send() and recv(). This is because under some
621 operating systems (OS/2 and Windows 95 come to mind), a socket
622 cannot be converted to a file descriptor -- it must be treated as a
623 socket and nothing else.
624
625 We may also need to deal with socket routine error codes differently
626 in these cases. This is handled through the SOCK_ERRNO and
627 SOCK_STRERROR macros. */
628
629static int use_socket_style = 0;
630static int server_sock;
631
632/* These routines implement a buffer structure which uses send and
633 recv. The buffer is always in blocking mode so we don't implement
634 the block routine. */
635
636/* Note that it is important that these routines always handle errors
637 internally and never return a positive errno code, since it would in
638 general be impossible for the caller to know in general whether any
639 error code came from a socket routine (to decide whether to use
640 SOCK_STRERROR or simply strerror to print an error message). */
641
642/* We use an instance of this structure as the closure field. */
643
644struct socket_buffer
645{
646 /* The socket number. */
647 int socket;
648};
649
650static struct buffer *socket_buffer_initialize
651 PROTO ((int, int, void (*) (struct buffer *)))(int, int, void (*) (struct buffer *));
652static int socket_buffer_input PROTO((void *, char *, int, int, int *))(void *, char *, int, int, int *);
653static int socket_buffer_output PROTO((void *, const char *, int, int *))(void *, const char *, int, int *);
654static int socket_buffer_flush PROTO((void *))(void *);
655
656/* Create a buffer based on a socket. */
657
658static struct buffer *
659socket_buffer_initialize (socket, input, memory)
660 int socket;
661 int input;
662 void (*memory) PROTO((struct buffer *))(struct buffer *);
663{
664 struct socket_buffer *n;
665
666 n = (struct socket_buffer *) xmalloc (sizeof *n);
667 n->socket = socket;
668 return buf_initialize (input ? socket_buffer_input : NULL((void*)0),
669 input ? NULL((void*)0) : socket_buffer_output,
670 input ? NULL((void*)0) : socket_buffer_flush,
671 (int (*) PROTO((void *, int))(void *, int)) NULL((void*)0),
672 (int (*) PROTO((void *))(void *)) NULL((void*)0),
673 memory,
674 n);
675}
676
677/* The buffer input function for a buffer built on a socket. */
678
679static int
680socket_buffer_input (closure, data, need, size, got)
681 void *closure;
682 char *data;
683 int need;
684 int size;
685 int *got;
686{
687 struct socket_buffer *sb = (struct socket_buffer *) closure;
688 int nbytes;
689
690 /* I believe that the recv function gives us exactly the semantics
691 we want. If there is a message, it returns immediately with
692 whatever it could get. If there is no message, it waits until
693 one comes in. In other words, it is not like read, which in
694 blocking mode normally waits until all the requested data is
695 available. */
696
697 *got = 0;
698
699 do
700 {
701
702 /* Note that for certain (broken?) networking stacks, like
703 VMS's UCX (not sure what version, problem reported with
704 recv() in 1997), and (according to windows-NT/config.h)
705 Windows NT 3.51, we must call recv or send with a
706 moderately sized buffer (say, less than 200K or something),
707 or else there may be network errors (somewhat hard to
708 produce, e.g. WAN not LAN or some such). buf_read_data
709 makes sure that we only recv() BUFFER_DATA_SIZE bytes at
710 a time. */
711
712 nbytes = recv (sb->socket, data, size, 0);
713 if (nbytes < 0)
714 error (1, 0, "reading from server: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
715 if (nbytes == 0)
716 {
717 /* End of file (for example, the server has closed
718 the connection). If we've already read something, we
719 just tell the caller about the data, not about the end of
720 file. If we've read nothing, we return end of file. */
721 if (*got == 0)
722 return -1;
723 else
724 return 0;
725 }
726 need -= nbytes;
727 size -= nbytes;
728 data += nbytes;
729 *got += nbytes;
730 }
731 while (need > 0);
732
733 return 0;
734}
735
736/* The buffer output function for a buffer built on a socket. */
737
738static int
739socket_buffer_output (closure, data, have, wrote)
740 void *closure;
741 const char *data;
742 int have;
743 int *wrote;
744{
745 struct socket_buffer *sb = (struct socket_buffer *) closure;
746
747 *wrote = have;
748
749 /* See comment in socket_buffer_input regarding buffer size we pass
750 to send and recv. */
751
752#ifdef SEND_NEVER_PARTIAL
753 /* If send() never will produce a partial write, then just do it. This
754 is needed for systems where its return value is something other than
755 the number of bytes written. */
756 if (send (sb->socket, data, have, 0) < 0)
757 error (1, 0, "writing to server socket: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
758#else
759 while (have > 0)
760 {
761 int nbytes;
762
763 nbytes = send (sb->socket, data, have, 0);
764 if (nbytes < 0)
765 error (1, 0, "writing to server socket: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
766
767 have -= nbytes;
768 data += nbytes;
769 }
770#endif
771
772 return 0;
773}
774
775/* The buffer flush function for a buffer built on a socket. */
776
777/*ARGSUSED*/
778static int
779socket_buffer_flush (closure)
780 void *closure;
781{
782 /* Nothing to do. Sockets are always flushed. */
783 return 0;
784}
785
786#endif /* NO_SOCKET_TO_FD */
787
788/*
789 * Read a line from the server. Result does not include the terminating \n.
790 *
791 * Space for the result is malloc'd and should be freed by the caller.
792 *
793 * Returns number of bytes read.
794 */
795static int
796read_line (resultp)
797 char **resultp;
798{
799 int status;
800 char *result;
801 int len;
802
803 status = buf_flush (to_server, 1);
804 if (status != 0)
805 error (1, status, "writing to server");
806
807 status = buf_read_line (from_server, &result, &len);
808 if (status != 0)
809 {
810 if (status == -1)
811 error (1, 0, "end of file from server (consult above messages if any)");
812 else if (status == -2)
813 error (1, 0, "out of memory");
814 else
815 error (1, status, "reading from server");
816 }
817
818 if (resultp != NULL((void*)0))
819 *resultp = result;
820 else
821 free (result);
822
823 return len;
824}
825
826#endif /* CLIENT_SUPPORT */
827
828
829#if defined(CLIENT_SUPPORT1) || defined(SERVER_SUPPORT1)
830
831/*
832 * Zero if compression isn't supported or requested; non-zero to indicate
833 * a compression level to request from gzip.
834 */
835int gzip_level;
836
837/*
838 * Level of compression to use when running gzip on a single file.
839 */
840int file_gzip_level;
841
842#endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
843
844#ifdef CLIENT_SUPPORT1
845
846/*
847 * The Repository for the top level of this command (not necessarily
848 * the CVSROOT, just the current directory at the time we do it).
849 */
850static char *toplevel_repos = NULL((void*)0);
851
852/* Working directory when we first started. Note: we could speed things
853 up on some systems by using savecwd.h here instead of just always
854 storing a name. */
855char *toplevel_wd;
856
857static void
858handle_ok (args, len)
859 char *args;
860 int len;
861{
862 return;
863}
864
865static void
866handle_error (args, len)
867 char *args;
868 int len;
869{
870 int something_printed;
871
872 /*
873 * First there is a symbolic error code followed by a space, which
874 * we ignore.
875 */
876 char *p = strchr (args, ' ');
877 if (p == NULL((void*)0))
878 {
879 error (0, 0, "invalid data from cvs server");
880 return;
881 }
882 ++p;
883
884 /* Next we print the text of the message from the server. We
885 probably should be prefixing it with "server error" or some
886 such, because if it is something like "Out of memory", the
887 current behavior doesn't say which machine is out of
888 memory. */
889
890 len -= p - args;
891 something_printed = 0;
892 for (; len > 0; --len)
893 {
894 something_printed = 1;
895 putc (*p++, stderr)(!__isthreaded ? __sputc(*p++, (&__sF[2])) : (putc)(*p++,
(&__sF[2])))
;
896 }
897 if (something_printed)
898 putc ('\n', stderr)(!__isthreaded ? __sputc('\n', (&__sF[2])) : (putc)('\n',
(&__sF[2])))
;
899}
900
901static void
902handle_valid_requests (args, len)
903 char *args;
904 int len;
905{
906 char *p = args;
907 char *q;
908 struct request *rq;
909 do
910 {
911 q = strchr (p, ' ');
912 if (q != NULL((void*)0))
913 *q++ = '\0';
914 for (rq = requests; rq->name != NULL((void*)0); ++rq)
915 {
916 if (strcmp (rq->name, p) == 0)
917 break;
918 }
919 if (rq->name == NULL((void*)0))
920 /*
921 * It is a request we have never heard of (and thus never
922 * will want to use). So don't worry about it.
923 */
924 ;
925 else
926 {
927 if (rq->flags & RQ_ENABLEME4)
928 {
929 /*
930 * Server wants to know if we have this, to enable the
931 * feature.
932 */
933 send_to_server (rq->name, 0);
934 send_to_server ("\012", 0);
935 }
936 else
937 rq->flags |= RQ_SUPPORTED2;
938 }
939 p = q;
940 } while (q != NULL((void*)0));
941 for (rq = requests; rq->name != NULL((void*)0); ++rq)
942 {
943 if ((rq->flags & RQ_SUPPORTED2)
944 || (rq->flags & RQ_ENABLEME4))
945 continue;
946 if (rq->flags & RQ_ESSENTIAL1)
947 error (1, 0, "request `%s' not supported by server", rq->name);
948 }
949}
950
951/* This variable holds the result of Entries_Open, so that we can
952 close Entries_Close on it when we move on to a new directory, or
953 when we finish. */
954static List *last_entries;
955
956/*
957 * Do all the processing for PATHNAME, where pathname consists of the
958 * repository and the filename. The parameters we pass to FUNC are:
959 * DATA is just the DATA parameter which was passed to
960 * call_in_directory; ENT_LIST is a pointer to an entries list (which
961 * we manage the storage for); SHORT_PATHNAME is the pathname of the
962 * file relative to the (overall) directory in which the command is
963 * taking place; and FILENAME is the filename portion only of
964 * SHORT_PATHNAME. When we call FUNC, the curent directory points to
965 * the directory portion of SHORT_PATHNAME. */
966
967static char *last_dir_name;
968
969static void
970call_in_directory (pathname, func, data)
971 char *pathname;
972 void (*func) PROTO((char *data, List *ent_list, char *short_pathname,(char *data, List *ent_list, char *short_pathname, char *filename
)
973 char *filename))(char *data, List *ent_list, char *short_pathname, char *filename
)
;
974 char *data;
975{
976 char *dir_name;
977 char *filename;
978 /* This is what we get when we hook up the directory (working directory
979 name) from PATHNAME with the filename from REPOSNAME. For example:
980 pathname: ccvs/src/
981 reposname: /u/src/master/ccvs/foo/ChangeLog
982 short_pathname: ccvs/src/ChangeLog
983 */
984 char *short_pathname;
985 char *p;
986
987 /*
988 * Do the whole descent in parallel for the repositories, so we
989 * know what to put in CVS/Repository files. I'm not sure the
990 * full hair is necessary since the server does a similar
991 * computation; I suspect that we only end up creating one
992 * directory at a time anyway.
993 *
994 * Also note that we must *only* worry about this stuff when we
995 * are creating directories; `cvs co foo/bar; cd foo/bar; cvs co
996 * CVSROOT; cvs update' is legitimate, but in this case
997 * foo/bar/CVSROOT/CVS/Repository is not a subdirectory of
998 * foo/bar/CVS/Repository.
999 */
1000 char *reposname;
1001 char *short_repos;
1002 char *reposdirname;
1003 char *rdirp;
1004 int reposdirname_absolute;
1005
1006 /*
1007 * For security reasons, if PATHNAME is absolute or attempts to
1008 * ascend outside of the current sandbox, we abort. The server should not
1009 * send us anything but relative paths which remain inside the sandbox
1010 * here. Anything less means a trojan CVS server could create and edit
1011 * arbitrary files on the client.
1012 */
1013 if (isabsolute (pathname) || pathname_levels (pathname) > 0)
1014 {
1015 error (0, 0,
1016 "Server attempted to update a file via an invalid pathname:");
1017 error (1, 0, "`%s'.", pathname);
1018 }
1019
1020 reposname = NULL((void*)0);
1021 read_line (&reposname);
1022 assert (reposname != NULL)((reposname != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/cvs/src/client.c"
, 1022, __func__, "reposname != NULL"))
;
1023
1024 reposdirname_absolute = 0;
1025 if (strncmp (reposname, toplevel_repos, strlen (toplevel_repos)) != 0)
1026 {
1027 reposdirname_absolute = 1;
1028 short_repos = reposname;
1029 }
1030 else
1031 {
1032 short_repos = reposname + strlen (toplevel_repos) + 1;
1033 if (short_repos[-1] != '/')
1034 {
1035 reposdirname_absolute = 1;
1036 short_repos = reposname;
1037 }
1038 }
1039 reposdirname = xstrdup (short_repos);
1040 p = strrchr (reposdirname, '/');
1041 if (p == NULL((void*)0))
1042 {
1043 reposdirname = xrealloc (reposdirname, 2);
1044 reposdirname[0] = '.'; reposdirname[1] = '\0';
1045 }
1046 else
1047 *p = '\0';
1048
1049 dir_name = xstrdup (pathname);
1050 p = strrchr (dir_name, '/');
1051 if (p == NULL((void*)0))
1052 {
1053 dir_name = xrealloc (dir_name, 2);
1054 dir_name[0] = '.'; dir_name[1] = '\0';
1055 }
1056 else
1057 *p = '\0';
1058 if (client_prune_dirs)
1059 add_prune_candidate (dir_name);
1060
1061 filename = strrchr (short_repos, '/');
1062 if (filename == NULL((void*)0))
1063 filename = short_repos;
1064 else
1065 ++filename;
1066
1067 short_pathname = xmalloc (strlen (pathname) + strlen (filename) + 5);
1068 strcpy (short_pathname, pathname);
1069 strcat (short_pathname, filename);
1070
1071 if (last_dir_name == NULL((void*)0)
1072 || strcmp (last_dir_name, dir_name) != 0)
1073 {
1074 int newdir;
1075
1076 if (strcmp (command_name, "export") != 0)
1077 if (last_entries)
1078 Entries_Close (last_entries);
1079
1080 if (last_dir_name)
1081 free (last_dir_name);
1082 last_dir_name = dir_name;
1083
1084 if (toplevel_wd == NULL((void*)0))
1085 {
1086 toplevel_wd = xgetwd ();
1087 if (toplevel_wd == NULL((void*)0))
1088 error (1, errno(*__errno()), "could not get working directory");
1089 }
1090
1091 if (CVS_CHDIRchdir (toplevel_wd) < 0)
1092 error (1, errno(*__errno()), "could not chdir to %s", toplevel_wd);
1093 newdir = 0;
1094
1095 /* Create the CVS directory at the top level if needed. The
1096 isdir seems like an unneeded system call, but it *does*
1097 need to be called both if the CVS_CHDIR below succeeds
1098 (e.g. "cvs co .") or if it fails (e.g. basicb-1a in
1099 testsuite). We only need to do this for the "." case,
1100 since the server takes care of forcing this directory to be
1101 created in all other cases. If we don't create CVSADM
1102 here, the call to Entries_Open below will fail. FIXME:
1103 perhaps this means that we should change our algorithm
1104 below that calls Create_Admin instead of having this code
1105 here? */
1106 if (/* I think the reposdirname_absolute case has to do with
1107 things like "cvs update /foo/bar". In any event, the
1108 code below which tries to put toplevel_repos into
1109 CVS/Repository is almost surely unsuited to
1110 the reposdirname_absolute case. */
1111 !reposdirname_absolute
1112 && (strcmp (dir_name, ".") == 0)
1113 && ! isdir (CVSADM"CVS"))
1114 {
1115 char *repo;
1116 char *r;
1117
1118 newdir = 1;
1119
1120 repo = xmalloc (strlen (toplevel_repos)
1121 + 10);
1122 strcpy (repo, toplevel_repos);
1123 r = repo + strlen (repo);
1124 if (r[-1] != '.' || r[-2] != '/')
1125 strcpy (r, "/.");
1126
1127 Create_Admin (".", ".", repo, (char *) NULL((void*)0),
1128 (char *) NULL((void*)0), 0, 1, 1);
1129
1130 free (repo);
1131 }
1132
1133 if ( CVS_CHDIRchdir (dir_name) < 0)
1134 {
1135 char *dir;
1136 char *dirp;
1137
1138 if (! existence_error (errno)(((*__errno())) == 2))
1139 error (1, errno(*__errno()), "could not chdir to %s", dir_name);
1140
1141 /* Directory does not exist, we need to create it. */
1142 newdir = 1;
1143
1144 /* Provided we are willing to assume that directories get
1145 created one at a time, we could simplify this a lot.
1146 Do note that one aspect still would need to walk the
1147 dir_name path: the checking for "fncmp (dir, CVSADM)". */
1148
1149 dir = xmalloc (strlen (dir_name) + 1);
1150 dirp = dir_name;
1151 rdirp = reposdirname;
1152
1153 /* This algorithm makes nested directories one at a time
1154 and create CVS administration files in them. For
1155 example, we're checking out foo/bar/baz from the
1156 repository:
1157
1158 1) create foo, point CVS/Repository to <root>/foo
1159 2) .. foo/bar .. <root>/foo/bar
1160 3) .. foo/bar/baz .. <root>/foo/bar/baz
1161
1162 As you can see, we're just stepping along DIR_NAME (with
1163 DIRP) and REPOSDIRNAME (with RDIRP) respectively.
1164
1165 We need to be careful when we are checking out a
1166 module, however, since DIR_NAME and REPOSDIRNAME are not
1167 going to be the same. Since modules will not have any
1168 slashes in their names, we should watch the output of
1169 STRCHR to decide whether or not we should use STRCHR on
1170 the RDIRP. That is, if we're down to a module name,
1171 don't keep picking apart the repository directory name. */
1172
1173 do
1174 {
1175 dirp = strchr (dirp, '/');
1176 if (dirp)
1177 {
1178 strncpy (dir, dir_name, dirp - dir_name);
1179 dir[dirp - dir_name] = '\0';
1180 /* Skip the slash. */
1181 ++dirp;
1182 if (rdirp == NULL((void*)0))
1183 /* This just means that the repository string has
1184 fewer components than the dir_name string. But
1185 that is OK (e.g. see modules3-8 in testsuite). */
1186 ;
1187 else
1188 rdirp = strchr (rdirp, '/');
1189 }
1190 else
1191 {
1192 /* If there are no more slashes in the dir name,
1193 we're down to the most nested directory -OR- to
1194 the name of a module. In the first case, we
1195 should be down to a DIRP that has no slashes,
1196 so it won't help/hurt to do another STRCHR call
1197 on DIRP. It will definitely hurt, however, if
1198 we're down to a module name, since a module
1199 name can point to a nested directory (that is,
1200 DIRP will still have slashes in it. Therefore,
1201 we should set it to NULL so the routine below
1202 copies the contents of REMOTEDIRNAME onto the
1203 root repository directory (does this if rdirp
1204 is set to NULL, because we used to do an extra
1205 STRCHR call here). */
1206
1207 rdirp = NULL((void*)0);
1208 strcpy (dir, dir_name);
1209 }
1210
1211 if (fncmpstrcmp (dir, CVSADM"CVS") == 0)
1212 {
1213 error (0, 0, "cannot create a directory named %s", dir);
1214 error (0, 0, "because CVS uses \"%s\" for its own uses",
1215 CVSADM"CVS");
1216 error (1, 0, "rename the directory and try again");
1217 }
1218
1219 if (mkdir_if_needed (dir))
1220 {
1221 /* It already existed, fine. Just keep going. */
1222 }
1223 else if (strcmp (command_name, "export") == 0)
1224 /* Don't create CVSADM directories if this is export. */
1225 ;
1226 else
1227 {
1228 /*
1229 * Put repository in CVS/Repository. For historical
1230 * (pre-CVS/Root) reasons, this is an absolute pathname,
1231 * but what really matters is the part of it which is
1232 * relative to cvsroot.
1233 */
1234 char *repo;
1235 char *r, *b;
1236
1237 repo = xmalloc (strlen (reposdirname)
1238 + strlen (toplevel_repos)
1239 + 80);
1240 if (reposdirname_absolute)
1241 r = repo;
1242 else
1243 {
1244 strcpy (repo, toplevel_repos);
1245 strcat (repo, "/");
1246 r = repo + strlen (repo);
1247 }
1248
1249 if (rdirp)
1250 {
1251 /* See comment near start of function; the only
1252 way that the server can put the right thing
1253 in each CVS/Repository file is to create the
1254 directories one at a time. I think that the
1255 CVS server has been doing this all along. */
1256 error (0, 0, "\
1257warning: server is not creating directories one at a time");
1258 strncpy (r, reposdirname, rdirp - reposdirname);
1259 r[rdirp - reposdirname] = '\0';
1260 }
1261 else
1262 strcpy (r, reposdirname);
1263
1264 Create_Admin (dir, dir, repo,
1265 (char *)NULL((void*)0), (char *)NULL((void*)0), 0, 0, 1);
1266 free (repo);
1267
1268 b = strrchr (dir, '/');
1269 if (b == NULL((void*)0))
1270 Subdir_Register ((List *) NULL((void*)0), (char *) NULL((void*)0), dir);
1271 else
1272 {
1273 *b = '\0';
1274 Subdir_Register ((List *) NULL((void*)0), dir, b + 1);
1275 *b = '/';
1276 }
1277 }
1278
1279 if (rdirp != NULL((void*)0))
1280 {
1281 /* Skip the slash. */
1282 ++rdirp;
1283 }
1284
1285 } while (dirp != NULL((void*)0));
1286 free (dir);
1287 /* Now it better work. */
1288 if ( CVS_CHDIRchdir (dir_name) < 0)
1289 error (1, errno(*__errno()), "could not chdir to %s", dir_name);
1290 }
1291 else if (!isdir (CVSADM"CVS"))
1292 {
1293 /*
1294 * Put repository in CVS/Repository. For historical
1295 * (pre-CVS/Root) reasons, this is an absolute pathname,
1296 * but what really matters is the part of it which is
1297 * relative to cvsroot.
1298 */
1299 char *repo;
1300
1301 if (reposdirname_absolute)
1302 repo = reposdirname;
1303 else
1304 {
1305 repo = xmalloc (strlen (reposdirname)
1306 + strlen (toplevel_repos)
1307 + 10);
1308 strcpy (repo, toplevel_repos);
1309 strcat (repo, "/");
1310 strcat (repo, reposdirname);
1311 }
1312
1313 Create_Admin (".", ".", repo, (char *)NULL((void*)0), (char *)NULL((void*)0), 0, 1, 1);
1314 if (repo != reposdirname)
1315 free (repo);
1316 }
1317
1318 if (strcmp (command_name, "export") != 0)
1319 {
1320 last_entries = Entries_Open (0, dir_name);
1321
1322 /* If this is a newly created directory, we will record
1323 all subdirectory information, so call Subdirs_Known in
1324 case there are no subdirectories. If this is not a
1325 newly created directory, it may be an old working
1326 directory from before we recorded subdirectory
1327 information in the Entries file. We force a search for
1328 all subdirectories now, to make sure our subdirectory
1329 information is up to date. If the Entries file does
1330 record subdirectory information, then this call only
1331 does list manipulation. */
1332 if (newdir)
1333 Subdirs_Known (last_entries);
1334 else
1335 {
1336 List *dirlist;
1337
1338 dirlist = Find_Directories ((char *) NULL((void*)0), W_LOCAL0x01,
1339 last_entries);
1340 dellist (&dirlist);
1341 }
1342 }
1343 }
1344 else
1345 free (dir_name);
1346 free (reposdirname);
1347 (*func) (data, last_entries, short_pathname, filename);
1348 free (short_pathname);
1349 free (reposname);
1350}
1351
1352static void
1353copy_a_file (data, ent_list, short_pathname, filename)
1354 char *data;
1355 List *ent_list;
1356 char *short_pathname;
1357 char *filename;
1358{
1359 char *newname;
1360#ifdef USE_VMS_FILENAMES
1361 char *p;
1362#endif
1363
1364 read_line (&newname);
1365
1366#ifdef USE_VMS_FILENAMES
1367 /* Mogrify the filename so VMS is happy with it. */
1368 for(p = newname; *p; p++)
1369 if(*p == '.' || *p == '#') *p = '_';
1370#endif
1371 /* cvsclient.texi has said for a long time that newname must be in the
1372 same directory. Wouldn't want a malicious or buggy server overwriting
1373 ~/.profile, /etc/passwd, or anything like that. */
1374 if (last_component (newname) != newname)
1375 error (1, 0, "protocol error: Copy-file tried to specify directory");
1376
1377 if (unlink_file (newname) && !existence_error (errno)(((*__errno())) == 2))
1378 error (0, errno(*__errno()), "unable to remove %s", newname);
1379 copy_file (filename, newname);
1380 free (newname);
1381}
1382
1383static void
1384handle_copy_file (args, len)
1385 char *args;
1386 int len;
1387{
1388 call_in_directory (args, copy_a_file, (char *)NULL((void*)0));
1389}
1390
1391
1392static void read_counted_file PROTO ((char *, char *))(char *, char *);
1393
1394/* Read from the server the count for the length of a file, then read
1395 the contents of that file and write them to FILENAME. FULLNAME is
1396 the name of the file for use in error messages. FIXME-someday:
1397 extend this to deal with compressed files and make update_entries
1398 use it. On error, gives a fatal error. */
1399static void
1400read_counted_file (filename, fullname)
1401 char *filename;
1402 char *fullname;
1403{
1404 char *size_string;
1405 size_t size;
1406 char *buf;
1407
1408 /* Pointers in buf to the place to put data which will be read,
1409 and the data which needs to be written, respectively. */
1410 char *pread;
1411 char *pwrite;
1412 /* Number of bytes left to read and number of bytes in buf waiting to
1413 be written, respectively. */
1414 size_t nread;
1415 size_t nwrite;
1416
1417 FILE *fp;
1418
1419 read_line (&size_string);
1420 if (size_string[0] == 'z')
1421 error (1, 0, "\
1422protocol error: compressed files not supported for that operation");
1423 /* FIXME: should be doing more error checking, probably. Like using
1424 strtoul and making sure we used up the whole line. */
1425 size = atoi (size_string);
1426 free (size_string);
1427
1428 /* A more sophisticated implementation would use only a limited amount
1429 of buffer space (8K perhaps), and read that much at a time. We allocate
1430 a buffer for the whole file only to make it easy to keep track what
1431 needs to be read and written. */
1432 buf = xmalloc (size);
1433
1434 /* FIXME-someday: caller should pass in a flag saying whether it
1435 is binary or not. I haven't carefully looked into whether
1436 CVS/Template files should use local text file conventions or
1437 not. */
1438 fp = CVS_FOPENfopen (filename, "wb");
1439 if (fp == NULL((void*)0))
1440 error (1, errno(*__errno()), "cannot write %s", fullname);
1441 nread = size;
1442 nwrite = 0;
1443 pread = buf;
1444 pwrite = buf;
1445 while (nread > 0 || nwrite > 0)
1446 {
1447 size_t n;
1448
1449 if (nread > 0)
1450 {
1451 n = try_read_from_server (pread, nread);
1452 nread -= n;
1453 pread += n;
1454 nwrite += n;
1455 }
1456
1457 if (nwrite > 0)
1458 {
1459 n = fwrite (pwrite, 1, nwrite, fp);
1460 if (ferror (fp)(!__isthreaded ? (((fp)->_flags & 0x0040) != 0) : (ferror
)(fp))
)
1461 error (1, errno(*__errno()), "cannot write %s", fullname);
1462 nwrite -= n;
1463 pwrite += n;
1464 }
1465 }
1466 free (buf);
1467 if (fclose (fp) < 0)
1468 error (1, errno(*__errno()), "cannot close %s", fullname);
1469}
1470
1471/* OK, we want to swallow the "U foo.c" response and then output it only
1472 if we can update the file. In the future we probably want some more
1473 systematic approach to parsing tagged text, but for now we keep it
1474 ad hoc. "Why," I hear you cry, "do we not just look at the
1475 Update-existing and Created responses?" That is an excellent question,
1476 and the answer is roughly conservatism/laziness--I haven't read through
1477 update.c enough to figure out the exact correspondence or lack thereof
1478 between those responses and a "U foo.c" line (note that Merged, from
1479 join_file, can be either "C foo" or "U foo" depending on the context). */
1480/* Nonzero if we have seen +updated and not -updated. */
1481static int updated_seen;
1482/* Filename from an "fname" tagged response within +updated/-updated. */
1483static char *updated_fname;
1484
1485/* This struct is used to hold data when reading the +importmergecmd
1486 and -importmergecmd tags. We put the variables in a struct only
1487 for namespace issues. FIXME: As noted above, we need to develop a
1488 more systematic approach. */
1489static struct
1490{
1491 /* Nonzero if we have seen +importmergecmd and not -importmergecmd. */
1492 int seen;
1493 /* Number of conflicts, from a "conflicts" tagged response. */
1494 int conflicts;
1495 /* First merge tag, from a "mergetag1" tagged response. */
1496 char *mergetag1;
1497 /* Second merge tag, from a "mergetag2" tagged response. */
1498 char *mergetag2;
1499 /* Repository, from a "repository" tagged response. */
1500 char *repository;
1501} importmergecmd;
1502
1503/* Nonzero if we should arrange to return with a failure exit status. */
1504static int failure_exit;
1505
1506
1507/*
1508 * The time stamp of the last file we registered.
1509 */
1510static time_t last_register_time;
1511
1512/*
1513 * The Checksum response gives the checksum for the file transferred
1514 * over by the next Updated, Merged or Patch response. We just store
1515 * it here, and then check it in update_entries.
1516 */
1517
1518static int stored_checksum_valid;
1519static unsigned char stored_checksum[16];
1520
1521static void
1522handle_checksum (args, len)
1523 char *args;
1524 int len;
1525{
1526 char *s;
1527 char buf[3];
1528 int i;
1529
1530 if (stored_checksum_valid)
1531 error (1, 0, "Checksum received before last one was used");
1532
1533 s = args;
1534 buf[2] = '\0';
1535 for (i = 0; i < 16; i++)
1536 {
1537 char *bufend;
1538
1539 buf[0] = *s++;
1540 buf[1] = *s++;
1541 stored_checksum[i] = (char) strtol (buf, &bufend, 16);
1542 if (bufend != buf + 2)
1543 break;
1544 }
1545
1546 if (i < 16 || *s != '\0')
1547 error (1, 0, "Invalid Checksum response: `%s'", args);
1548
1549 stored_checksum_valid = 1;
1550}
1551
1552/* Mode that we got in a "Mode" response (malloc'd), or NULL if none. */
1553static char *stored_mode;
1554
1555static void handle_mode PROTO ((char *, int))(char *, int);
1556
1557static void
1558handle_mode (args, len)
1559 char *args;
1560 int len;
1561{
1562 if (stored_mode != NULL((void*)0))
1563 error (1, 0, "protocol error: duplicate Mode");
1564 stored_mode = xstrdup (args);
1565}
1566
1567/* Nonzero if time was specified in Mod-time. */
1568static int stored_modtime_valid;
1569/* Time specified in Mod-time. */
1570static time_t stored_modtime;
1571
1572static void handle_mod_time PROTO ((char *, int))(char *, int);
1573
1574static void
1575handle_mod_time (args, len)
1576 char *args;
1577 int len;
1578{
1579 if (stored_modtime_valid)
1580 error (0, 0, "protocol error: duplicate Mod-time");
1581 stored_modtime = get_date (args);
1582 if (stored_modtime == (time_t) -1)
1583 error (0, 0, "protocol error: cannot parse date %s", args);
1584 else
1585 stored_modtime_valid = 1;
1586}
1587
1588/*
1589 * If we receive a patch, but the patch program fails to apply it, we
1590 * want to request the original file. We keep a list of files whose
1591 * patches have failed.
1592 */
1593
1594char **failed_patches;
1595int failed_patches_count;
1596
1597struct update_entries_data
1598{
1599 enum {
1600 /*
1601 * We are just getting an Entries line; the local file is
1602 * correct.
1603 */
1604 UPDATE_ENTRIES_CHECKIN,
1605 /* We are getting the file contents as well. */
1606 UPDATE_ENTRIES_UPDATE,
1607 /*
1608 * We are getting a patch against the existing local file, not
1609 * an entire new file.
1610 */
1611 UPDATE_ENTRIES_PATCH,
1612 /*
1613 * We are getting an RCS change text (diff -n output) against
1614 * the existing local file, not an entire new file.
1615 */
1616 UPDATE_ENTRIES_RCS_DIFF
1617 } contents;
1618
1619 enum {
1620 /* We are replacing an existing file. */
1621 UPDATE_ENTRIES_EXISTING,
1622 /* We are creating a new file. */
1623 UPDATE_ENTRIES_NEW,
1624 /* We don't know whether it is existing or new. */
1625 UPDATE_ENTRIES_EXISTING_OR_NEW
1626 } existp;
1627
1628 /*
1629 * String to put in the timestamp field or NULL to use the timestamp
1630 * of the file.
1631 */
1632 char *timestamp;
1633};
1634
1635/* Update the Entries line for this file. */
1636static void
1637update_entries (data_arg, ent_list, short_pathname, filename)
1638 char *data_arg;
1639 List *ent_list;
1640 char *short_pathname;
1641 char *filename;
1642{
1643 char *entries_line;
1644 struct update_entries_data *data = (struct update_entries_data *)data_arg;
1645
1646 char *cp;
1647 char *user;
1648 char *vn;
1649 /* Timestamp field. Always empty according to the protocol. */
1650 char *ts;
1651 char *options = NULL((void*)0);
1652 char *tag = NULL((void*)0);
1653 char *date = NULL((void*)0);
1654 char *tag_or_date;
1655 char *scratch_entries = NULL((void*)0);
1656 int bin;
1657
1658#ifdef UTIME_EXPECTS_WRITABLE
1659 int change_it_back = 0;
1660#endif
1661
1662 read_line (&entries_line);
1663
1664 /*
1665 * Parse the entries line.
1666 */
1667 scratch_entries = xstrdup (entries_line);
1668
1669 if (scratch_entries[0] != '/')
1670 error (1, 0, "bad entries line `%s' from server", entries_line);
1671 user = scratch_entries + 1;
1672 if ((cp = strchr (user, '/')) == NULL((void*)0))
1673 error (1, 0, "bad entries line `%s' from server", entries_line);
1674 *cp++ = '\0';
1675 vn = cp;
1676 if ((cp = strchr (vn, '/')) == NULL((void*)0))
1677 error (1, 0, "bad entries line `%s' from server", entries_line);
1678 *cp++ = '\0';
1679
1680 ts = cp;
1681 if ((cp = strchr (ts, '/')) == NULL((void*)0))
1682 error (1, 0, "bad entries line `%s' from server", entries_line);
1683 *cp++ = '\0';
1684 options = cp;
1685 if ((cp = strchr (options, '/')) == NULL((void*)0))
1686 error (1, 0, "bad entries line `%s' from server", entries_line);
1687 *cp++ = '\0';
1688 tag_or_date = cp;
1689
1690 /* If a slash ends the tag_or_date, ignore everything after it. */
1691 cp = strchr (tag_or_date, '/');
1692 if (cp != NULL((void*)0))
1693 *cp = '\0';
1694 if (*tag_or_date == 'T')
1695 tag = tag_or_date + 1;
1696 else if (*tag_or_date == 'D')
1697 date = tag_or_date + 1;
1698
1699 /* Done parsing the entries line. */
1700
1701 if (data->contents == UPDATE_ENTRIES_UPDATE
1702 || data->contents == UPDATE_ENTRIES_PATCH
1703 || data->contents == UPDATE_ENTRIES_RCS_DIFF)
1704 {
1705 char *size_string;
1706 char *mode_string;
1707 int size;
1708 char *buf;
1709 char *temp_filename;
1710 int use_gzip;
1711 int patch_failed;
1712
1713 read_line (&mode_string);
1714
1715 read_line (&size_string);
1716 if (size_string[0] == 'z')
1717 {
1718 use_gzip = 1;
1719 size = atoi (size_string+1);
1720 }
1721 else
1722 {
1723 use_gzip = 0;
1724 size = atoi (size_string);
1725 }
1726 free (size_string);
1727
1728 /* Note that checking this separately from writing the file is
1729 a race condition: if the existence or lack thereof of the
1730 file changes between now and the actual calls which
1731 operate on it, we lose. However (a) there are so many
1732 cases, I'm reluctant to try to fix them all, (b) in some
1733 cases the system might not even have a system call which
1734 does the right thing, and (c) it isn't clear this needs to
1735 work. */
1736 if (data->existp == UPDATE_ENTRIES_EXISTING
1737 && !isfile (filename))
1738 /* Emit a warning and update the file anyway. */
1739 error (0, 0, "warning: %s unexpectedly disappeared",
1740 short_pathname);
1741
1742 if (data->existp == UPDATE_ENTRIES_NEW
1743 && isfile (filename))
1744 {
1745 /* Emit a warning and refuse to update the file; we don't want
1746 to clobber a user's file. */
1747 size_t nread;
1748 size_t toread;
1749
1750 /* size should be unsigned, but until we get around to fixing
1751 that, work around it. */
1752 size_t usize;
1753
1754 char buf[8192];
1755
1756 /* This error might be confusing; it isn't really clear to
1757 the user what to do about it. Keep in mind that it has
1758 several causes: (1) something/someone creates the file
1759 during the time that CVS is running, (2) the repository
1760 has two files whose names clash for the client because
1761 of case-insensitivity or similar causes, (3) a special
1762 case of this is that a file gets renamed for example
1763 from a.c to A.C. A "cvs update" on a case-insensitive
1764 client will get this error. Repeating the update takes
1765 care of the problem, but is it clear to the user what
1766 is going on and what to do about it?, (4) the client
1767 has a file which the server doesn't know about (e.g. "?
1768 foo" file), and that name clashes with a file the
1769 server does know about, (5) classify.c will print the same
1770 message for other reasons.
1771
1772 I hope the above paragraph makes it clear that making this
1773 clearer is not a one-line fix. */
1774 error (0, 0, "move away %s; it is in the way", short_pathname);
1775 if (updated_fname != NULL((void*)0))
1776 {
1777 cvs_output ("C ", 0);
1778 cvs_output (updated_fname, 0);
1779 cvs_output ("\n", 1);
1780 }
1781 failure_exit = 1;
1782
1783 discard_file_and_return:
1784 /* Now read and discard the file contents. */
1785 usize = size;
1786 nread = 0;
1787 while (nread < usize)
1788 {
1789 toread = usize - nread;
1790 if (toread > sizeof buf)
1791 toread = sizeof buf;
1792
1793 nread += try_read_from_server (buf, toread);
1794 if (nread == usize)
1795 break;
1796 }
1797
1798 free (mode_string);
1799 free (scratch_entries);
1800 free (entries_line);
1801
1802 /* The Mode, Mod-time, and Checksum responses should not carry
1803 over to a subsequent Created (or whatever) response, even
1804 in the error case. */
1805 if (stored_mode != NULL((void*)0))
1806 {
1807 free (stored_mode);
1808 stored_mode = NULL((void*)0);
1809 }
1810 stored_modtime_valid = 0;
1811 stored_checksum_valid = 0;
1812
1813 if (updated_fname != NULL((void*)0))
1814 {
1815 free (updated_fname);
1816 updated_fname = NULL((void*)0);
1817 }
1818 return;
1819 }
1820
1821 temp_filename = xmalloc (strlen (filename) + 80);
1822#ifdef USE_VMS_FILENAMES
1823 /* A VMS rename of "blah.dat" to "foo" to implies a
1824 destination of "foo.dat" which is unfortinate for CVS */
1825 sprintf (temp_filename, "%s_new_", filename);
1826#else
1827#ifdef _POSIX_NO_TRUNC1
1828 sprintf (temp_filename, ".new.%.9s", filename);
1829#else /* _POSIX_NO_TRUNC */
1830 sprintf (temp_filename, ".new.%s", filename);
1831#endif /* _POSIX_NO_TRUNC */
1832#endif /* USE_VMS_FILENAMES */
1833
1834 buf = xmalloc (size);
1835
1836 /* Some systems, like OS/2 and Windows NT, end lines with CRLF
1837 instead of just LF. Format translation is done in the C
1838 library I/O funtions. Here we tell them whether or not to
1839 convert -- if this file is marked "binary" with the RCS -kb
1840 flag, then we don't want to convert, else we do (because
1841 CVS assumes text files by default). */
1842
1843 if (options)
1844 bin = !(strcmp (options, "-kb"));
1845 else
1846 bin = 0;
1847
1848 if (data->contents == UPDATE_ENTRIES_RCS_DIFF)
1849 {
1850 /* This is an RCS change text. We just hold the change
1851 text in memory. */
1852
1853 if (use_gzip)
1854 error (1, 0,
1855 "server error: gzip invalid with RCS change text");
1856
1857 read_from_server (buf, size);
1858 }
1859 else
1860 {
1861 int fd;
1862
1863 fd = CVS_OPENopen (temp_filename,
1864 (O_WRONLY0x0001 | O_CREAT0x0200 | O_TRUNC0x0400
1865 | (bin ? OPEN_BINARY(0) : 0)),
1866 0777);
1867
1868 if (fd < 0)
1869 {
1870 /* I can see a case for making this a fatal error; for
1871 a condition like disk full or network unreachable
1872 (for a file server), carrying on and giving an
1873 error on each file seems unnecessary. But if it is
1874 a permission problem, or some such, then it is
1875 entirely possible that future files will not have
1876 the same problem. */
1877 error (0, errno(*__errno()), "cannot write %s", short_pathname);
1878 goto discard_file_and_return;
1879 }
1880
1881 if (size > 0)
1882 {
1883 read_from_server (buf, size);
1884
1885 if (use_gzip)
1886 {
1887 if (gunzip_and_write (fd, short_pathname,
1888 (unsigned char *) buf, size))
1889 error (1, 0, "aborting due to compression error");
1890 }
1891 else if (write (fd, buf, size) != size)
1892 error (1, errno(*__errno()), "writing %s", short_pathname);
1893 }
1894
1895 if (close (fd) < 0)
1896 error (1, errno(*__errno()), "writing %s", short_pathname);
1897 }
1898
1899 /* This is after we have read the file from the net (a change
1900 from previous versions, where the server would send us
1901 "M U foo.c" before Update-existing or whatever), but before
1902 we finish writing the file (arguably a bug). The timing
1903 affects a user who wants status info about how far we have
1904 gotten, and also affects whether "U foo.c" appears in addition
1905 to various error messages. */
1906 if (updated_fname != NULL((void*)0))
1907 {
1908 cvs_output ("U ", 0);
1909 cvs_output (updated_fname, 0);
1910 cvs_output ("\n", 1);
1911 free (updated_fname);
1912 updated_fname = 0;
1913 }
1914
1915 patch_failed = 0;
1916
1917 if (data->contents == UPDATE_ENTRIES_UPDATE)
1918 {
1919 rename_file (temp_filename, filename);
1920 }
1921 else if (data->contents == UPDATE_ENTRIES_PATCH)
1922 {
1923 /* You might think we could just leave Patched out of
1924 Valid-responses and not get this response. However, if
1925 memory serves, the CVS 1.9 server bases this on -u
1926 (update-patches), and there is no way for us to send -u
1927 or not based on whether the server supports "Rcs-diff".
1928
1929 Fall back to transmitting entire files. */
1930 patch_failed = 1;
1931 }
1932 else
1933 {
1934 char *filebuf;
1935 size_t filebufsize;
1936 size_t nread;
1937 char *patchedbuf;
1938 size_t patchedlen;
1939
1940 /* Handle UPDATE_ENTRIES_RCS_DIFF. */
1941
1942 if (!isfile (filename))
1943 error (1, 0, "patch original file %s does not exist",
1944 short_pathname);
1945 filebuf = NULL((void*)0);
1946 filebufsize = 0;
1947 nread = 0;
1948
1949 get_file (filename, short_pathname, bin ? FOPEN_BINARY_READ("rb") : "r",
1950 &filebuf, &filebufsize, &nread);
1951 /* At this point the contents of the existing file are in
1952 FILEBUF, and the length of the contents is in NREAD.
1953 The contents of the patch from the network are in BUF,
1954 and the length of the patch is in SIZE. */
1955
1956 if (! rcs_change_text (short_pathname, filebuf, nread, buf, size,
1957 &patchedbuf, &patchedlen))
1958 patch_failed = 1;
1959 else
1960 {
1961 if (stored_checksum_valid)
1962 {
1963 struct cvs_MD5Context context;
1964 unsigned char checksum[16];
1965
1966 /* We have a checksum. Check it before writing
1967 the file out, so that we don't have to read it
1968 back in again. */
1969 cvs_MD5Init (&context);
1970 cvs_MD5Update (&context,
1971 (unsigned char *) patchedbuf, patchedlen);
1972 cvs_MD5Final (checksum, &context);
1973 if (memcmp (checksum, stored_checksum, 16) != 0)
1974 {
1975 error (0, 0,
1976 "checksum failure after patch to %s; will refetch",
1977 short_pathname);
1978
1979 patch_failed = 1;
1980 }
1981
1982 stored_checksum_valid = 0;
1983 }
1984
1985 if (! patch_failed)
1986 {
1987 FILE *e;
1988
1989 e = open_file (temp_filename,
1990 bin ? FOPEN_BINARY_WRITE("wb") : "w");
1991 if (fwrite (patchedbuf, 1, patchedlen, e) != patchedlen)
1992 error (1, errno(*__errno()), "cannot write %s", temp_filename);
1993 if (fclose (e) == EOF(-1))
1994 error (1, errno(*__errno()), "cannot close %s", temp_filename);
1995 rename_file (temp_filename, filename);
1996 }
1997
1998 free (patchedbuf);
1999 }
2000
2001 free (filebuf);
2002 }
2003
2004 free (temp_filename);
2005
2006 if (stored_checksum_valid && ! patch_failed)
2007 {
2008 FILE *e;
2009 struct cvs_MD5Context context;
2010 unsigned char buf[8192];
2011 unsigned len;
2012 unsigned char checksum[16];
2013
2014 /*
2015 * Compute the MD5 checksum. This will normally only be
2016 * used when receiving a patch, so we always compute it
2017 * here on the final file, rather than on the received
2018 * data.
2019 *
2020 * Note that if the file is a text file, we should read it
2021 * here using text mode, so its lines will be terminated the same
2022 * way they were transmitted.
2023 */
2024 e = CVS_FOPENfopen (filename, "r");
2025 if (e == NULL((void*)0))
2026 error (1, errno(*__errno()), "could not open %s", short_pathname);
2027
2028 cvs_MD5Init (&context);
2029 while ((len = fread (buf, 1, sizeof buf, e)) != 0)
2030 cvs_MD5Update (&context, buf, len);
2031 if (ferror (e)(!__isthreaded ? (((e)->_flags & 0x0040) != 0) : (ferror
)(e))
)
2032 error (1, errno(*__errno()), "could not read %s", short_pathname);
2033 cvs_MD5Final (checksum, &context);
2034
2035 fclose (e);
2036
2037 stored_checksum_valid = 0;
2038
2039 if (memcmp (checksum, stored_checksum, 16) != 0)
2040 {
2041 if (data->contents != UPDATE_ENTRIES_PATCH)
2042 error (1, 0, "checksum failure on %s",
2043 short_pathname);
2044
2045 error (0, 0,
2046 "checksum failure after patch to %s; will refetch",
2047 short_pathname);
2048
2049 patch_failed = 1;
2050 }
2051 }
2052
2053 if (patch_failed)
2054 {
2055 /* Save this file to retrieve later. */
2056 failed_patches = (char **) xrealloc ((char *) failed_patches,
2057 ((failed_patches_count + 1)
2058 * sizeof (char *)));
2059 failed_patches[failed_patches_count] = xstrdup (short_pathname);
2060 ++failed_patches_count;
2061
2062 stored_checksum_valid = 0;
2063
2064 free (mode_string);
2065 free (buf);
2066 free (scratch_entries);
2067 free (entries_line);
2068
2069 return;
2070 }
2071
2072 {
2073 int status = change_mode (filename, mode_string, 1);
2074 if (status != 0)
2075 error (0, status, "cannot change mode of %s", short_pathname);
2076 }
2077
2078 free (mode_string);
2079 free (buf);
2080 }
2081
2082 if (stored_mode != NULL((void*)0))
2083 {
2084 change_mode (filename, stored_mode, 1);
2085 free (stored_mode);
2086 stored_mode = NULL((void*)0);
2087 }
2088
2089 if (stored_modtime_valid)
2090 {
2091 struct utimbuf t;
2092
2093 memset (&t, 0, sizeof (t));
2094 /* There is probably little point in trying to preserved the
2095 actime (or is there? What about Checked-in?). */
2096 t.modtime = t.actime = stored_modtime;
2097
2098#ifdef UTIME_EXPECTS_WRITABLE
2099 if (!iswritable (filename))
2100 {
2101 xchmod (filename, 1);
2102 change_it_back = 1;
2103 }
2104#endif /* UTIME_EXPECTS_WRITABLE */
2105
2106 if (utime (filename, &t) < 0)
2107 error (0, errno(*__errno()), "cannot set time on %s", filename);
2108
2109#ifdef UTIME_EXPECTS_WRITABLE
2110 if (change_it_back == 1)
2111 {
2112 xchmod (filename, 0);
2113 change_it_back = 0;
2114 }
2115#endif /* UTIME_EXPECTS_WRITABLE */
2116
2117 stored_modtime_valid = 0;
2118 }
2119
2120 /*
2121 * Process the entries line. Do this after we've written the file,
2122 * since we need the timestamp.
2123 */
2124 if (strcmp (command_name, "export") != 0)
2125 {
2126 char *local_timestamp;
2127 char *file_timestamp;
2128
2129 (void) time (&last_register_time);
2130
2131 local_timestamp = data->timestamp;
2132 if (local_timestamp == NULL((void*)0) || ts[0] == '+')
2133 file_timestamp = time_stamp (filename);
2134 else
2135 file_timestamp = NULL((void*)0);
2136
2137 /*
2138 * These special version numbers signify that it is not up to
2139 * date. Create a dummy timestamp which will never compare
2140 * equal to the timestamp of the file.
2141 */
2142 if (vn[0] == '\0' || vn[0] == '0' || vn[0] == '-')
2143 local_timestamp = "dummy timestamp";
2144 else if (local_timestamp == NULL((void*)0))
2145 {
2146 local_timestamp = file_timestamp;
2147
2148 /* Checking for command_name of "commit" doesn't seem like
2149 the cleanest way to handle this, but it seem to roughly
2150 parallel what the :local: code which calls
2151 mark_up_to_date ends up amounting to. Some day, should
2152 think more about what the Checked-in response means
2153 vis-a-vis both Entries and Base and clarify
2154 cvsclient.texi accordingly. */
2155
2156 if (!strcmp (command_name, "commit"))
2157 mark_up_to_date (filename);
2158 }
2159
2160 Register (ent_list, filename, vn, local_timestamp,
2161 options, tag, date, ts[0] == '+' ? file_timestamp : NULL((void*)0));
2162
2163 if (file_timestamp)
2164 free (file_timestamp);
2165
2166 }
2167 free (scratch_entries);
2168 free (entries_line);
2169}
2170
2171static void
2172handle_checked_in (args, len)
2173 char *args;
2174 int len;
2175{
2176 struct update_entries_data dat;
2177 dat.contents = UPDATE_ENTRIES_CHECKIN;
2178 dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
2179 dat.timestamp = NULL((void*)0);
2180 call_in_directory (args, update_entries, (char *)&dat);
2181}
2182
2183static void
2184handle_new_entry (args, len)
2185 char *args;
2186 int len;
2187{
2188 struct update_entries_data dat;
2189 dat.contents = UPDATE_ENTRIES_CHECKIN;
2190 dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
2191 dat.timestamp = "dummy timestamp from new-entry";
2192 call_in_directory (args, update_entries, (char *)&dat);
2193}
2194
2195static void
2196handle_updated (args, len)
2197 char *args;
2198 int len;
2199{
2200 struct update_entries_data dat;
2201 dat.contents = UPDATE_ENTRIES_UPDATE;
2202 dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
2203 dat.timestamp = NULL((void*)0);
2204 call_in_directory (args, update_entries, (char *)&dat);
2205}
2206
2207static void handle_created PROTO((char *, int))(char *, int);
2208
2209static void
2210handle_created (args, len)
2211 char *args;
2212 int len;
2213{
2214 struct update_entries_data dat;
2215 dat.contents = UPDATE_ENTRIES_UPDATE;
2216 dat.existp = UPDATE_ENTRIES_NEW;
2217 dat.timestamp = NULL((void*)0);
2218 call_in_directory (args, update_entries, (char *)&dat);
2219}
2220
2221static void handle_update_existing PROTO((char *, int))(char *, int);
2222
2223static void
2224handle_update_existing (args, len)
2225 char *args;
2226 int len;
2227{
2228 struct update_entries_data dat;
2229 dat.contents = UPDATE_ENTRIES_UPDATE;
2230 dat.existp = UPDATE_ENTRIES_EXISTING;
2231 dat.timestamp = NULL((void*)0);
2232 call_in_directory (args, update_entries, (char *)&dat);
2233}
2234
2235static void
2236handle_merged (args, len)
2237 char *args;
2238 int len;
2239{
2240 struct update_entries_data dat;
2241 dat.contents = UPDATE_ENTRIES_UPDATE;
2242 /* Think this could be UPDATE_ENTRIES_EXISTING, but just in case... */
2243 dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
2244 dat.timestamp = "Result of merge";
2245 call_in_directory (args, update_entries, (char *)&dat);
2246}
2247
2248static void
2249handle_patched (args, len)
2250 char *args;
2251 int len;
2252{
2253 struct update_entries_data dat;
2254 dat.contents = UPDATE_ENTRIES_PATCH;
2255 /* Think this could be UPDATE_ENTRIES_EXISTING, but just in case... */
2256 dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
2257 dat.timestamp = NULL((void*)0);
2258 call_in_directory (args, update_entries, (char *)&dat);
2259}
2260
2261static void
2262handle_rcs_diff (args, len)
2263 char *args;
2264 int len;
2265{
2266 struct update_entries_data dat;
2267 dat.contents = UPDATE_ENTRIES_RCS_DIFF;
2268 /* Think this could be UPDATE_ENTRIES_EXISTING, but just in case... */
2269 dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
2270 dat.timestamp = NULL((void*)0);
2271 call_in_directory (args, update_entries, (char *)&dat);
2272}
2273
2274static void
2275remove_entry (data, ent_list, short_pathname, filename)
2276 char *data;
2277 List *ent_list;
2278 char *short_pathname;
2279 char *filename;
2280{
2281 Scratch_Entry (ent_list, filename);
2282}
2283
2284static void
2285handle_remove_entry (args, len)
2286 char *args;
2287 int len;
2288{
2289 call_in_directory (args, remove_entry, (char *)NULL((void*)0));
2290}
2291
2292static void
2293remove_entry_and_file (data, ent_list, short_pathname, filename)
2294 char *data;
2295 List *ent_list;
2296 char *short_pathname;
2297 char *filename;
2298{
2299 Scratch_Entry (ent_list, filename);
2300 /* Note that we don't ignore existence_error's here. The server
2301 should be sending Remove-entry rather than Removed in cases
2302 where the file does not exist. And if the user removes the
2303 file halfway through a cvs command, we should be printing an
2304 error. */
2305 if (unlink_file (filename) < 0)
2306 error (0, errno(*__errno()), "unable to remove %s", short_pathname);
2307}
2308
2309static void
2310handle_removed (args, len)
2311 char *args;
2312 int len;
2313{
2314 call_in_directory (args, remove_entry_and_file, (char *)NULL((void*)0));
2315}
2316
2317/* Is this the top level (directory containing CVSROOT)? */
2318static int
2319is_cvsroot_level (pathname)
2320 char *pathname;
2321{
2322 if (strcmp (toplevel_repos, current_parsed_root->directory) != 0)
2323 return 0;
2324
2325 return strchr (pathname, '/') == NULL((void*)0);
2326}
2327
2328static void
2329set_static (data, ent_list, short_pathname, filename)
2330 char *data;
2331 List *ent_list;
2332 char *short_pathname;
2333 char *filename;
2334{
2335 FILE *fp;
2336 fp = open_file (CVSADM_ENTSTAT"CVS/Entries.Static", "w+");
2337 if (fclose (fp) == EOF(-1))
2338 error (1, errno(*__errno()), "cannot close %s", CVSADM_ENTSTAT"CVS/Entries.Static");
2339}
2340
2341static void
2342handle_set_static_directory (args, len)
2343 char *args;
2344 int len;
2345{
2346 if (strcmp (command_name, "export") == 0)
2347 {
2348 /* Swallow the repository. */
2349 read_line (NULL((void*)0));
2350 return;
2351 }
2352 call_in_directory (args, set_static, (char *)NULL((void*)0));
2353}
2354
2355static void
2356clear_static (data, ent_list, short_pathname, filename)
2357 char *data;
2358 List *ent_list;
2359 char *short_pathname;
2360 char *filename;
2361{
2362 if (unlink_file (CVSADM_ENTSTAT"CVS/Entries.Static") < 0 && ! existence_error (errno)(((*__errno())) == 2))
2363 error (1, errno(*__errno()), "cannot remove file %s", CVSADM_ENTSTAT"CVS/Entries.Static");
2364}
2365
2366static void
2367handle_clear_static_directory (pathname, len)
2368 char *pathname;
2369 int len;
2370{
2371 if (strcmp (command_name, "export") == 0)
2372 {
2373 /* Swallow the repository. */
2374 read_line (NULL((void*)0));
2375 return;
2376 }
2377
2378 if (is_cvsroot_level (pathname))
2379 {
2380 /*
2381 * Top level (directory containing CVSROOT). This seems to normally
2382 * lack a CVS directory, so don't try to create files in it.
2383 */
2384 return;
2385 }
2386 call_in_directory (pathname, clear_static, (char *)NULL((void*)0));
2387}
2388
2389static void
2390set_sticky (data, ent_list, short_pathname, filename)
2391 char *data;
2392 List *ent_list;
2393 char *short_pathname;
2394 char *filename;
2395{
2396 char *tagspec;
2397 FILE *f;
2398
2399 read_line (&tagspec);
2400
2401 /* FIXME-update-dir: error messages should include the directory. */
2402 f = CVS_FOPENfopen (CVSADM_TAG"CVS/Tag", "w+");
2403 if (f == NULL((void*)0))
2404 {
2405 /* Making this non-fatal is a bit of a kludge (see dirs2
2406 in testsuite). A better solution would be to avoid having
2407 the server tell us about a directory we shouldn't be doing
2408 anything with anyway (e.g. by handling directory
2409 addition/removal better). */
2410 error (0, errno(*__errno()), "cannot open %s", CVSADM_TAG"CVS/Tag");
2411 free (tagspec);
2412 return;
2413 }
2414 if (fprintf (f, "%s\n", tagspec) < 0)
2415 error (1, errno(*__errno()), "writing %s", CVSADM_TAG"CVS/Tag");
2416 if (fclose (f) == EOF(-1))
2417 error (1, errno(*__errno()), "closing %s", CVSADM_TAG"CVS/Tag");
2418 free (tagspec);
2419}
2420
2421static void
2422handle_set_sticky (pathname, len)
2423 char *pathname;
2424 int len;
2425{
2426 if (strcmp (command_name, "export") == 0)
2427 {
2428 /* Swallow the repository. */
2429 read_line (NULL((void*)0));
2430 /* Swallow the tag line. */
2431 read_line (NULL((void*)0));
2432 return;
2433 }
2434 if (is_cvsroot_level (pathname))
2435 {
2436 /*
2437 * Top level (directory containing CVSROOT). This seems to normally
2438 * lack a CVS directory, so don't try to create files in it.
2439 */
2440
2441 /* Swallow the repository. */
2442 read_line (NULL((void*)0));
2443 /* Swallow the tag line. */
2444 read_line (NULL((void*)0));
2445 return;
2446 }
2447
2448 call_in_directory (pathname, set_sticky, (char *)NULL((void*)0));
2449}
2450
2451static void
2452clear_sticky (data, ent_list, short_pathname, filename)
2453 char *data;
2454 List *ent_list;
2455 char *short_pathname;
2456 char *filename;
2457{
2458 if (unlink_file (CVSADM_TAG"CVS/Tag") < 0 && ! existence_error (errno)(((*__errno())) == 2))
2459 error (1, errno(*__errno()), "cannot remove %s", CVSADM_TAG"CVS/Tag");
2460}
2461
2462static void
2463handle_clear_sticky (pathname, len)
2464 char *pathname;
2465 int len;
2466{
2467 if (strcmp (command_name, "export") == 0)
2468 {
2469 /* Swallow the repository. */
2470 read_line (NULL((void*)0));
2471 return;
2472 }
2473
2474 if (is_cvsroot_level (pathname))
2475 {
2476 /*
2477 * Top level (directory containing CVSROOT). This seems to normally
2478 * lack a CVS directory, so don't try to create files in it.
2479 */
2480 return;
2481 }
2482
2483 call_in_directory (pathname, clear_sticky, (char *)NULL((void*)0));
2484}
2485
2486
2487static void template PROTO ((char *, List *, char *, char *))(char *, List *, char *, char *);
2488
2489static void
2490template (data, ent_list, short_pathname, filename)
2491 char *data;
2492 List *ent_list;
2493 char *short_pathname;
2494 char *filename;
2495{
2496 /* FIXME: should be computing second argument from CVSADM_TEMPLATE
2497 and short_pathname. */
2498 read_counted_file (CVSADM_TEMPLATE"CVS/Template", "<CVS/Template file>");
2499}
2500
2501static void handle_template PROTO ((char *, int))(char *, int);
2502
2503static void
2504handle_template (pathname, len)
2505 char *pathname;
2506 int len;
2507{
2508 call_in_directory (pathname, template, NULL((void*)0));
2509}
2510
2511
2512struct save_prog {
2513 char *name;
2514 char *dir;
2515 struct save_prog *next;
2516};
2517
2518static struct save_prog *checkin_progs;
2519static struct save_prog *update_progs;
2520
2521/*
2522 * Unlike some responses this doesn't include the repository. So we can't
2523 * just call call_in_directory and have the right thing happen; we save up
2524 * the requests and do them at the end.
2525 */
2526static void
2527handle_set_checkin_prog (args, len)
2528 char *args;
2529 int len;
2530{
2531 char *prog;
2532 struct save_prog *p;
2533
2534 read_line (&prog);
2535 if (strcmp (command_name, "export") == 0)
2536 return;
2537
2538 p = (struct save_prog *) xmalloc (sizeof (struct save_prog));
2539 p->next = checkin_progs;
2540 p->dir = xstrdup (args);
2541 p->name = prog;
2542 checkin_progs = p;
2543}
2544
2545static void
2546handle_set_update_prog (args, len)
2547 char *args;
2548 int len;
2549{
2550 char *prog;
2551 struct save_prog *p;
2552
2553 read_line (&prog);
2554 if (strcmp (command_name, "export") == 0)
2555 return;
2556
2557 p = (struct save_prog *) xmalloc (sizeof (struct save_prog));
2558 p->next = update_progs;
2559 p->dir = xstrdup (args);
2560 p->name = prog;
2561 update_progs = p;
2562}
2563
2564static void do_deferred_progs PROTO((void))(void);
2565
2566static void
2567do_deferred_progs ()
2568{
2569 struct save_prog *p;
2570 struct save_prog *q;
2571
2572 char *fname;
2573 FILE *f;
2574
2575 if (toplevel_wd != NULL((void*)0))
2576 {
2577 if (CVS_CHDIRchdir (toplevel_wd) < 0)
2578 error (1, errno(*__errno()), "could not chdir to %s", toplevel_wd);
2579 }
2580 for (p = checkin_progs; p != NULL((void*)0); )
2581 {
2582 fname = xmalloc (strlen (p->dir) + sizeof CVSADM_CIPROG"CVS/Checkin.prog" + 10);
2583 sprintf (fname, "%s/%s", p->dir, CVSADM_CIPROG"CVS/Checkin.prog");
2584 f = open_file (fname, "w");
2585 if (fprintf (f, "%s\n", p->name) < 0)
2586 error (1, errno(*__errno()), "writing %s", fname);
2587 if (fclose (f) == EOF(-1))
2588 error (1, errno(*__errno()), "closing %s", fname);
2589 free (p->name);
2590 free (p->dir);
2591 q = p->next;
2592 free (p);
2593 p = q;
2594 free (fname);
2595 }
2596 checkin_progs = NULL((void*)0);
2597 for (p = update_progs; p != NULL((void*)0); )
2598 {
2599 fname = xmalloc (strlen (p->dir) + sizeof CVSADM_UPROG"CVS/Update.prog" + 10);
2600 sprintf (fname, "%s/%s", p->dir, CVSADM_UPROG"CVS/Update.prog");
2601 f = open_file (fname, "w");
2602 if (fprintf (f, "%s\n", p->name) < 0)
2603 error (1, errno(*__errno()), "writing %s", fname);
2604 if (fclose (f) == EOF(-1))
2605 error (1, errno(*__errno()), "closing %s", fname);
2606 free (p->name);
2607 free (p->dir);
2608 q = p->next;
2609 free (p);
2610 p = q;
2611 free (fname);
2612 }
2613 update_progs = NULL((void*)0);
2614}
2615
2616struct save_dir {
2617 char *dir;
2618 struct save_dir *next;
2619};
2620
2621struct save_dir *prune_candidates;
2622
2623static void
2624add_prune_candidate (dir)
2625 char *dir;
2626{
2627 struct save_dir *p;
2628
2629 if ((dir[0] == '.' && dir[1] == '\0')
2630 || (prune_candidates != NULL((void*)0)
2631 && strcmp (dir, prune_candidates->dir) == 0))
2632 return;
2633 p = (struct save_dir *) xmalloc (sizeof (struct save_dir));
2634 p->dir = xstrdup (dir);
2635 p->next = prune_candidates;
2636 prune_candidates = p;
2637}
2638
2639static void process_prune_candidates PROTO((void))(void);
2640
2641static void
2642process_prune_candidates ()
2643{
2644 struct save_dir *p;
2645 struct save_dir *q;
2646
2647 if (toplevel_wd != NULL((void*)0))
2648 {
2649 if (CVS_CHDIRchdir (toplevel_wd) < 0)
2650 error (1, errno(*__errno()), "could not chdir to %s", toplevel_wd);
2651 }
2652 for (p = prune_candidates; p != NULL((void*)0); )
2653 {
2654 if (isemptydir (p->dir, 1))
2655 {
2656 char *b;
2657
2658 if (unlink_file_dir (p->dir) < 0)
2659 error (0, errno(*__errno()), "cannot remove %s", p->dir);
2660 b = strrchr (p->dir, '/');
2661 if (b == NULL((void*)0))
2662 Subdir_Deregister ((List *) NULL((void*)0), (char *) NULL((void*)0), p->dir);
2663 else
2664 {
2665 *b = '\0';
2666 Subdir_Deregister ((List *) NULL((void*)0), p->dir, b + 1);
2667 }
2668 }
2669 free (p->dir);
2670 q = p->next;
2671 free (p);
2672 p = q;
2673 }
2674 prune_candidates = NULL((void*)0);
2675}
2676
2677/* Send a Repository line. */
2678
2679static char *last_repos;
2680static char *last_update_dir;
2681
2682static void send_repository PROTO((char *, char *, char *))(char *, char *, char *);
2683
2684static void
2685send_repository (dir, repos, update_dir)
2686 char *dir;
2687 char *repos;
2688 char *update_dir;
2689{
2690 char *adm_name;
2691
2692 /* FIXME: this is probably not the best place to check; I wish I
2693 * knew where in here's callers to really trap this bug. To
2694 * reproduce the bug, just do this:
2695 *
2696 * mkdir junk
2697 * cd junk
2698 * cvs -d some_repos update foo
2699 *
2700 * Poof, CVS seg faults and dies! It's because it's trying to
2701 * send a NULL string to the server but dies in send_to_server.
2702 * That string was supposed to be the repository, but it doesn't
2703 * get set because there's no CVSADM dir, and somehow it's not
2704 * getting set from the -d argument either... ?
2705 */
2706 if (repos == NULL((void*)0))
2707 {
2708 /* Lame error. I want a real fix but can't stay up to track
2709 this down right now. */
2710 error (1, 0, "no repository");
2711 }
2712
2713 if (update_dir == NULL((void*)0) || update_dir[0] == '\0')
2714 update_dir = ".";
2715
2716 if (last_repos != NULL((void*)0)
2717 && strcmp (repos, last_repos) == 0
2718 && last_update_dir != NULL((void*)0)
2719 && strcmp (update_dir, last_update_dir) == 0)
2720 /* We've already sent it. */
2721 return;
2722
2723 if (client_prune_dirs)
2724 add_prune_candidate (update_dir);
2725
2726 /* Add a directory name to the list of those sent to the
2727 server. */
2728 if (update_dir && (*update_dir != '\0')
2729 && (strcmp (update_dir, ".") != 0)
2730 && (findnode (dirs_sent_to_server, update_dir) == NULL((void*)0)))
2731 {
2732 Node *n;
2733 n = getnode ();
2734 n->type = NT_UNKNOWN;
2735 n->key = xstrdup (update_dir);
2736 n->data = NULL((void*)0);
2737
2738 if (addnode (dirs_sent_to_server, n))
2739 error (1, 0, "cannot add directory %s to list", n->key);
2740 }
2741
2742 /* 80 is large enough for any of CVSADM_*. */
2743 adm_name = xmalloc (strlen (dir) + 80);
2744
2745 send_to_server ("Directory ", 0);
2746 {
2747 /* Send the directory name. I know that this
2748 sort of duplicates code elsewhere, but each
2749 case seems slightly different... */
2750 char buf[1];
2751 char *p = update_dir;
2752 while (*p != '\0')
2753 {
2754 assert (*p != '\012')((*p != '\012') ? (void)0 : __assert2("/usr/src/gnu/usr.bin/cvs/src/client.c"
, 2754, __func__, "*p != '\\012'"))
;
2755 if (ISDIRSEP (*p)((*p) == '/'))
2756 {
2757 buf[0] = '/';
2758 send_to_server (buf, 1);
2759 }
2760 else
2761 {
2762 buf[0] = *p;
2763 send_to_server (buf, 1);
2764 }
2765 ++p;
2766 }
2767 }
2768 send_to_server ("\012", 1);
2769 send_to_server (repos, 0);
2770 send_to_server ("\012", 1);
2771
2772 if (supported_request ("Static-directory"))
2773 {
2774 adm_name[0] = '\0';
2775 if (dir[0] != '\0')
2776 {
2777 strcat (adm_name, dir);
2778 strcat (adm_name, "/");
2779 }
2780 strcat (adm_name, CVSADM_ENTSTAT"CVS/Entries.Static");
2781 if (isreadable (adm_name))
2782 {
2783 send_to_server ("Static-directory\012", 0);
2784 }
2785 }
2786 if (supported_request ("Sticky"))
2787 {
2788 FILE *f;
2789 if (dir[0] == '\0')
2790 strcpy (adm_name, CVSADM_TAG"CVS/Tag");
2791 else
2792 sprintf (adm_name, "%s/%s", dir, CVSADM_TAG"CVS/Tag");
2793
2794 f = CVS_FOPENfopen (adm_name, "r");
2795 if (f == NULL((void*)0))
2796 {
2797 if (! existence_error (errno)(((*__errno())) == 2))
2798 error (1, errno(*__errno()), "reading %s", adm_name);
2799 }
2800 else
2801 {
2802 char line[80];
2803 char *nl = NULL((void*)0);
2804 send_to_server ("Sticky ", 0);
2805 while (fgets (line, sizeof (line), f) != NULL((void*)0))
2806 {
2807 send_to_server (line, 0);
2808 nl = strchr (line, '\n');
2809 if (nl != NULL((void*)0))
2810 break;
2811 }
2812 if (nl == NULL((void*)0))
2813 send_to_server ("\012", 1);
2814 if (fclose (f) == EOF(-1))
2815 error (0, errno(*__errno()), "closing %s", adm_name);
2816 }
2817 }
2818 if (supported_request ("Checkin-prog"))
2819 {
2820 FILE *f;
2821 if (dir[0] == '\0')
2822 strcpy (adm_name, CVSADM_CIPROG"CVS/Checkin.prog");
2823 else
2824 sprintf (adm_name, "%s/%s", dir, CVSADM_CIPROG"CVS/Checkin.prog");
2825
2826 f = CVS_FOPENfopen (adm_name, "r");
2827 if (f == NULL((void*)0))
2828 {
2829 if (! existence_error (errno)(((*__errno())) == 2))
2830 error (1, errno(*__errno()), "reading %s", adm_name);
2831 }
2832 else
2833 {
2834 char line[80];
2835 char *nl = NULL((void*)0);
2836
2837 send_to_server ("Checkin-prog ", 0);
2838
2839 while (fgets (line, sizeof (line), f) != NULL((void*)0))
2840 {
2841 send_to_server (line, 0);
2842
2843 nl = strchr (line, '\n');
2844 if (nl != NULL((void*)0))
2845 break;
2846 }
2847 if (nl == NULL((void*)0))
2848 send_to_server ("\012", 1);
2849 if (fclose (f) == EOF(-1))
2850 error (0, errno(*__errno()), "closing %s", adm_name);
2851 }
2852 }
2853 if (supported_request ("Update-prog"))
2854 {
2855 FILE *f;
2856 if (dir[0] == '\0')
2857 strcpy (adm_name, CVSADM_UPROG"CVS/Update.prog");
2858 else
2859 sprintf (adm_name, "%s/%s", dir, CVSADM_UPROG"CVS/Update.prog");
2860
2861 f = CVS_FOPENfopen (adm_name, "r");
2862 if (f == NULL((void*)0))
2863 {
2864 if (! existence_error (errno)(((*__errno())) == 2))
2865 error (1, errno(*__errno()), "reading %s", adm_name);
2866 }
2867 else
2868 {
2869 char line[80];
2870 char *nl = NULL((void*)0);
2871
2872 send_to_server ("Update-prog ", 0);
2873
2874 while (fgets (line, sizeof (line), f) != NULL((void*)0))
2875 {
2876 send_to_server (line, 0);
2877
2878 nl = strchr (line, '\n');
2879 if (nl != NULL((void*)0))
2880 break;
2881 }
2882 if (nl == NULL((void*)0))
2883 send_to_server ("\012", 1);
2884 if (fclose (f) == EOF(-1))
2885 error (0, errno(*__errno()), "closing %s", adm_name);
2886 }
2887 }
2888 free (adm_name);
2889 if (last_repos != NULL((void*)0))
2890 free (last_repos);
2891 if (last_update_dir != NULL((void*)0))
2892 free (last_update_dir);
2893 last_repos = xstrdup (repos);
2894 last_update_dir = xstrdup (update_dir);
2895}
2896
2897/* Send a Repository line and set toplevel_repos. */
2898
2899void
2900send_a_repository (dir, repository, update_dir)
2901 char *dir;
2902 char *repository;
2903 char *update_dir;
2904{
2905 if (toplevel_repos == NULL((void*)0) && repository != NULL((void*)0))
2906 {
2907 if (update_dir[0] == '\0'
2908 || (update_dir[0] == '.' && update_dir[1] == '\0'))
2909 toplevel_repos = xstrdup (repository);
2910 else
2911 {
2912 /*
2913 * Get the repository from a CVS/Repository file if update_dir
2914 * is absolute. This is not correct in general, because
2915 * the CVS/Repository file might not be the top-level one.
2916 * This is for cases like "cvs update /foo/bar" (I'm not
2917 * sure it matters what toplevel_repos we get, but it does
2918 * matter that we don't hit the "internal error" code below).
2919 */
2920 if (update_dir[0] == '/')
2921 toplevel_repos = Name_Repository (update_dir, update_dir);
2922 else
2923 {
2924 /*
2925 * Guess the repository of that directory by looking at a
2926 * subdirectory and removing as many pathname components
2927 * as are in update_dir. I think that will always (or at
2928 * least almost always) be 1.
2929 *
2930 * So this deals with directories which have been
2931 * renamed, though it doesn't necessarily deal with
2932 * directories which have been put inside other
2933 * directories (and cvs invoked on the containing
2934 * directory). I'm not sure the latter case needs to
2935 * work.
2936 *
2937 * 21 Aug 1998: Well, Mr. Above-Comment-Writer, it
2938 * does need to work after all. When we are using the
2939 * client in a multi-cvsroot environment, it will be
2940 * fairly common that we have the above case (e.g.,
2941 * cwd checked out from one repository but
2942 * subdirectory checked out from another). We can't
2943 * assume that by walking up a directory in our wd we
2944 * necessarily walk up a directory in the repository.
2945 */
2946 /*
2947 * This gets toplevel_repos wrong for "cvs update ../foo"
2948 * but I'm not sure toplevel_repos matters in that case.
2949 */
2950
2951 int repository_len, update_dir_len;
2952
2953 strip_trailing_slashes (update_dir);
2954
2955 repository_len = strlen (repository);
2956 update_dir_len = strlen (update_dir);
2957
2958 /* Try to remove the path components in UPDATE_DIR
2959 from REPOSITORY. If the path elements don't exist
2960 in REPOSITORY, or the removal of those path
2961 elements mean that we "step above"
2962 current_parsed_root->directory, set toplevel_repos to
2963 current_parsed_root->directory. */
2964 if ((repository_len > update_dir_len)
2965 && (strcmp (repository + repository_len - update_dir_len,
2966 update_dir) == 0)
2967 /* TOPLEVEL_REPOS shouldn't be above current_parsed_root->directory */
2968 && ((repository_len - update_dir_len)
2969 > strlen (current_parsed_root->directory)))
2970 {
2971 /* The repository name contains UPDATE_DIR. Set
2972 toplevel_repos to the repository name without
2973 UPDATE_DIR. */
2974
2975 toplevel_repos = xmalloc (repository_len - update_dir_len);
2976 /* Note that we don't copy the trailing '/'. */
2977 strncpy (toplevel_repos, repository,
2978 repository_len - update_dir_len - 1);
2979 toplevel_repos[repository_len - update_dir_len - 1] = '\0';
2980 }
2981 else
2982 {
2983 toplevel_repos = xstrdup (current_parsed_root->directory);
2984 }
2985 }
2986 }
2987 }
2988
2989 send_repository (dir, repository, update_dir);
2990}
2991
2992/* The "expanded" modules. */
2993static int modules_count;
2994static int modules_allocated;
2995static char **modules_vector;
2996
2997static void
2998handle_module_expansion (args, len)
2999 char *args;
3000 int len;
3001{
3002 if (modules_vector == NULL((void*)0))
3003 {
3004 modules_allocated = 1; /* Small for testing */
3005 modules_vector = (char **) xmalloc
3006 (modules_allocated * sizeof (modules_vector[0]));
3007 }
3008 else if (modules_count >= modules_allocated)
3009 {
3010 modules_allocated *= 2;
3011 modules_vector = (char **) xrealloc
3012 ((char *) modules_vector,
3013 modules_allocated * sizeof (modules_vector[0]));
3014 }
3015 modules_vector[modules_count] = xmalloc (strlen (args) + 1);
3016 strcpy (modules_vector[modules_count], args);
3017 ++modules_count;
3018}
3019
3020/* Original, not "expanded" modules. */
3021static int module_argc;
3022static char **module_argv;
3023
3024void
3025client_expand_modules (argc, argv, local)
3026 int argc;
3027 char **argv;
3028 int local;
3029{
3030 int errs;
3031 int i;
3032
3033 module_argc = argc;
3034 module_argv = (char **) xmalloc ((argc + 1) * sizeof (module_argv[0]));
3035 for (i = 0; i < argc; ++i)
3036 module_argv[i] = xstrdup (argv[i]);
3037 module_argv[argc] = NULL((void*)0);
3038
3039 for (i = 0; i < argc; ++i)
3040 send_arg (argv[i]);
3041 send_a_repository ("", current_parsed_root->directory, "");
3042
3043 send_to_server ("expand-modules\012", 0);
3044
3045 errs = get_server_responses ();
3046 if (last_repos != NULL((void*)0))
3047 free (last_repos);
3048 last_repos = NULL((void*)0);
3049 if (last_update_dir != NULL((void*)0))
3050 free (last_update_dir);
3051 last_update_dir = NULL((void*)0);
3052 if (errs)
3053 error (errs, 0, "cannot expand modules");
3054}
3055
3056void
3057client_send_expansions (local, where, build_dirs)
3058 int local;
3059 char *where;
3060 int build_dirs;
3061{
3062 int i;
3063 char *argv[1];
3064
3065 /* Send the original module names. The "expanded" module name might
3066 not be suitable as an argument to a co request (e.g. it might be
3067 the result of a -d argument in the modules file). It might be
3068 cleaner if we genuinely expanded module names, all the way to a
3069 local directory and repository, but that isn't the way it works
3070 now. */
3071 send_file_names (module_argc, module_argv, 0);
3072
3073 for (i = 0; i < modules_count; ++i)
3074 {
3075 argv[0] = where ? where : modules_vector[i];
3076 if (isfile (argv[0]))
3077 send_files (1, argv, local, 0, build_dirs ? SEND_BUILD_DIRS1 : 0);
3078 }
3079 send_a_repository ("", current_parsed_root->directory, "");
3080}
3081
3082void
3083client_nonexpanded_setup ()
3084{
3085 send_a_repository ("", current_parsed_root->directory, "");
3086}
3087
3088/* Receive a cvswrappers line from the server; it must be a line
3089 containing an RCS option (e.g., "*.exe -k 'b'").
3090
3091 Note that this doesn't try to handle -t/-f options (which are a
3092 whole separate issue which noone has thought much about, as far
3093 as I know).
3094
3095 We need to know the keyword expansion mode so we know whether to
3096 read the file in text or binary mode. */
3097
3098static void
3099handle_wrapper_rcs_option (args, len)
3100 char *args;
3101 int len;
3102{
3103 char *p;
3104
3105 /* Enforce the notes in cvsclient.texi about how the response is not
3106 as free-form as it looks. */
3107 p = strchr (args, ' ');
3108 if (p == NULL((void*)0))
3109 goto handle_error;
3110 if (*++p != '-'
3111 || *++p != 'k'
3112 || *++p != ' '
3113 || *++p != '\'')
3114 goto handle_error;
3115 if (strchr (p, '\'') == NULL((void*)0))
3116 goto handle_error;
3117
3118 /* Add server-side cvswrappers line to our wrapper list. */
3119 wrap_add (args, 0);
3120 return;
3121 handle_error:
3122 error (0, errno(*__errno()), "protocol error: ignoring invalid wrappers %s", args);
3123}
3124
3125
3126static void
3127handle_m (args, len)
3128 char *args;
3129 int len;
3130{
3131 /* In the case where stdout and stderr point to the same place,
3132 fflushing stderr will make output happen in the correct order.
3133 Often stderr will be line-buffered and this won't be needed,
3134 but not always (is that true? I think the comment is probably
3135 based on being confused between default buffering between
3136 stdout and stderr. But I'm not sure). */
3137 fflush (stderr(&__sF[2]));
3138 fwrite (args, len, sizeof (*args), stdout(&__sF[1]));
3139 putc ('\n', stdout)(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
3140}
3141
3142static void handle_mbinary PROTO ((char *, int))(char *, int);
3143
3144static void
3145handle_mbinary (args, len)
3146 char *args;
3147 int len;
3148{
3149 char *size_string;
3150 size_t size;
3151 size_t totalread;
3152 size_t nread;
3153 size_t toread;
3154 char buf[8192];
3155
3156 /* See comment at handle_m about (non)flush of stderr. */
3157
3158 /* Get the size. */
3159 read_line (&size_string);
3160 size = atoi (size_string);
3161 free (size_string);
3162
3163 /* OK, now get all the data. The algorithm here is that we read
3164 as much as the network wants to give us in
3165 try_read_from_server, and then we output it all, and then
3166 repeat, until we get all the data. */
3167 totalread = 0;
3168 while (totalread < size)
3169 {
3170 toread = size - totalread;
3171 if (toread > sizeof buf)
3172 toread = sizeof buf;
3173
3174 nread = try_read_from_server (buf, toread);
3175 cvs_output_binary (buf, nread);
3176 totalread += nread;
3177 }
3178}
3179
3180static void
3181handle_e (args, len)
3182 char *args;
3183 int len;
3184{
3185 /* In the case where stdout and stderr point to the same place,
3186 fflushing stdout will make output happen in the correct order. */
3187 fflush (stdout(&__sF[1]));
3188 fwrite (args, len, sizeof (*args), stderr(&__sF[2]));
3189 putc ('\n', stderr)(!__isthreaded ? __sputc('\n', (&__sF[2])) : (putc)('\n',
(&__sF[2])))
;
3190}
3191
3192/*ARGSUSED*/
3193static void
3194handle_f (args, len)
3195 char *args;
3196 int len;
3197{
3198 fflush (stderr(&__sF[2]));
3199}
3200
3201static void handle_mt PROTO ((char *, int))(char *, int);
3202
3203static void
3204handle_mt (args, len)
3205 char *args;
3206 int len;
3207{
3208 char *p;
3209 char *tag = args;
3210 char *text;
3211
3212 /* See comment at handle_m for more details. */
3213 fflush (stderr(&__sF[2]));
3214
3215 p = strchr (args, ' ');
3216 if (p == NULL((void*)0))
3217 text = NULL((void*)0);
3218 else
3219 {
3220 *p++ = '\0';
3221 text = p;
3222 }
3223
3224 switch (tag[0])
3225 {
3226 case '+':
3227 if (strcmp (tag, "+updated") == 0)
3228 updated_seen = 1;
3229 else if (strcmp (tag, "+importmergecmd") == 0)
3230 importmergecmd.seen = 1;
3231 break;
3232 case '-':
3233 if (strcmp (tag, "-updated") == 0)
3234 updated_seen = 0;
3235 else if (strcmp (tag, "-importmergecmd") == 0)
3236 {
3237 char buf[80];
3238
3239 /* Now that we have gathered the information, we can
3240 output the suggested merge command. */
3241
3242 if (importmergecmd.conflicts == 0
3243 || importmergecmd.mergetag1 == NULL((void*)0)
3244 || importmergecmd.mergetag2 == NULL((void*)0)
3245 || importmergecmd.repository == NULL((void*)0))
3246 {
3247 error (0, 0,
3248 "invalid server: incomplete importmergecmd tags");
3249 break;
3250 }
3251
3252 sprintf (buf, "\n%d conflicts created by this import.\n",
3253 importmergecmd.conflicts);
3254 cvs_output (buf, 0);
3255 cvs_output ("Use the following command to help the merge:\n\n",
3256 0);
3257 cvs_output ("\t", 1);
3258 cvs_output (program_name, 0);
3259 if (CVSroot_cmdline != NULL((void*)0))
3260 {
3261 cvs_output (" -d ", 0);
3262 cvs_output (CVSroot_cmdline, 0);
3263 }
3264 cvs_output (" checkout -j", 0);
3265 cvs_output (importmergecmd.mergetag1, 0);
3266 cvs_output (" -j", 0);
3267 cvs_output (importmergecmd.mergetag2, 0);
3268 cvs_output (" ", 1);
3269 cvs_output (importmergecmd.repository, 0);
3270 cvs_output ("\n\n", 0);
3271
3272 /* Clear the static variables so that everything is
3273 ready for any subsequent importmergecmd tag. */
3274 importmergecmd.conflicts = 0;
3275 free (importmergecmd.mergetag1);
3276 importmergecmd.mergetag1 = NULL((void*)0);
3277 free (importmergecmd.mergetag2);
3278 importmergecmd.mergetag2 = NULL((void*)0);
3279 free (importmergecmd.repository);
3280 importmergecmd.repository = NULL((void*)0);
3281
3282 importmergecmd.seen = 0;
3283 }
3284 break;
3285 default:
3286 if (updated_seen)
3287 {
3288 if (strcmp (tag, "fname") == 0)
3289 {
3290 if (updated_fname != NULL((void*)0))
3291 {
3292 /* Output the previous message now. This can happen
3293 if there was no Update-existing or other such
3294 response, due to the -n global option. */
3295 cvs_output ("U ", 0);
3296 cvs_output (updated_fname, 0);
3297 cvs_output ("\n", 1);
3298 free (updated_fname);
3299 }
3300 updated_fname = xstrdup (text);
3301 }
3302 /* Swallow all other tags. Either they are extraneous
3303 or they reflect future extensions that we can
3304 safely ignore. */
3305 }
3306 else if (importmergecmd.seen)
3307 {
3308 if (strcmp (tag, "conflicts") == 0)
3309 importmergecmd.conflicts = atoi (text);
3310 else if (strcmp (tag, "mergetag1") == 0)
3311 importmergecmd.mergetag1 = xstrdup (text);
3312 else if (strcmp (tag, "mergetag2") == 0)
3313 importmergecmd.mergetag2 = xstrdup (text);
3314 else if (strcmp (tag, "repository") == 0)
3315 importmergecmd.repository = xstrdup (text);
3316 /* Swallow all other tags. Either they are text for
3317 which we are going to print our own version when we
3318 see -importmergecmd, or they are future extensions
3319 we can safely ignore. */
3320 }
3321 else if (strcmp (tag, "newline") == 0)
3322 printf ("\n");
3323 else if (text != NULL((void*)0))
3324 printf ("%s", text);
3325 }
3326}
3327
3328#endif /* CLIENT_SUPPORT */
3329#if defined(CLIENT_SUPPORT1) || defined(SERVER_SUPPORT1)
3330
3331/* This table must be writeable if the server code is included. */
3332struct response responses[] =
3333{
3334#ifdef CLIENT_SUPPORT1
3335#define RSP_LINE(n, f, t, s) {n, f, t, s}
3336#else /* ! CLIENT_SUPPORT */
3337#define RSP_LINE(n, f, t, s) {n, s}
3338#endif /* CLIENT_SUPPORT */
3339
3340 RSP_LINE("ok", handle_ok, response_type_ok, rs_essential),
3341 RSP_LINE("error", handle_error, response_type_error, rs_essential),
3342 RSP_LINE("Valid-requests", handle_valid_requests, response_type_normal,
3343 rs_essential),
3344 RSP_LINE("Checked-in", handle_checked_in, response_type_normal,
3345 rs_essential),
3346 RSP_LINE("New-entry", handle_new_entry, response_type_normal, rs_optional),
3347 RSP_LINE("Checksum", handle_checksum, response_type_normal, rs_optional),
3348 RSP_LINE("Copy-file", handle_copy_file, response_type_normal, rs_optional),
3349 RSP_LINE("Updated", handle_updated, response_type_normal, rs_essential),
3350 RSP_LINE("Created", handle_created, response_type_normal, rs_optional),
3351 RSP_LINE("Update-existing", handle_update_existing, response_type_normal,
3352 rs_optional),
3353 RSP_LINE("Merged", handle_merged, response_type_normal, rs_essential),
3354 RSP_LINE("Patched", handle_patched, response_type_normal, rs_optional),
3355 RSP_LINE("Rcs-diff", handle_rcs_diff, response_type_normal, rs_optional),
3356 RSP_LINE("Mode", handle_mode, response_type_normal, rs_optional),
3357 RSP_LINE("Mod-time", handle_mod_time, response_type_normal, rs_optional),
3358 RSP_LINE("Removed", handle_removed, response_type_normal, rs_essential),
3359 RSP_LINE("Remove-entry", handle_remove_entry, response_type_normal,
3360 rs_optional),
3361 RSP_LINE("Set-static-directory", handle_set_static_directory,
3362 response_type_normal,
3363 rs_optional),
3364 RSP_LINE("Clear-static-directory", handle_clear_static_directory,
3365 response_type_normal,
3366 rs_optional),
3367 RSP_LINE("Set-sticky", handle_set_sticky, response_type_normal,
3368 rs_optional),
3369 RSP_LINE("Clear-sticky", handle_clear_sticky, response_type_normal,
3370 rs_optional),
3371 RSP_LINE("Template", handle_template, response_type_normal,
3372 rs_optional),
3373 RSP_LINE("Set-checkin-prog", handle_set_checkin_prog, response_type_normal,
3374 rs_optional),
3375 RSP_LINE("Set-update-prog", handle_set_update_prog, response_type_normal,
3376 rs_optional),
3377 RSP_LINE("Notified", handle_notified, response_type_normal, rs_optional),
3378 RSP_LINE("Module-expansion", handle_module_expansion, response_type_normal,
3379 rs_optional),
3380 RSP_LINE("Wrapper-rcsOption", handle_wrapper_rcs_option,
3381 response_type_normal,
3382 rs_optional),
3383 RSP_LINE("M", handle_m, response_type_normal, rs_essential),
3384 RSP_LINE("Mbinary", handle_mbinary, response_type_normal, rs_optional),
3385 RSP_LINE("E", handle_e, response_type_normal, rs_essential),
3386 RSP_LINE("F", handle_f, response_type_normal, rs_optional),
3387 RSP_LINE("MT", handle_mt, response_type_normal, rs_optional),
3388 /* Possibly should be response_type_error. */
3389 RSP_LINE(NULL((void*)0), NULL((void*)0), response_type_normal, rs_essential)
3390
3391#undef RSP_LINE
3392};
3393
3394#endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
3395#ifdef CLIENT_SUPPORT1
3396
3397/*
3398 * If LEN is 0, then send_to_server() computes string's length itself.
3399 *
3400 * Therefore, pass the real length when transmitting data that might
3401 * contain 0's.
3402 */
3403void
3404send_to_server (str, len)
3405 char *str;
3406 size_t len;
3407{
3408 static int nbytes;
3409
3410 if (len == 0)
3411 len = strlen (str);
3412
3413 buf_output (to_server, str, len);
3414
3415 /* There is no reason not to send data to the server, so do it
3416 whenever we've accumulated enough information in the buffer to
3417 make it worth sending. */
3418 nbytes += len;
3419 if (nbytes >= 2 * BUFFER_DATA_SIZE(4096))
3420 {
3421 int status;
3422
3423 status = buf_send_output (to_server);
3424 if (status != 0)
3425 error (1, status, "error writing to server");
3426 nbytes = 0;
3427 }
3428}
3429
3430/* Read up to LEN bytes from the server. Returns actual number of
3431 bytes read, which will always be at least one; blocks if there is
3432 no data available at all. Gives a fatal error on EOF or error. */
3433static size_t
3434try_read_from_server (buf, len)
3435 char *buf;
3436 size_t len;
3437{
3438 int status, nread;
3439 char *data;
3440
3441 status = buf_read_data (from_server, len, &data, &nread);
3442 if (status != 0)
3443 {
3444 if (status == -1)
3445 error (1, 0,
3446 "end of file from server (consult above messages if any)");
3447 else if (status == -2)
3448 error (1, 0, "out of memory");
3449 else
3450 error (1, status, "reading from server");
3451 }
3452
3453 memcpy (buf, data, nread);
3454
3455 return nread;
3456}
3457
3458/*
3459 * Read LEN bytes from the server or die trying.
3460 */
3461void
3462read_from_server (buf, len)
3463 char *buf;
3464 size_t len;
3465{
3466 size_t red = 0;
3467 while (red < len)
3468 {
3469 red += try_read_from_server (buf + red, len - red);
3470 if (red == len)
3471 break;
3472 }
3473}
3474
3475/*
3476 * Get some server responses and process them. Returns nonzero for
3477 * error, 0 for success. */
3478int
3479get_server_responses ()
3480{
3481 struct response *rs;
3482 do
3483 {
3484 char *cmd;
3485 int len;
3486
3487 len = read_line (&cmd);
3488 for (rs = responses; rs->name != NULL((void*)0); ++rs)
3489 if (strncmp (cmd, rs->name, strlen (rs->name)) == 0)
3490 {
3491 int cmdlen = strlen (rs->name);
3492 if (cmd[cmdlen] == '\0')
3493 ;
3494 else if (cmd[cmdlen] == ' ')
3495 ++cmdlen;
3496 else
3497 /*
3498 * The first len characters match, but it's a different
3499 * response. e.g. the response is "oklahoma" but we
3500 * matched "ok".
3501 */
3502 continue;
3503 (*rs->func) (cmd + cmdlen, len - cmdlen);
3504 break;
3505 }
3506 if (rs->name == NULL((void*)0))
3507 /* It's OK to print just to the first '\0'. */
3508 /* We might want to handle control characters and the like
3509 in some other way other than just sending them to stdout.
3510 One common reason for this error is if people use :ext:
3511 with a version of rsh which is doing CRLF translation or
3512 something, and so the client gets "ok^M" instead of "ok".
3513 Right now that will tend to print part of this error
3514 message over the other part of it. It seems like we could
3515 do better (either in general, by quoting or omitting all
3516 control characters, and/or specifically, by detecting the CRLF
3517 case and printing a specific error message). */
3518 error (0, 0,
3519 "warning: unrecognized response `%s' from cvs server",
3520 cmd);
3521 free (cmd);
3522 } while (rs->type == response_type_normal);
3523
3524 if (updated_fname != NULL((void*)0))
3525 {
3526 /* Output the previous message now. This can happen
3527 if there was no Update-existing or other such
3528 response, due to the -n global option. */
3529 cvs_output ("U ", 0);
3530 cvs_output (updated_fname, 0);
3531 cvs_output ("\n", 1);
3532 free (updated_fname);
3533 updated_fname = NULL((void*)0);
3534 }
3535
3536 if (rs->type == response_type_error)
3537 return 1;
3538 if (failure_exit)
3539 return 1;
3540 return 0;
3541}
3542
3543/* Get the responses and then close the connection. */
3544int server_fd = -1;
3545
3546/*
3547 * Flag var; we'll set it in start_server() and not one of its
3548 * callees, such as start_rsh_server(). This means that there might
3549 * be a small window between the starting of the server and the
3550 * setting of this var, but all the code in that window shouldn't care
3551 * because it's busy checking return values to see if the server got
3552 * started successfully anyway.
3553 */
3554int server_started = 0;
3555
3556int
3557get_responses_and_close ()
3558{
3559 int errs = get_server_responses ();
3560 int status;
3561
3562 if (last_entries != NULL((void*)0))
3563 {
3564 Entries_Close (last_entries);
3565 last_entries = NULL((void*)0);
3566 }
3567
3568 do_deferred_progs ();
3569
3570 if (client_prune_dirs)
3571 process_prune_candidates ();
3572
3573 /* The calls to buf_shutdown are currently only meaningful when we
3574 are using compression. First we shut down TO_SERVER. That
3575 tells the server that its input is finished. It then shuts
3576 down the buffer it is sending to us, at which point our shut
3577 down of FROM_SERVER will complete. */
3578
3579 status = buf_shutdown (to_server);
3580 if (status != 0)
3581 error (0, status, "shutting down buffer to server");
3582 status = buf_shutdown (from_server);
3583 if (status != 0)
3584 error (0, status, "shutting down buffer from server");
3585
3586#ifdef NO_SOCKET_TO_FD
3587 if (use_socket_style)
3588 {
3589 if (shutdown (server_sock, 2) < 0)
3590 error (1, 0, "shutting down server socket: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
3591 }
3592 else
3593#endif /* NO_SOCKET_TO_FD */
3594 {
3595#if defined(HAVE_KERBEROS) || defined(AUTH_CLIENT_SUPPORT1)
3596 if (server_fd != -1)
3597 {
3598 if (shutdown (server_fd, 1) < 0)
3599 error (1, 0, "shutting down connection to %s: %s",
3600 current_parsed_root->hostname, SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
3601 server_fd = -1;
3602 /*
3603 * This test will always be true because we dup the descriptor
3604 */
3605 if (fileno (from_server_fp)(!__isthreaded ? ((from_server_fp)->_file) : (fileno)(from_server_fp
))
!= fileno (to_server_fp)(!__isthreaded ? ((to_server_fp)->_file) : (fileno)(to_server_fp
))
)
3606 {
3607 if (fclose (to_server_fp) != 0)
3608 error (1, errno(*__errno()),
3609 "closing down connection to %s",
3610 current_parsed_root->hostname);
3611 }
3612 }
3613 else
3614#endif
3615
3616#ifdef SHUTDOWN_SERVER
3617 SHUTDOWN_SERVER (fileno (to_server_fp)(!__isthreaded ? ((to_server_fp)->_file) : (fileno)(to_server_fp
))
);
3618#else /* ! SHUTDOWN_SERVER */
3619 {
3620
3621#ifdef START_RSH_WITH_POPEN_RW
3622 if (pclose (to_server_fp) == EOF(-1))
3623#else /* ! START_RSH_WITH_POPEN_RW */
3624 if (fclose (to_server_fp) == EOF(-1))
3625#endif /* START_RSH_WITH_POPEN_RW */
3626 {
3627 error (1, errno(*__errno()), "closing connection to %s",
3628 current_parsed_root->hostname);
3629 }
3630 }
3631
3632 if (! buf_empty_p (from_server)
3633 || getc (from_server_fp)(!__isthreaded ? (--(from_server_fp)->_r < 0 ? __srget(
from_server_fp) : (int)(*(from_server_fp)->_p++)) : (getc)
(from_server_fp))
!= EOF(-1))
3634 error (0, 0, "dying gasps from %s unexpected", current_parsed_root->hostname);
3635 else if (ferror (from_server_fp)(!__isthreaded ? (((from_server_fp)->_flags & 0x0040) !=
0) : (ferror)(from_server_fp))
)
3636 error (0, errno(*__errno()), "reading from %s", current_parsed_root->hostname);
3637
3638 fclose (from_server_fp);
3639#endif /* SHUTDOWN_SERVER */
3640 }
3641
3642 if (rsh_pid != -1
3643 && waitpid (rsh_pid, (int *) 0, 0) == -1)
3644 error (1, errno(*__errno()), "waiting for process %d", rsh_pid);
3645
3646 buf_free (to_server);
3647 buf_free (from_server);
3648 server_started = 0;
3649
3650 /* see if we need to sleep before returning to avoid time-stamp races */
3651 if (last_register_time)
3652 {
3653 sleep_past (last_register_time);
3654 }
3655
3656 return errs;
3657}
3658
3659#ifndef NO_EXT_METHOD
3660static void start_rsh_server PROTO((int *, int *))(int *, int *);
3661#endif
3662
3663int
3664supported_request (name)
3665 char *name;
3666{
3667 struct request *rq;
3668
3669 for (rq = requests; rq->name; rq++)
3670 if (!strcmp (rq->name, name))
3671 return (rq->flags & RQ_SUPPORTED2) != 0;
3672 error (1, 0, "internal error: testing support for unknown option?");
3673 /* NOTREACHED */
3674 return 0;
3675}
3676
3677
3678
3679#if defined (AUTH_CLIENT_SUPPORT1) || defined (HAVE_KERBEROS)
3680static struct hostent *init_sockaddr PROTO ((struct sockaddr_in *, char *,(struct sockaddr_in *, char *, unsigned int)
3681 unsigned int))(struct sockaddr_in *, char *, unsigned int);
3682
3683static struct hostent *
3684init_sockaddr (name, hostname, port)
3685 struct sockaddr_in *name;
3686 char *hostname;
3687 unsigned int port;
3688{
3689 struct hostent *hostinfo;
3690 unsigned short shortport = port;
3691
3692 memset (name, 0, sizeof (*name));
3693 name->sin_family = AF_INET2;
3694 name->sin_port = htons (shortport)(__uint16_t)(__builtin_constant_p(shortport) ? (__uint16_t)((
(__uint16_t)(shortport) & 0xffU) << 8 | ((__uint16_t
)(shortport) & 0xff00U) >> 8) : __swap16md(shortport
))
;
1
'?' condition is false
3695 hostinfo = gethostbyname (hostname);
2
Value assigned to 'hostinfo'
3696 if (hostinfo == NULL((void*)0))
3
Assuming 'hostinfo' is equal to NULL
4
Taking true branch
3697 {
3698 fprintf (stderr(&__sF[2]), "Unknown host %s.\n", hostname);
3699 error_exit ();
3700 }
3701 name->sin_addr = *(struct in_addr *) hostinfo->h_addrh_addr_list[0];
5
Access to field 'h_addr_list' results in a dereference of a null pointer (loaded from variable 'hostinfo')
3702 return hostinfo;
3703}
3704
3705#endif /* defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_KERBEROS) */
3706
3707
3708
3709#ifdef AUTH_CLIENT_SUPPORT1
3710
3711/* Generic function to do port number lookup tasks.
3712 *
3713 * In order of precedence, will return:
3714 * getenv (envname), if defined
3715 * getservbyname (portname), if defined
3716 * defaultport
3717 */
3718static int
3719get_port_number (envname, portname, defaultport)
3720 const char *envname;
3721 const char *portname;
3722 int defaultport;
3723{
3724 struct servent *s;
3725 char *port_s;
3726
3727 if (envname && (port_s = getenv (envname)))
3728 {
3729 int port = atoi (port_s);
3730 if (port <= 0)
3731 {
3732 error (0, 0, "%s must be a positive integer! If you", envname);
3733 error (0, 0, "are trying to force a connection via ssh, please");
3734 error (0, 0, "put \":server:\" at the beginning of your CVSROOT");
3735 error (1, 0, "variable.");
3736 }
3737 return port;
3738 }
3739 else if (portname && (s = getservbyname (portname, "tcp")))
3740 return ntohs (s->s_port)(__uint16_t)(__builtin_constant_p(s->s_port) ? (__uint16_t
)(((__uint16_t)(s->s_port) & 0xffU) << 8 | ((__uint16_t
)(s->s_port) & 0xff00U) >> 8) : __swap16md(s->
s_port))
;
3741 else
3742 return defaultport;
3743}
3744
3745
3746
3747/* get the port number for a client to connect to based on the port
3748 * and method of a cvsroot_t.
3749 *
3750 * we do this here instead of in parse_cvsroot so that we can keep network
3751 * code confined to a localized area and also to delay the lookup until the
3752 * last possible moment so it remains possible to run cvs client commands that
3753 * skip opening connections to the server (i.e. skip network operations entirely)
3754 *
3755 * and yes, I know none of the the commands do that now, but here's to planning
3756 * for the future, eh? cheers.
3757 *
3758 * FIXME - We could cache the port lookup safely right now as we never change
3759 * it for a single root on the fly, but we'd have to un'const some other
3760 * functions
3761 */
3762int
3763get_cvs_port_number (root)
3764 const cvsroot_t *root;
3765{
3766
3767 if (root->port) return root->port;
3768
3769 switch (root->method)
3770 {
3771 case gserver_method:
3772 case pserver_method:
3773 return get_port_number ("CVS_CLIENT_PORT", "cvspserver", CVS_AUTH_PORT2401);
3774#ifdef HAVE_KERBEROS
3775 case kserver_method:
3776 return get_port_number ("CVS_CLIENT_PORT", "cvs", CVS_PORT);
3777#endif
3778 default:
3779 error(1, EINVAL22, "internal error: get_cvs_port_number called for invalid connection method (%s)",
3780 method_names[root->method]);
3781 break;
3782 }
3783}
3784
3785
3786
3787/* Read a line from socket SOCK. Result does not include the
3788 terminating linefeed. This is only used by the authentication
3789 protocol, which we call before we set up all the buffering stuff.
3790 It is possible it should use the buffers too, which would be faster
3791 (unlike the server, there isn't really a security issue in terms of
3792 separating authentication from the rest of the code).
3793
3794 Space for the result is malloc'd and should be freed by the caller.
3795
3796 Returns number of bytes read. */
3797static int
3798recv_line (sock, resultp)
3799 int sock;
3800 char **resultp;
3801{
3802 char *result;
3803 size_t input_index = 0;
3804 size_t result_size = 80;
3805
3806 result = (char *) xmalloc (result_size);
3807
3808 while (1)
3809 {
3810 char ch;
3811 int n;
3812 n = recv (sock, &ch, 1, 0);
3813 if (n <= 0)
3814 error (1, 0, "recv() from server %s: %s", current_parsed_root->hostname,
3815 n == 0 ? "EOF" : SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
3816
3817 if (ch == '\012')
3818 break;
3819
3820 result[input_index++] = ch;
3821 while (input_index + 1 >= result_size)
3822 {
3823 result_size *= 2;
3824 result = (char *) xrealloc (result, result_size);
3825 }
3826 }
3827
3828 if (resultp)
3829 *resultp = result;
3830
3831 /* Terminate it just for kicks, but we *can* deal with embedded NULs. */
3832 result[input_index] = '\0';
3833
3834 if (resultp == NULL((void*)0))
3835 free (result);
3836 return input_index;
3837}
3838
3839/* Connect to a forked server process. */
3840
3841void
3842connect_to_forked_server (tofdp, fromfdp)
3843 int *tofdp, *fromfdp;
3844{
3845 /* This is pretty simple. All we need to do is choose the correct
3846 cvs binary and call piped_child. */
3847
3848 char *command[3];
3849
3850 command[0] = getenv ("CVS_SERVER");
3851 if (! command[0])
3852 command[0] = program_path;
3853
3854 command[1] = "server";
3855 command[2] = NULL((void*)0);
3856
3857 if (trace)
3858 {
3859 fprintf (stderr(&__sF[2]), " -> Forking server: %s %s\n", command[0], command[1]);
3860 }
3861 if (! piped_child (command, tofdp, fromfdp))
3862 error (1, 0, "could not fork server process");
3863}
3864
3865/* Connect to the authenticating server.
3866
3867 If VERIFY_ONLY is non-zero, then just verify that the password is
3868 correct and then shutdown the connection.
3869
3870 If VERIFY_ONLY is 0, then really connect to the server.
3871
3872 If DO_GSSAPI is non-zero, then we use GSSAPI authentication rather
3873 than the pserver password authentication.
3874
3875 If we fail to connect or if access is denied, then die with fatal
3876 error. */
3877void
3878connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
3879 int *tofdp, *fromfdp;
3880 int verify_only;
3881 int do_gssapi;
3882{
3883 int sock;
3884#ifndef NO_SOCKET_TO_FD
3885 int tofd, fromfd;
3886#endif
3887 int port_number;
3888 char *username; /* the username we use to connect */
3889 struct addrinfo hints, *res, *res0 = NULL((void*)0);
3890 char hbuf[NI_MAXHOST256], sbuf[NI_MAXSERV32];
3891 char no_passwd = 0; /* gets set if no password found */
3892 int e;
3893
3894 memset(&hints, 0, sizeof(hints));
3895 hints.ai_socktype = SOCK_STREAM1;
3896 hints.ai_flags = AI_CANONNAME2;
3897 port_number = get_cvs_port_number (current_parsed_root);
3898 snprintf(sbuf, sizeof(sbuf), "%d", port_number);
3899 e = getaddrinfo(current_parsed_root->hostname, sbuf, &hints, &res0);
3900 if (e)
3901 {
3902 error (1, 0, "%s", gai_strerror(e));
3903 }
3904 sock = -1;
3905 for (res = res0; res; res = res->ai_next)
3906 {
3907 sock = socket (res->ai_family, res->ai_socktype, res->ai_protocol);
3908 if (sock < 0)
3909 {
3910 continue;
3911 }
3912
3913 if (trace)
3914 {
3915 getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
3916 sbuf, sizeof(sbuf), NI_NUMERICHOST1 | NI_NUMERICSERV2);
3917 fprintf (stderr(&__sF[2]), " -> Connecting to %s(%s):%s\n",
3918 current_parsed_root->hostname, hbuf, sbuf);
3919 }
3920 if (connect(sock, res->ai_addr, res->ai_addrlen) < 0)
3921 {
3922 close(sock);
3923 sock = -1;
3924 continue;
3925 }
3926 break;
3927 }
3928 if (sock < 0)
3929 {
3930 getnameinfo(res0->ai_addr, res0->ai_addrlen, hbuf, sizeof(hbuf),
3931 sbuf, sizeof(sbuf), NI_NUMERICHOST1 | NI_NUMERICSERV2);
3932 error (1, 0, "connect to %s(%s):%s failed: %s",
3933 current_parsed_root->hostname, hbuf, sbuf,
3934 SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
3935 }
3936
3937 /* Run the authorization mini-protocol before anything else. */
3938 if (do_gssapi)
3939 {
3940#ifdef HAVE_GSSAPI
3941 if (! connect_to_gserver (sock, res0->ai_canonname ?
3942 res0->ai_canonname : current_parsed_root->hostname))
3943 {
3944 error (0, 0,
3945 "authorization failed: server %s rejected access to %s",
3946 current_parsed_root->hostname, current_parsed_root->directory);
3947 goto rejected;
3948 }
3949#else
3950 error (1, 0, "This client does not support GSSAPI authentication");
3951#endif
3952 }
3953 else
3954 {
3955 char *begin = NULL((void*)0);
3956 char *password = NULL((void*)0);
3957 char *end = NULL((void*)0);
3958
3959 if (verify_only)
3960 {
3961 begin = "BEGIN VERIFICATION REQUEST\012";
3962 end = "END VERIFICATION REQUEST\012";
3963 }
3964 else
3965 {
3966 begin = "BEGIN AUTH REQUEST\012";
3967 end = "END AUTH REQUEST\012";
3968 }
3969
3970 /* Get the password, probably from ~/.cvspass. */
3971 password = get_cvs_password ();
3972 username = current_parsed_root->username ? current_parsed_root->username : getcaller();
3973
3974 /* Send the empty string by default. This is so anonymous CVS
3975 access doesn't require client to have done "cvs login". */
3976 if (password == NULL((void*)0))
3977 {
3978 no_passwd = 1;
3979 password = scramble ("");
3980 }
3981
3982 /* Announce that we're starting the authorization protocol. */
3983 if (send (sock, begin, strlen (begin), 0) < 0)
3984 error (1, 0, "cannot send: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
3985
3986 /* Send the data the server needs. */
3987 if (send (sock, current_parsed_root->directory, strlen (current_parsed_root->directory), 0) < 0)
3988 error (1, 0, "cannot send: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
3989 if (send (sock, "\012", 1, 0) < 0)
3990 error (1, 0, "cannot send: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
3991 if (send (sock, username, strlen (username), 0) < 0)
3992 error (1, 0, "cannot send: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
3993 if (send (sock, "\012", 1, 0) < 0)
3994 error (1, 0, "cannot send: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
3995 if (send (sock, password, strlen (password), 0) < 0)
3996 error (1, 0, "cannot send: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
3997 if (send (sock, "\012", 1, 0) < 0)
3998 error (1, 0, "cannot send: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
3999
4000 /* Announce that we're ending the authorization protocol. */
4001 if (send (sock, end, strlen (end), 0) < 0)
4002 error (1, 0, "cannot send: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
4003
4004 /* Paranoia. */
4005 memset (password, 0, strlen (password));
4006 }
4007
4008 {
4009 char *read_buf;
4010
4011 /* Loop, getting responses from the server. */
4012 while (1)
4013 {
4014 recv_line (sock, &read_buf);
4015
4016 if (strcmp (read_buf, "I HATE YOU") == 0)
4017 {
4018 /* Authorization not granted.
4019 *
4020 * This is a little confusing since we can reach this while loop in GSSAPI
4021 * mode, but if GSSAPI authentication failed, we already jumped to the
4022 * rejected label (there is no case where the connect_to_gserver function
4023 * can return 1 and we will not receive "I LOVE YOU" from the server, barring
4024 * broken connections and garbled messages, of course).
4025 *
4026 * i.e. This is a pserver specific error message and shoiuld be since
4027 * GSSAPI doesn't use username.
4028 */
4029 error (0, 0,
4030 "authorization failed: server %s rejected access to %s for user %s",
4031 current_parsed_root->hostname, current_parsed_root->directory, username);
4032
4033 /* Output a special error message if authentication was attempted
4034 with no password -- the user should be made aware that they may
4035 have missed a step. */
4036 if (no_passwd)
4037 {
4038 error (0, 0,
4039 "used empty password; try \"cvs login\" with a real password");
4040 }
4041 goto rejected;
4042 }
4043 else if (strncmp (read_buf, "E ", 2) == 0)
4044 {
4045 fprintf (stderr(&__sF[2]), "%s\n", read_buf + 2);
4046
4047 /* Continue with the authentication protocol. */
4048 }
4049 else if (strncmp (read_buf, "error ", 6) == 0)
4050 {
4051 char *p;
4052
4053 /* First skip the code. */
4054 p = read_buf + 6;
4055 while (*p != ' ' && *p != '\0')
4056 ++p;
4057
4058 /* Skip the space that follows the code. */
4059 if (*p == ' ')
4060 ++p;
4061
4062 /* Now output the text. */
4063 fprintf (stderr(&__sF[2]), "%s\n", p);
4064 goto rejected;
4065 }
4066 else if (strcmp (read_buf, "I LOVE YOU") == 0)
4067 {
4068 free (read_buf);
4069 break;
4070 }
4071 else
4072 {
4073 /* Unrecognized response from server. */
4074 if (shutdown (sock, 2) < 0)
4075 {
4076 error (0, 0,
4077 "unrecognized auth response from %s: %s",
4078 current_parsed_root->hostname, read_buf);
4079 error (1, 0,
4080 "shutdown() failed, server %s: %s",
4081 current_parsed_root->hostname,
4082 SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
4083 }
4084 error (1, 0,
4085 "unrecognized auth response from %s: %s",
4086 current_parsed_root->hostname, read_buf);
4087 }
4088 free (read_buf);
4089 }
4090 }
4091
4092 if (verify_only)
4093 {
4094 if (shutdown (sock, 2) < 0)
4095 error (0, 0, "shutdown() failed, server %s: %s", current_parsed_root->hostname,
4096 SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
4097 if (res0)
4098 freeaddrinfo(res0);
4099 return;
4100 }
4101 else
4102 {
4103#ifdef NO_SOCKET_TO_FD
4104 use_socket_style = 1;
4105 server_sock = sock;
4106 /* Try to break mistaken callers: */
4107 *tofdp = 0;
4108 *fromfdp = 0;
4109#else /* ! NO_SOCKET_TO_FD */
4110 server_fd = sock;
4111 close_on_exec (server_fd);
4112 tofd = fromfd = sock;
4113 /* Hand them back to the caller. */
4114 *tofdp = tofd;
4115 *fromfdp = fromfd;
4116#endif /* NO_SOCKET_TO_FD */
4117 }
4118
4119 if (res0)
4120 freeaddrinfo(res0);
4121 return;
4122
4123 rejected:
4124 if (shutdown (sock, 2) < 0)
4125 {
4126 error (0, 0,
4127 "shutdown() failed (server %s): %s",
4128 current_parsed_root->hostname,
4129 SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
4130 }
4131
4132 error_exit();
4133}
4134#endif /* AUTH_CLIENT_SUPPORT */
4135
4136
4137
4138#ifdef HAVE_KERBEROS
4139
4140/* This function has not been changed to deal with NO_SOCKET_TO_FD
4141 (i.e., systems on which sockets cannot be converted to file
4142 descriptors). The first person to try building a kerberos client
4143 on such a system (OS/2, Windows 95, and maybe others) will have to
4144 make take care of this. */
4145void
4146start_tcp_server (tofdp, fromfdp)
4147 int *tofdp, *fromfdp;
4148{
4149 int s;
4150 const char *portenv;
4151 int port;
4152 struct hostent *hp;
4153 struct sockaddr_in client_sai;
4154 char *hname;
4155
4156 s = socket (AF_INET2, SOCK_STREAM1, 0);
4157 if (s < 0)
4158 error (1, 0, "cannot create socket: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
4159
4160 port = get_cvs_port_number (current_parsed_root);
4161
4162 hp = init_sockaddr (&client_sai, current_parsed_root->hostname, port);
4163
4164 hname = xmalloc (strlen (hp->h_name) + 1);
4165 strcpy (hname, hp->h_name);
4166
4167 if (trace)
4168 {
4169 fprintf (stderr(&__sF[2]), " -> Connecting to %s(%s):%d\n",
4170 current_parsed_root->hostname,
4171 inet_ntoa (client_sai.sin_addr), port);
4172 }
4173
4174 if (connect (s, (struct sockaddr *) &client_sai, sizeof client_sai) < 0)
4175 error (1, 0, "connect to %s(%s):%d failed: %s",
4176 current_parsed_root->hostname,
4177 inet_ntoa (client_sai.sin_addr),
4178 port, SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
4179
4180 {
4181 const char *realm;
4182 struct sockaddr_in laddr;
4183 int laddrlen;
4184 KTEXT_ST ticket;
4185 MSG_DAT msg_data;
4186 CREDENTIALS cred;
4187 int status;
4188
4189 realm = krb_realmofhost (hname);
4190
4191 laddrlen = sizeof (laddr);
4192 if (getsockname (s, (struct sockaddr *) &laddr, &laddrlen) < 0)
4193 error (1, 0, "getsockname failed: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
4194
4195 /* We don't care about the checksum, and pass it as zero. */
4196 status = krb_sendauth (KOPT_DO_MUTUAL, s, &ticket, "rcmd",
4197 hname, realm, (unsigned long) 0, &msg_data,
4198 &cred, sched, &laddr, &client_sai, "KCVSV1.0");
4199 if (status != KSUCCESS)
4200 error (1, 0, "kerberos authentication failed: %s",
4201 krb_get_err_text (status));
4202 memcpy (kblock, cred.session, sizeof (C_Block));
4203 }
4204
4205 server_fd = s;
4206 close_on_exec (server_fd);
4207
4208 free (hname);
4209
4210 /* Give caller the values it wants. */
4211 *tofdp = s;
4212 *fromfdp = s;
4213}
4214
4215#endif /* HAVE_KERBEROS */
4216
4217#ifdef HAVE_GSSAPI
4218
4219/* Receive a given number of bytes. */
4220
4221static void
4222recv_bytes (sock, buf, need)
4223 int sock;
4224 char *buf;
4225 int need;
4226{
4227 while (need > 0)
4228 {
4229 int got;
4230
4231 got = recv (sock, buf, need, 0);
4232 if (got <= 0)
4233 error (1, 0, "recv() from server %s: %s", current_parsed_root->hostname,
4234 got == 0 ? "EOF" : SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
4235
4236 buf += got;
4237 need -= got;
4238 }
4239}
4240
4241/* Connect to the server using GSSAPI authentication. */
4242
4243static int
4244connect_to_gserver (sock, hostname)
4245 int sock;
4246 const char *hostname;
4247{
4248 char *str;
4249 char buf[1024];
4250 gss_buffer_desc *tok_in_ptr, tok_in, tok_out;
4251 OM_uint32 stat_min, stat_maj;
4252 gss_name_t server_name;
4253
4254 str = "BEGIN GSSAPI REQUEST\012";
4255
4256 if (send (sock, str, strlen (str), 0) < 0)
4257 error (1, 0, "cannot send: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
4258
4259 sprintf (buf, "cvs@%s", hostname);
4260 tok_in.length = strlen (buf);
4261 tok_in.value = buf;
4262 gss_import_name (&stat_min, &tok_in, GSS_C_NT_HOSTBASED_SERVICE,
4263 &server_name);
4264
4265 tok_in_ptr = GSS_C_NO_BUFFER;
4266 gcontext = GSS_C_NO_CONTEXT;
4267
4268 do
4269 {
4270 stat_maj = gss_init_sec_context (&stat_min, GSS_C_NO_CREDENTIAL,
4271 &gcontext, server_name,
4272 GSS_C_NULL_OID,
4273 (GSS_C_MUTUAL_FLAG
4274 | GSS_C_REPLAY_FLAG),
4275 0, NULL((void*)0), tok_in_ptr, NULL((void*)0), &tok_out,
4276 NULL((void*)0), NULL((void*)0));
4277 if (stat_maj != GSS_S_COMPLETE && stat_maj != GSS_S_CONTINUE_NEEDED)
4278 {
4279 OM_uint32 message_context;
4280 OM_uint32 new_stat_min;
4281
4282 message_context = 0;
4283 gss_display_status (&new_stat_min, stat_maj, GSS_C_GSS_CODE,
4284 GSS_C_NULL_OID, &message_context, &tok_out);
4285 error (0, 0, "GSSAPI authentication failed: %s",
4286 (char *) tok_out.value);
4287
4288 message_context = 0;
4289 gss_display_status (&new_stat_min, stat_min, GSS_C_MECH_CODE,
4290 GSS_C_NULL_OID, &message_context, &tok_out);
4291 error (1, 0, "GSSAPI authentication failed: %s",
4292 (char *) tok_out.value);
4293 }
4294
4295 if (tok_out.length == 0)
4296 {
4297 tok_in.length = 0;
4298 }
4299 else
4300 {
4301 char cbuf[2];
4302 int need;
4303
4304 cbuf[0] = (tok_out.length >> 8) & 0xff;
4305 cbuf[1] = tok_out.length & 0xff;
4306 if (send (sock, cbuf, 2, 0) < 0)
4307 error (1, 0, "cannot send: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
4308 if (send (sock, tok_out.value, tok_out.length, 0) < 0)
4309 error (1, 0, "cannot send: %s", SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
4310
4311 recv_bytes (sock, cbuf, 2);
4312 need = ((cbuf[0] & 0xff) << 8) | (cbuf[1] & 0xff);
4313
4314 if (need > sizeof buf)
4315 {
4316 int got;
4317
4318 /* This usually means that the server sent us an error
4319 message. Read it byte by byte and print it out.
4320 FIXME: This is a terrible error handling strategy.
4321 However, even if we fix the server, we will still
4322 want to do this to work with older servers. */
4323 buf[0] = cbuf[0];
4324 buf[1] = cbuf[1];
4325 got = recv (sock, buf + 2, sizeof buf - 2, 0);
4326 if (got < 0)
4327 error (1, 0, "recv() from server %s: %s",
4328 current_parsed_root->hostname, SOCK_STRERRORstrerror (SOCK_ERRNO(*__errno())));
4329 buf[got + 2] = '\0';
4330 if (buf[got + 1] == '\n')
4331 buf[got + 1] = '\0';
4332 error (1, 0, "error from server %s: %s", current_parsed_root->hostname,
4333 buf);
4334 }
4335
4336 recv_bytes (sock, buf, need);
4337 tok_in.length = need;
4338 }
4339
4340 tok_in.value = buf;
4341 tok_in_ptr = &tok_in;
4342 }
4343 while (stat_maj == GSS_S_CONTINUE_NEEDED);
4344
4345 return 1;
4346}
4347
4348#endif /* HAVE_GSSAPI */
4349
4350static int send_variable_proc PROTO ((Node *, void *))(Node *, void *);
4351
4352static int
4353send_variable_proc (node, closure)
4354 Node *node;
4355 void *closure;
4356{
4357 send_to_server ("Set ", 0);
4358 send_to_server (node->key, 0);
4359 send_to_server ("=", 1);
4360 send_to_server (node->data, 0);
4361 send_to_server ("\012", 1);
4362 return 0;
4363}
4364
4365/* Contact the server. */
4366void
4367start_server ()
4368{
4369 int tofd, fromfd, rootless;
4370 char *log = getenv ("CVS_CLIENT_LOG");
4371
4372
4373 /* Clear our static variables for this invocation. */
4374 if (toplevel_repos != NULL((void*)0))
4375 free (toplevel_repos);
4376 toplevel_repos = NULL((void*)0);
4377
4378
4379 /* Note that generally speaking we do *not* fall back to a different
4380 way of connecting if the first one does not work. This is slow
4381 (*really* slow on a 14.4kbps link); the clean way to have a CVS
4382 which supports several ways of connecting is with access methods. */
4383
4384 switch (current_parsed_root->method)
4385 {
4386
4387#ifdef AUTH_CLIENT_SUPPORT1
4388 case pserver_method:
4389 /* Toss the return value. It will die with error if anything
4390 goes wrong anyway. */
4391 connect_to_pserver (&tofd, &fromfd, 0, 0);
4392 break;
4393#endif
4394
4395#if HAVE_KERBEROS
4396 case kserver_method:
4397 start_tcp_server (&tofd, &fromfd);
4398 break;
4399#endif
4400
4401#ifdef HAVE_GSSAPI
4402 case gserver_method:
4403 /* GSSAPI authentication is handled by the pserver. */
4404 connect_to_pserver (&tofd, &fromfd, 0, 1);
4405 break;
4406#endif
4407
4408 case ext_method:
4409#if defined (NO_EXT_METHOD)
4410 error (0, 0, ":ext: method not supported by this port of CVS");
4411 error (1, 0, "try :server: instead");
4412#else
4413 start_rsh_server (&tofd, &fromfd);
4414#endif
4415 break;
4416
4417 case server_method:
4418#if defined(START_SERVER)
4419 START_SERVER (&tofd, &fromfd, getcaller (),
4420 current_parsed_root->username, current_parsed_root->hostname,
4421 current_parsed_root->directory);
4422# if defined (START_SERVER_RETURNS_SOCKET) && defined (NO_SOCKET_TO_FD)
4423 /* This is a system on which we can only write to a socket
4424 using send/recv. Therefore its START_SERVER needs to
4425 return a socket. */
4426 use_socket_style = 1;
4427 server_sock = tofd;
4428# endif
4429
4430#else
4431 /* FIXME: It should be possible to implement this portably,
4432 like pserver, which would get rid of the duplicated code
4433 in {vms,windows-NT,...}/startserver.c. */
4434 error (1, 0, "\
4435the :server: access method is not supported by this port of CVS");
4436#endif
4437 break;
4438
4439 case fork_method:
4440 connect_to_forked_server (&tofd, &fromfd);
4441 break;
4442
4443 default:
4444 error (1, 0, "\
4445(start_server internal error): unknown access method");
4446 break;
4447 }
4448
4449 /* "Hi, I'm Darlene and I'll be your server tonight..." */
4450 server_started = 1;
4451
4452#ifdef NO_SOCKET_TO_FD
4453 if (use_socket_style)
4454 {
4455 to_server = socket_buffer_initialize (server_sock, 0,
4456 (BUFMEMERRPROC) NULL((void*)0));
4457 from_server = socket_buffer_initialize (server_sock, 1,
4458 (BUFMEMERRPROC) NULL((void*)0));
4459 }
4460 else
4461#endif /* NO_SOCKET_TO_FD */
4462 {
4463 /* todo: some OS's don't need these calls... */
4464 close_on_exec (tofd);
4465 close_on_exec (fromfd);
4466
4467 /* SCO 3 and AIX have a nasty bug in the I/O libraries which precludes
4468 fdopening the same file descriptor twice, so dup it if it is the
4469 same. */
4470 if (tofd == fromfd)
4471 {
4472 fromfd = dup (tofd);
4473 if (fromfd < 0)
4474 error (1, errno(*__errno()), "cannot dup net connection");
4475 }
4476
4477 /* These will use binary mode on systems which have it. */
4478 to_server_fp = fdopen (tofd, FOPEN_BINARY_WRITE("wb"));
4479 if (to_server_fp == NULL((void*)0))
4480 error (1, errno(*__errno()), "cannot fdopen %d for write", tofd);
4481 to_server = stdio_buffer_initialize (to_server_fp, 0,
4482 (BUFMEMERRPROC) NULL((void*)0));
4483
4484 from_server_fp = fdopen (fromfd, FOPEN_BINARY_READ("rb"));
4485 if (from_server_fp == NULL((void*)0))
4486 error (1, errno(*__errno()), "cannot fdopen %d for read", fromfd);
4487 from_server = stdio_buffer_initialize (from_server_fp, 1,
4488 (BUFMEMERRPROC) NULL((void*)0));
4489 }
4490
4491 /* Set up logfiles, if any. */
4492 if (log)
4493 {
4494 int len = strlen (log);
4495 char *buf = xmalloc (len + 5);
4496 char *p;
4497 FILE *fp;
4498
4499 strcpy (buf, log);
4500 p = buf + len;
4501
4502 /* Open logfiles in binary mode so that they reflect
4503 exactly what was transmitted and received (that is
4504 more important than that they be maximally
4505 convenient to view). */
4506 /* Note that if we create several connections in a single CVS client
4507 (currently used by update.c), then the last set of logfiles will
4508 overwrite the others. There is currently no way around this. */
4509 strcpy (p, ".in");
4510 fp = open_file (buf, "wb");
4511 if (fp == NULL((void*)0))
4512 error (0, errno(*__errno()), "opening to-server logfile %s", buf);
4513 else
4514 to_server = log_buffer_initialize (to_server, fp, 0,
4515 (BUFMEMERRPROC) NULL((void*)0));
4516
4517 strcpy (p, ".out");
4518 fp = open_file (buf, "wb");
4519 if (fp == NULL((void*)0))
4520 error (0, errno(*__errno()), "opening from-server logfile %s", buf);
4521 else
4522 from_server = log_buffer_initialize (from_server, fp, 1,
4523 (BUFMEMERRPROC) NULL((void*)0));
4524
4525 free (buf);
4526 }
4527
4528 /* Clear static variables. */
4529 if (toplevel_repos != NULL((void*)0))
4530 free (toplevel_repos);
4531 toplevel_repos = NULL((void*)0);
4532 if (last_dir_name != NULL((void*)0))
4533 free (last_dir_name);
4534 last_dir_name = NULL((void*)0);
4535 if (last_repos != NULL((void*)0))
4536 free (last_repos);
4537 last_repos = NULL((void*)0);
4538 if (last_update_dir != NULL((void*)0))
4539 free (last_update_dir);
4540 last_update_dir = NULL((void*)0);
4541 stored_checksum_valid = 0;
4542 if (stored_mode != NULL((void*)0))
4543 {
4544 free (stored_mode);
4545 stored_mode = NULL((void*)0);
4546 }
4547
4548 rootless = (strcmp (command_name, "init") == 0);
4549 if (!rootless)
4550 {
4551 send_to_server ("Root ", 0);
4552 send_to_server (current_parsed_root->directory, 0);
4553 send_to_server ("\012", 1);
4554 }
4555
4556 {
4557 struct response *rs;
4558
4559 send_to_server ("Valid-responses", 0);
4560
4561 for (rs = responses; rs->name != NULL((void*)0); ++rs)
4562 {
4563 send_to_server (" ", 0);
4564 send_to_server (rs->name, 0);
4565 }
4566 send_to_server ("\012", 1);
4567 }
4568 send_to_server ("valid-requests\012", 0);
4569
4570 if (get_server_responses ())
4571 error_exit ();
4572
4573 /*
4574 * Now handle global options.
4575 *
4576 * -H, -f, -d, -e should be handled OK locally.
4577 *
4578 * -b we ignore (treating it as a server installation issue).
4579 * FIXME: should be an error message.
4580 *
4581 * -v we print local version info; FIXME: Add a protocol request to get
4582 * the version from the server so we can print that too.
4583 *
4584 * -l -t -r -w -q -n and -Q need to go to the server.
4585 */
4586
4587 {
4588 int have_global = supported_request ("Global_option");
4589
4590 if (noexec)
4591 {
4592 if (have_global)
4593 {
4594 send_to_server ("Global_option -n\012", 0);
4595 }
4596 else
4597 error (1, 0,
4598 "This server does not support the global -n option.");
4599 }
4600 if (quiet)
4601 {
4602 if (have_global)
4603 {
4604 send_to_server ("Global_option -q\012", 0);
4605 }
4606 else
4607 error (1, 0,
4608 "This server does not support the global -q option.");
4609 }
4610 if (really_quiet)
4611 {
4612 if (have_global)
4613 {
4614 send_to_server ("Global_option -Q\012", 0);
4615 }
4616 else
4617 error (1, 0,
4618 "This server does not support the global -Q option.");
4619 }
4620 if (!cvswrite)
4621 {
4622 if (have_global)
4623 {
4624 send_to_server ("Global_option -r\012", 0);
4625 }
4626 else
4627 error (1, 0,
4628 "This server does not support the global -r option.");
4629 }
4630 if (trace)
4631 {
4632 if (have_global)
4633 {
4634 send_to_server ("Global_option -t\012", 0);
4635 }
4636 else
4637 error (1, 0,
4638 "This server does not support the global -t option.");
4639 }
4640 if (logoff)
4641 {
4642 if (have_global)
4643 {
4644 send_to_server ("Global_option -l\012", 0);
4645 }
4646 else
4647 error (1, 0,
4648 "This server does not support the global -l option.");
4649 }
4650 }
4651
4652 /* Find out about server-side cvswrappers. An extra network
4653 turnaround for cvs import seems to be unavoidable, unless we
4654 want to add some kind of client-side place to configure which
4655 filenames imply binary. For cvs add, we could avoid the
4656 problem by keeping a copy of the wrappers in CVSADM (the main
4657 reason to bother would be so we could make add work without
4658 contacting the server, I suspect). */
4659
4660 if ((strcmp (command_name, "import") == 0)
4661 || (strcmp (command_name, "add") == 0))
4662 {
4663 if (supported_request ("wrapper-sendme-rcsOptions"))
4664 {
4665 int err;
4666 send_to_server ("wrapper-sendme-rcsOptions\012", 0);
4667 err = get_server_responses ();
4668 if (err != 0)
4669 error (err, 0, "error reading from server");
4670 }
4671 }
4672
4673 if (cvsencrypt && !rootless)
4674 {
4675#ifdef ENCRYPTION
4676 /* Turn on encryption before turning on compression. We do
4677 not want to try to compress the encrypted stream. Instead,
4678 we want to encrypt the compressed stream. If we can't turn
4679 on encryption, bomb out; don't let the user think the data
4680 is being encrypted when it is not. */
4681#ifdef HAVE_KERBEROS
4682 if (current_parsed_root->method == kserver_method)
4683 {
4684 if (! supported_request ("Kerberos-encrypt"))
4685 error (1, 0, "This server does not support encryption");
4686 send_to_server ("Kerberos-encrypt\012", 0);
4687 to_server = krb_encrypt_buffer_initialize (to_server, 0, sched,
4688 kblock,
4689 (BUFMEMERRPROC) NULL((void*)0));
4690 from_server = krb_encrypt_buffer_initialize (from_server, 1,
4691 sched, kblock,
4692 (BUFMEMERRPROC) NULL((void*)0));
4693 }
4694 else
4695#endif /* HAVE_KERBEROS */
4696#ifdef HAVE_GSSAPI
4697 if (current_parsed_root->method == gserver_method)
4698 {
4699 if (! supported_request ("Gssapi-encrypt"))
4700 error (1, 0, "This server does not support encryption");
4701 send_to_server ("Gssapi-encrypt\012", 0);
4702 to_server = cvs_gssapi_wrap_buffer_initialize (to_server, 0,
4703 gcontext,
4704 ((BUFMEMERRPROC)
4705 NULL((void*)0)));
4706 from_server = cvs_gssapi_wrap_buffer_initialize (from_server, 1,
4707 gcontext,
4708 ((BUFMEMERRPROC)
4709 NULL((void*)0)));
4710 cvs_gssapi_encrypt = 1;
4711 }
4712 else
4713#endif /* HAVE_GSSAPI */
4714 error (1, 0, "Encryption is only supported when using GSSAPI or Kerberos");
4715#else /* ! ENCRYPTION */
4716 error (1, 0, "This client does not support encryption");
4717#endif /* ! ENCRYPTION */
4718 }
4719
4720 if (gzip_level && !rootless)
4721 {
4722 if (supported_request ("Gzip-stream"))
4723 {
4724 char gzip_level_buf[5];
4725 send_to_server ("Gzip-stream ", 0);
4726 sprintf (gzip_level_buf, "%d", gzip_level);
4727 send_to_server (gzip_level_buf, 0);
4728 send_to_server ("\012", 1);
4729
4730 /* All further communication with the server will be
4731 compressed. */
4732
4733 to_server = compress_buffer_initialize (to_server, 0, gzip_level,
4734 (BUFMEMERRPROC) NULL((void*)0));
4735 from_server = compress_buffer_initialize (from_server, 1,
4736 gzip_level,
4737 (BUFMEMERRPROC) NULL((void*)0));
4738 }
4739#ifndef NO_CLIENT_GZIP_PROCESS
4740 else if (supported_request ("gzip-file-contents"))
4741 {
4742 char gzip_level_buf[5];
4743 send_to_server ("gzip-file-contents ", 0);
4744 sprintf (gzip_level_buf, "%d", gzip_level);
4745 send_to_server (gzip_level_buf, 0);
4746
4747 send_to_server ("\012", 1);
4748
4749 file_gzip_level = gzip_level;
4750 }
4751#endif
4752 else
4753 {
4754 fprintf (stderr(&__sF[2]), "server doesn't support gzip-file-contents\n");
4755 /* Setting gzip_level to 0 prevents us from giving the
4756 error twice if update has to contact the server again
4757 to fetch unpatchable files. */
4758 gzip_level = 0;
4759 }
4760 }
4761
4762 if (cvsauthenticate && ! cvsencrypt && !rootless)
4763 {
4764 /* Turn on authentication after turning on compression, so
4765 that we can compress the authentication information. We
4766 assume that encrypted data is always authenticated--the
4767 ability to decrypt the data stream is itself a form of
4768 authentication. */
4769#ifdef HAVE_GSSAPI
4770 if (current_parsed_root->method == gserver_method)
4771 {
4772 if (! supported_request ("Gssapi-authenticate"))
4773 error (1, 0,
4774 "This server does not support stream authentication");
4775 send_to_server ("Gssapi-authenticate\012", 0);
4776 to_server = cvs_gssapi_wrap_buffer_initialize (to_server, 0,
4777 gcontext,
4778 ((BUFMEMERRPROC)
4779 NULL((void*)0)));
4780 from_server = cvs_gssapi_wrap_buffer_initialize (from_server, 1,
4781 gcontext,
4782 ((BUFMEMERRPROC)
4783 NULL((void*)0)));
4784 }
4785 else
4786 error (1, 0, "Stream authentication is only supported when using GSSAPI");
4787#else /* ! HAVE_GSSAPI */
4788 error (1, 0, "This client does not support stream authentication");
4789#endif /* ! HAVE_GSSAPI */
4790 }
4791
4792#ifdef FILENAMES_CASE_INSENSITIVE
4793 if (supported_request ("Case") && !rootless)
4794 send_to_server ("Case\012", 0);
4795#endif
4796
4797 /* If "Set" is not supported, just silently fail to send the variables.
4798 Users with an old server should get a useful error message when it
4799 fails to recognize the ${=foo} syntax. This way if someone uses
4800 several servers, some of which are new and some old, they can still
4801 set user variables in their .cvsrc without trouble. */
4802 if (supported_request ("Set"))
4803 walklist (variable_list, send_variable_proc, NULL((void*)0));
4804}
4805
4806#ifndef NO_EXT_METHOD
4807
4808/* Contact the server by starting it with rsh. */
4809
4810/* Right now, we have two different definitions for this function,
4811 depending on whether we start the rsh server using popenRW or not.
4812 This isn't ideal, and the best thing would probably be to change
4813 the OS/2 port to be more like the regular Unix client (i.e., by
4814 implementing piped_child)... but I'm doing something else at the
4815 moment, and wish to make only one change at a time. -Karl */
4816
4817#ifdef START_RSH_WITH_POPEN_RW
4818
4819/* This is actually a crock -- it's OS/2-specific, for no one else
4820 uses it. If I get time, I want to make piped_child and all the
4821 other stuff in os2/run.c work right. In the meantime, this gets us
4822 up and running, and that's most important. */
4823
4824static void
4825start_rsh_server (tofdp, fromfdp)
4826 int *tofdp, *fromfdp;
4827{
4828 int pipes[2];
4829
4830 /* If you're working through firewalls, you can set the
4831 CVS_RSH environment variable to a script which uses rsh to
4832 invoke another rsh on a proxy machine. */
4833 char *cvs_rsh = getenv ("CVS_RSH");
4834 char *cvs_server = getenv ("CVS_SERVER");
4835 int i = 0;
4836 /* This needs to fit "rsh", "-b", "-l", "USER", "--", "host",
4837 "cmd (w/ args)", and NULL. We leave some room to grow. */
4838 char *rsh_argv[10];
4839
4840 if (!cvs_rsh)
4841 /* People sometimes suggest or assume that this should default
4842 to "remsh" on systems like HPUX in which that is the
4843 system-supplied name for the rsh program. However, that
4844 causes various problems (keep in mind that systems such as
4845 HPUX might have non-system-supplied versions of "rsh", like
4846 a Kerberized one, which one might want to use). If we
4847 based the name on what is found in the PATH of the person
4848 who runs configure, that would make it harder to
4849 consistently produce the same result in the face of
4850 different people producing binary distributions. If we
4851 based it on "remsh" always being the default for HPUX
4852 (e.g. based on uname), that might be slightly better but
4853 would require us to keep track of what the defaults are for
4854 each system type, and probably would cope poorly if the
4855 existence of remsh or rsh varies from OS version to OS
4856 version. Therefore, it seems best to have the default
4857 remain "rsh", and tell HPUX users to specify remsh, for
4858 example in CVS_RSH or other such mechanisms to be devised,
4859 if that is what they want (the manual already tells them
4860 that).
4861 Nowadays, however, ssh is pretty much everywhere, so we start
4862 to default to ssh instead.
4863 */
4864 cvs_rsh = "ssh";
4865 if (!cvs_server)
4866 cvs_server = "cvs";
4867
4868 /* The command line starts out with rsh. */
4869 rsh_argv[i++] = cvs_rsh;
4870
4871#ifdef RSH_NEEDS_BINARY_FLAG
4872 /* "-b" for binary, under OS/2. */
4873 rsh_argv[i++] = "-b";
4874#endif /* RSH_NEEDS_BINARY_FLAG */
4875
4876 /* Then we strcat more things on the end one by one. */
4877 if (current_parsed_root->username != NULL((void*)0))
4878 {
4879 rsh_argv[i++] = "-l";
4880 rsh_argv[i++] = current_parsed_root->username;
4881 }
4882
4883 rsh_argv[i++] = "--";
4884 rsh_argv[i++] = current_parsed_root->hostname;
4885 rsh_argv[i++] = cvs_server;
4886 rsh_argv[i++] = "server";
4887
4888 /* Mark the end of the arg list. */
4889 rsh_argv[i] = (char *) NULL((void*)0);
4890
4891 if (trace)
4892 {
4893 fprintf (stderr(&__sF[2]), " -> Starting server: ");
4894 for (i = 0; rsh_argv[i]; i++)
4895 fprintf (stderr(&__sF[2]), "%s ", rsh_argv[i]);
4896 putc ('\n', stderr)(!__isthreaded ? __sputc('\n', (&__sF[2])) : (putc)('\n',
(&__sF[2])))
;
4897 }
4898
4899 /* Do the deed. */
4900 rsh_pid = popenRW (rsh_argv, pipes);
4901 if (rsh_pid < 0)
4902 error (1, errno(*__errno()), "cannot start server via ssh");
4903
4904 /* Give caller the file descriptors. */
4905 *tofdp = pipes[0];
4906 *fromfdp = pipes[1];
4907}
4908
4909#else /* ! START_RSH_WITH_POPEN_RW */
4910
4911static void
4912start_rsh_server (tofdp, fromfdp)
4913 int *tofdp;
4914 int *fromfdp;
4915{
4916 /* If you're working through firewalls, you can set the
4917 CVS_RSH environment variable to a script which uses rsh to
4918 invoke another rsh on a proxy machine. */
4919 char *cvs_rsh = getenv ("CVS_RSH");
4920 char *cvs_server = getenv ("CVS_SERVER");
4921 char *command;
4922
4923 if (!cvs_rsh)
4924 cvs_rsh = "ssh";
4925 if (!cvs_server)
4926 cvs_server = "cvs";
4927
4928 /* Pass the command to rsh as a single string. This shouldn't
4929 affect most rsh servers at all, and will pacify some buggy
4930 versions of rsh that grab switches out of the middle of the
4931 command (they're calling the GNU getopt routines incorrectly). */
4932 command = xmalloc (strlen (cvs_server)
4933 + strlen (current_parsed_root->directory)
4934 + 50);
4935
4936 /* If you are running a very old (Nov 3, 1994, before 1.5)
4937 * version of the server, you need to make sure that your .bashrc
4938 * on the server machine does not set CVSROOT to something
4939 * containing a colon (or better yet, upgrade the server). */
4940 sprintf (command, "%s server", cvs_server);
4941
4942 {
4943 char *argv[10];
4944 char **p = argv;
4945
4946 *p++ = cvs_rsh;
4947
4948 /* If the login names differ between client and server
4949 * pass it on to rsh.
4950 */
4951 if (current_parsed_root->username != NULL((void*)0))
4952 {
4953 *p++ = "-l";
4954 *p++ = current_parsed_root->username;
4955 }
4956
4957 *p++ = "--";
4958 *p++ = current_parsed_root->hostname;
4959 *p++ = command;
4960 *p++ = NULL((void*)0);
4961
4962 if (trace)
4963 {
4964 int i;
4965
4966 fprintf (stderr(&__sF[2]), " -> Starting server: ");
4967 for (i = 0; argv[i]; i++)
4968 fprintf (stderr(&__sF[2]), "%s ", argv[i]);
4969 putc ('\n', stderr)(!__isthreaded ? __sputc('\n', (&__sF[2])) : (putc)('\n',
(&__sF[2])))
;
4970 }
4971 rsh_pid = piped_child (argv, tofdp, fromfdp);
4972
4973 if (rsh_pid < 0)
4974 error (1, errno(*__errno()), "cannot start server via ssh");
4975 }
4976 free (command);
4977}
4978
4979#endif /* START_RSH_WITH_POPEN_RW */
4980
4981#endif /* NO_EXT_METHOD */
4982
4983
4984
4985/* Send an argument STRING. */
4986void
4987send_arg (string)
4988 char *string;
4989{
4990 char buf[1];
4991 char *p = string;
4992
4993 send_to_server ("Argument ", 0);
4994
4995 while (*p)
4996 {
4997 if (*p == '\n')
4998 {
4999 send_to_server ("\012Argumentx ", 0);
5000 }
5001 else
5002 {
5003 buf[0] = *p;
5004 send_to_server (buf, 1);
5005 }
5006 ++p;
5007 }
5008 send_to_server ("\012", 1);
5009}
5010
5011static void send_modified PROTO ((char *, char *, Vers_TS *))(char *, char *, Vers_TS *);
5012
5013/* VERS->OPTIONS specifies whether the file is binary or not. NOTE: BEFORE
5014 using any other fields of the struct vers, we would need to fix
5015 client_process_import_file to set them up. */
5016
5017static void
5018send_modified (file, short_pathname, vers)
5019 char *file;
5020 char *short_pathname;
5021 Vers_TS *vers;
5022{
5023 /* File was modified, send it. */
5024 struct stat sb;
5025 int fd;
5026 char *buf;
5027 char *mode_string;
5028 size_t bufsize;
5029 int bin;
5030
5031 if (trace)
5032 (void) fprintf (stderr(&__sF[2]), " -> Sending file `%s' to server\n", file);
5033
5034 /* Don't think we can assume fstat exists. */
5035 if ( CVS_STATstat (file, &sb) < 0)
5036 error (1, errno(*__errno()), "reading %s", short_pathname);
5037
5038 mode_string = mode_to_string (sb.st_mode);
5039
5040 /* Beware: on systems using CRLF line termination conventions,
5041 the read and write functions will convert CRLF to LF, so the
5042 number of characters read is not the same as sb.st_size. Text
5043 files should always be transmitted using the LF convention, so
5044 we don't want to disable this conversion. */
5045 bufsize = sb.st_size;
5046 buf = xmalloc (bufsize);
5047
5048 /* Is the file marked as containing binary data by the "-kb" flag?
5049 If so, make sure to open it in binary mode: */
5050
5051 if (vers && vers->options)
5052 bin = !(strcmp (vers->options, "-kb"));
5053 else
5054 bin = 0;
5055
5056#ifdef BROKEN_READWRITE_CONVERSION
5057 if (!bin)
5058 {
5059 /* If only stdio, not open/write/etc., do text/binary
5060 conversion, use convert_file which can compensate
5061 (FIXME: we could just use stdio instead which would
5062 avoid the whole problem). */
5063 char tfile[1024]; strcpy(tfile, file); strcat(tfile, ".CVSBFCTMP");
5064 convert_file (file, O_RDONLY0x0000,
5065 tfile, O_WRONLY0x0001 | O_CREAT0x0200 | O_TRUNC0x0400 | OPEN_BINARY(0));
5066 fd = CVS_OPENopen (tfile, O_RDONLY0x0000 | OPEN_BINARY(0));
5067 if (fd < 0)
5068 error (1, errno(*__errno()), "reading %s", short_pathname);
5069 }
5070 else
5071 fd = CVS_OPENopen (file, O_RDONLY0x0000 | OPEN_BINARY(0));
5072#else
5073 fd = CVS_OPENopen (file, O_RDONLY0x0000 | (bin ? OPEN_BINARY(0) : 0));
5074#endif
5075
5076 if (fd < 0)
5077 error (1, errno(*__errno()), "reading %s", short_pathname);
5078
5079 if (file_gzip_level && sb.st_size > 100)
5080 {
5081 size_t newsize = 0;
5082
5083 if (read_and_gzip (fd, short_pathname, (unsigned char **)&buf,
5084 &bufsize, &newsize,
5085 file_gzip_level))
5086 error (1, 0, "aborting due to compression error");
5087
5088 if (close (fd) < 0)
5089 error (0, errno(*__errno()), "warning: can't close %s", short_pathname);
5090
5091 {
5092 char tmp[80];
5093
5094 send_to_server ("Modified ", 0);
5095 send_to_server (file, 0);
5096 send_to_server ("\012", 1);
5097 send_to_server (mode_string, 0);
5098 send_to_server ("\012z", 2);
5099 sprintf (tmp, "%lu\n", (unsigned long) newsize);
5100 send_to_server (tmp, 0);
5101
5102 send_to_server (buf, newsize);
5103 }
5104 }
5105 else
5106 {
5107 int newsize;
5108
5109 {
5110 char *bufp = buf;
5111 int len;
5112
5113 /* FIXME: This is gross. It assumes that we might read
5114 less than st_size bytes (true on NT), but not more.
5115 Instead of this we should just be reading a block of
5116 data (e.g. 8192 bytes), writing it to the network, and
5117 so on until EOF. */
5118 while ((len = read (fd, bufp, (buf + sb.st_size) - bufp)) > 0)
5119 bufp += len;
5120
5121 if (len < 0)
5122 error (1, errno(*__errno()), "reading %s", short_pathname);
5123
5124 newsize = bufp - buf;
5125 }
5126 if (close (fd) < 0)
5127 error (0, errno(*__errno()), "warning: can't close %s", short_pathname);
5128
5129 {
5130 char tmp[80];
5131
5132 send_to_server ("Modified ", 0);
5133 send_to_server (file, 0);
5134 send_to_server ("\012", 1);
5135 send_to_server (mode_string, 0);
5136 send_to_server ("\012", 1);
5137 sprintf (tmp, "%lu\012", (unsigned long) newsize);
5138 send_to_server (tmp, 0);
5139 }
5140#ifdef BROKEN_READWRITE_CONVERSION
5141 if (!bin)
5142 {
5143 char tfile[1024]; strcpy(tfile, file); strcat(tfile, ".CVSBFCTMP");
5144 if (CVS_UNLINKunlink (tfile) < 0)
5145 error (0, errno(*__errno()), "warning: can't remove temp file %s", tfile);
5146 }
5147#endif
5148
5149 /*
5150 * Note that this only ends with a newline if the file ended with
5151 * one.
5152 */
5153 if (newsize > 0)
5154 send_to_server (buf, newsize);
5155 }
5156 free (buf);
5157 free (mode_string);
5158}
5159
5160/* The address of an instance of this structure is passed to
5161 send_fileproc, send_filesdoneproc, and send_direntproc, as the
5162 callerdat parameter. */
5163
5164struct send_data
5165{
5166 /* Each of the following flags are zero for clear or nonzero for set. */
5167 int build_dirs;
5168 int force;
5169 int no_contents;
5170 int backup_modified;
5171};
5172
5173static int send_fileproc PROTO ((void *callerdat, struct file_info *finfo))(void *callerdat, struct file_info *finfo);
5174
5175/* Deal with one file. */
5176static int
5177send_fileproc (callerdat, finfo)
5178 void *callerdat;
5179 struct file_info *finfo;
5180{
5181 struct send_data *args = (struct send_data *) callerdat;
5182 Vers_TS *vers;
5183 struct file_info xfinfo;
5184 /* File name to actually use. Might differ in case from
5185 finfo->file. */
5186 char *filename;
5187
5188 send_a_repository ("", finfo->repository, finfo->update_dir);
5189
5190 xfinfo = *finfo;
5191 xfinfo.repository = NULL((void*)0);
5192 xfinfo.rcs = NULL((void*)0);
5193 vers = Version_TS (&xfinfo, NULL((void*)0), NULL((void*)0), NULL((void*)0), 0, 0);
5194
5195 if (vers->entdata != NULL((void*)0))
5196 filename = vers->entdata->user;
5197 else
5198 filename = finfo->file;
5199
5200 if (vers->vn_user != NULL((void*)0))
5201 {
5202 /* The Entries request. */
5203 send_to_server ("Entry /", 0);
5204 send_to_server (filename, 0);
5205 send_to_server ("/", 0);
5206 send_to_server (vers->vn_user, 0);
5207 send_to_server ("/", 0);
5208 if (vers->ts_conflict != NULL((void*)0))
5209 {
5210 if (vers->ts_user != NULL((void*)0) &&
5211 strcmp (vers->ts_conflict, vers->ts_user) == 0)
5212 send_to_server ("+=", 0);
5213 else
5214 send_to_server ("+modified", 0);
5215 }
5216 send_to_server ("/", 0);
5217 send_to_server (vers->entdata != NULL((void*)0)
5218 ? vers->entdata->options
5219 : vers->options,
5220 0);
5221 send_to_server ("/", 0);
5222 if (vers->entdata != NULL((void*)0) && vers->entdata->tag)
5223 {
5224 send_to_server ("T", 0);
5225 send_to_server (vers->entdata->tag, 0);
5226 }
5227 else if (vers->entdata != NULL((void*)0) && vers->entdata->date)
5228 {
5229 send_to_server ("D", 0);
5230 send_to_server (vers->entdata->date, 0);
5231 }
5232 send_to_server ("\012", 1);
5233 }
5234 else
5235 {
5236 /* It seems a little silly to re-read this on each file, but
5237 send_dirent_proc doesn't get called if filenames are specified
5238 explicitly on the command line. */
5239 wrap_add_file (CVSDOTWRAPPER".cvswrappers", 1);
5240
5241 if (wrap_name_has (filename, WRAP_RCSOPTION))
5242 {
5243 /* No "Entry", but the wrappers did give us a kopt so we better
5244 send it with "Kopt". As far as I know this only happens
5245 for "cvs add". Question: is there any reason why checking
5246 for options from wrappers isn't done in Version_TS?
5247
5248 Note: it might have been better to just remember all the
5249 kopts on the client side, rather than send them to the server,
5250 and have it send us back the same kopts. But that seemed like
5251 a bigger change than I had in mind making now. */
5252
5253 if (supported_request ("Kopt"))
5254 {
5255 char *opt;
5256
5257 send_to_server ("Kopt ", 0);
5258 opt = wrap_rcsoption (filename, 1);
5259 send_to_server (opt, 0);
5260 send_to_server ("\012", 1);
5261 free (opt);
5262 }
5263 else
5264 error (0, 0,
5265 "\
5266warning: ignoring -k options due to server limitations");
5267 }
5268 }
5269
5270 if (vers->ts_user == NULL((void*)0))
5271 {
5272 /*
5273 * Do we want to print "file was lost" like normal CVS?
5274 * Would it always be appropriate?
5275 */
5276 /* File no longer exists. Don't do anything, missing files
5277 just happen. */
5278 }
5279 else if (vers->ts_rcs == NULL((void*)0)
5280 || args->force
5281 || strcmp (vers->ts_user, vers->ts_rcs) != 0)
5282 {
5283 if (args->no_contents
5284 && supported_request ("Is-modified"))
5285 {
5286 send_to_server ("Is-modified ", 0);
5287 send_to_server (filename, 0);
5288 send_to_server ("\012", 1);
5289 }
5290 else
5291 send_modified (filename, finfo->fullname, vers);
5292
5293 if (args->backup_modified)
5294 {
5295 char *bakname;
5296 bakname = backup_file (filename, vers->vn_user);
5297 /* This behavior is sufficiently unexpected to
5298 justify overinformativeness, I think. */
5299 if (! really_quiet)
5300 printf ("(Locally modified %s moved to %s)\n",
5301 filename, bakname);
5302 free (bakname);
5303 }
5304 }
5305 else
5306 {
5307 send_to_server ("Unchanged ", 0);
5308 send_to_server (filename, 0);
5309 send_to_server ("\012", 1);
5310 }
5311
5312 /* if this directory has an ignore list, add this file to it */
5313 if (ignlist)
5314 {
5315 Node *p;
5316
5317 p = getnode ();
5318 p->type = FILES;
5319 p->key = xstrdup (finfo->file);
5320 (void) addnode (ignlist, p);
5321 }
5322
5323 freevers_ts (&vers);
5324 return 0;
5325}
5326
5327static void send_ignproc PROTO ((char *, char *))(char *, char *);
5328
5329static void
5330send_ignproc (file, dir)
5331 char *file;
5332 char *dir;
5333{
5334 if (ign_inhibit_server || !supported_request ("Questionable"))
5335 {
5336 if (dir[0] != '\0')
5337 (void) printf ("? %s/%s\n", dir, file);
5338 else
5339 (void) printf ("? %s\n", file);
5340 }
5341 else
5342 {
5343 send_to_server ("Questionable ", 0);
5344 send_to_server (file, 0);
5345 send_to_server ("\012", 1);
5346 }
5347}
5348
5349static int send_filesdoneproc PROTO ((void *, int, char *, char *, List *))(void *, int, char *, char *, List *);
5350
5351static int
5352send_filesdoneproc (callerdat, err, repository, update_dir, entries)
5353 void *callerdat;
5354 int err;
5355 char *repository;
5356 char *update_dir;
5357 List *entries;
5358{
5359 /* if this directory has an ignore list, process it then free it */
5360 if (ignlist)
5361 {
5362 ignore_files (ignlist, entries, update_dir, send_ignproc);
5363 dellist (&ignlist);
5364 }
5365
5366 return (err);
5367}
5368
5369static Dtype send_dirent_proc PROTO ((void *, char *, char *, char *, List *))(void *, char *, char *, char *, List *);
5370
5371/*
5372 * send_dirent_proc () is called back by the recursion processor before a
5373 * sub-directory is processed for update.
5374 * A return code of 0 indicates the directory should be
5375 * processed by the recursion code. A return of non-zero indicates the
5376 * recursion code should skip this directory.
5377 *
5378 */
5379static Dtype
5380send_dirent_proc (callerdat, dir, repository, update_dir, entries)
5381 void *callerdat;
5382 char *dir;
5383 char *repository;
5384 char *update_dir;
5385 List *entries;
5386{
5387 struct send_data *args = (struct send_data *) callerdat;
5388 int dir_exists;
5389 char *cvsadm_name;
5390
5391 if (ignore_directory (update_dir))
5392 {
5393 /* print the warm fuzzy message */
5394 if (!quiet)
5395 error (0, 0, "Ignoring %s", update_dir);
5396 return (R_SKIP_ALL);
5397 }
5398
5399 /*
5400 * If the directory does not exist yet (e.g. "cvs update -d foo"),
5401 * no need to send any files from it. If the directory does not
5402 * have a CVS directory, then we pretend that it does not exist.
5403 * Otherwise, we will fail when trying to open the Entries file.
5404 * This case will happen when checking out a module defined as
5405 * ``-a .''.
5406 */
5407 cvsadm_name = xmalloc (strlen (dir) + sizeof (CVSADM"CVS") + 10);
5408 sprintf (cvsadm_name, "%s/%s", dir, CVSADM"CVS");
5409 dir_exists = isdir (cvsadm_name);
5410 free (cvsadm_name);
5411
5412 /*
5413 * If there is an empty directory (e.g. we are doing `cvs add' on a
5414 * newly-created directory), the server still needs to know about it.
5415 */
5416
5417 if (dir_exists)
5418 {
5419 /*
5420 * Get the repository from a CVS/Repository file whenever possible.
5421 * The repository variable is wrong if the names in the local
5422 * directory don't match the names in the repository.
5423 */
5424 char *repos = Name_Repository (dir, update_dir);
5425 send_a_repository (dir, repos, update_dir);
5426 free (repos);
5427
5428 /* initialize the ignore list for this directory */
5429 ignlist = getlist ();
5430 }
5431 else
5432 {
5433 /* It doesn't make sense to send a non-existent directory,
5434 because there is no way to get the correct value for
5435 the repository (I suppose maybe via the expand-modules
5436 request). In the case where the "obvious" choice for
5437 repository is correct, the server can figure out whether
5438 to recreate the directory; in the case where it is wrong
5439 (that is, does not match what modules give us), we might as
5440 well just fail to recreate it.
5441
5442 Checking for noexec is a kludge for "cvs -n add dir". */
5443 /* Don't send a non-existent directory unless we are building
5444 new directories (build_dirs is true). Otherwise, CVS may
5445 see a D line in an Entries file, and recreate a directory
5446 which the user removed by hand. */
5447 if (args->build_dirs && noexec)
5448 send_a_repository (dir, repository, update_dir);
5449 }
5450
5451 return (dir_exists ? R_PROCESS : R_SKIP_ALL);
5452}
5453
5454static int send_dirleave_proc PROTO ((void *, char *, int, char *, List *))(void *, char *, int, char *, List *);
5455
5456/*
5457 * send_dirleave_proc () is called back by the recursion code upon leaving
5458 * a directory. All it does is delete the ignore list if it hasn't already
5459 * been done (by send_filesdone_proc).
5460 */
5461/* ARGSUSED */
5462static int
5463send_dirleave_proc (callerdat, dir, err, update_dir, entries)
5464 void *callerdat;
5465 char *dir;
5466 int err;
5467 char *update_dir;
5468 List *entries;
5469{
5470
5471 /* Delete the ignore list if it hasn't already been done. */
5472 if (ignlist)
5473 dellist (&ignlist);
5474 return err;
5475}
5476
5477/*
5478 * Send each option in a string to the server, one by one.
5479 * This assumes that the options are separated by spaces, for example
5480 * STRING might be "--foo -C5 -y".
5481 */
5482
5483void
5484send_option_string (string)
5485 char *string;
5486{
5487 char *copy;
5488 char *p;
5489
5490 copy = xstrdup (string);
5491 p = copy;
5492 while (1)
5493 {
5494 char *s;
5495 char l;
5496
5497 for (s = p; *s != ' ' && *s != '\0'; s++)
5498 ;
5499 l = *s;
5500 *s = '\0';
5501 if (s != p)
5502 send_arg (p);
5503 if (l == '\0')
5504 break;
5505 p = s + 1;
5506 }
5507 free (copy);
5508}
5509
5510
5511/* Send the names of all the argument files to the server. */
5512
5513void
5514send_file_names (argc, argv, flags)
5515 int argc;
5516 char **argv;
5517 unsigned int flags;
5518{
5519 int i;
5520 int level;
5521 int max_level;
5522
5523 /* The fact that we do this here as well as start_recursion is a bit
5524 of a performance hit. Perhaps worth cleaning up someday. */
5525 if (flags & SEND_EXPAND_WILD1)
5526 expand_wild (argc, argv, &argc, &argv);
5527
5528 /* Send Max-dotdot if needed. */
5529 max_level = 0;
5530 for (i = 0; i < argc; ++i)
5531 {
5532 level = pathname_levels (argv[i]);
5533 if (level > max_level)
5534 max_level = level;
5535 }
5536 if (max_level > 0)
5537 {
5538 if (supported_request ("Max-dotdot"))
5539 {
5540 char buf[10];
5541 sprintf (buf, "%d", max_level);
5542
5543 send_to_server ("Max-dotdot ", 0);
5544 send_to_server (buf, 0);
5545 send_to_server ("\012", 1);
5546 }
5547 else
5548 /*
5549 * "leading .." is not strictly correct, as this also includes
5550 * cases like "foo/../..". But trying to explain that in the
5551 * error message would probably just confuse users.
5552 */
5553 error (1, 0,
5554 "leading .. not supported by old (pre-Max-dotdot) servers");
5555 }
5556
5557 for (i = 0; i < argc; ++i)
5558 {
5559 char buf[1];
5560 char *p = argv[i];
5561 char *line = NULL((void*)0);
5562
5563 if (arg_should_not_be_sent_to_server (argv[i]))
5564 continue;
5565
5566#ifdef FILENAMES_CASE_INSENSITIVE
5567 /* We want to send the file name as it appears
5568 in CVS/Entries. We put this inside an ifdef
5569 to avoid doing all these system calls in
5570 cases where fncmp is just strcmp anyway. */
5571 /* For now just do this for files in the local
5572 directory. Would be nice to handle the
5573 non-local case too, though. */
5574 /* The isdir check could more gracefully be replaced
5575 with a way of having Entries_Open report back the
5576 error to us and letting us ignore existence_error.
5577 Or some such. */
5578 if (p == last_component (p) && isdir (CVSADM"CVS"))
5579 {
5580 List *entries;
5581 Node *node;
5582
5583 /* If we were doing non-local directory,
5584 we would save_cwd, CVS_CHDIR
5585 like in update.c:isemptydir. */
5586 /* Note that if we are adding a directory,
5587 the following will read the entry
5588 that we just wrote there, that is, we
5589 will get the case specified on the
5590 command line, not the case of the
5591 directory in the filesystem. This
5592 is correct behavior. */
5593 entries = Entries_Open (0, NULL((void*)0));
5594 node = findnode_fn (entries, p);
5595 if (node != NULL((void*)0))
5596 {
5597 line = xstrdup (node->key);
5598 p = line;
5599 delnode (node);
5600 }
5601 Entries_Close (entries);
5602 }
5603#endif /* FILENAMES_CASE_INSENSITIVE */
5604
5605 send_to_server ("Argument ", 0);
5606
5607 while (*p)
5608 {
5609 if (*p == '\n')
5610 {
5611 send_to_server ("\012Argumentx ", 0);
5612 }
5613 else if (ISDIRSEP (*p)((*p) == '/'))
5614 {
5615 buf[0] = '/';
5616 send_to_server (buf, 1);
5617 }
5618 else
5619 {
5620 buf[0] = *p;
5621 send_to_server (buf, 1);
5622 }
5623 ++p;
5624 }
5625 send_to_server ("\012", 1);
5626 if (line != NULL((void*)0))
5627 free (line);
5628 }
5629
5630 if (flags & SEND_EXPAND_WILD1)
5631 {
5632 int i;
5633 for (i = 0; i < argc; ++i)
5634 free (argv[i]);
5635 free (argv);
5636 }
5637}
5638
5639
5640/* Send Repository, Modified and Entry. argc and argv contain only
5641 the files to operate on (or empty for everything), not options.
5642 local is nonzero if we should not recurse (-l option). flags &
5643 SEND_BUILD_DIRS is nonzero if nonexistent directories should be
5644 sent. flags & SEND_FORCE is nonzero if we should send unmodified
5645 files to the server as though they were modified. flags &
5646 SEND_NO_CONTENTS means that this command only needs to know
5647 _whether_ a file is modified, not the contents. Also sends Argument
5648 lines for argc and argv, so should be called after options are sent. */
5649void
5650send_files (argc, argv, local, aflag, flags)
5651 int argc;
5652 char **argv;
5653 int local;
5654 int aflag;
5655 unsigned int flags;
5656{
5657 struct send_data args;
5658 int err;
5659
5660 /*
5661 * aflag controls whether the tag/date is copied into the vers_ts.
5662 * But we don't actually use it, so I don't think it matters what we pass
5663 * for aflag here.
5664 */
5665 args.build_dirs = flags & SEND_BUILD_DIRS1;
5666 args.force = flags & SEND_FORCE2;
5667 args.no_contents = flags & SEND_NO_CONTENTS4;
5668 args.backup_modified = flags & BACKUP_MODIFIED_FILES8;
5669 err = start_recursion
5670 (send_fileproc, send_filesdoneproc,
5671 send_dirent_proc, send_dirleave_proc, (void *) &args,
5672 argc, argv, local, W_LOCAL0x01, aflag, 0, (char *)NULL((void*)0), 0);
5673 if (err)
5674 error_exit ();
5675 if (toplevel_repos == NULL((void*)0))
5676 /*
5677 * This happens if we are not processing any files,
5678 * or for checkouts in directories without any existing stuff
5679 * checked out. The following assignment is correct for the
5680 * latter case; I don't think toplevel_repos matters for the
5681 * former.
5682 */
5683 toplevel_repos = xstrdup (current_parsed_root->directory);
5684 send_repository ("", toplevel_repos, ".");
5685}
5686
5687void
5688client_import_setup (repository)
5689 char *repository;
5690{
5691 if (toplevel_repos == NULL((void*)0)) /* should always be true */
5692 send_a_repository ("", repository, "");
5693}
5694
5695/*
5696 * Process the argument import file.
5697 */
5698int
5699client_process_import_file (message, vfile, vtag, targc, targv, repository,
5700 all_files_binary, modtime)
5701 char *message;
5702 char *vfile;
5703 char *vtag;
5704 int targc;
5705 char *targv[];
5706 char *repository;
5707 int all_files_binary;
5708
5709 /* Nonzero for "import -d". */
5710 int modtime;
5711{
5712 char *update_dir;
5713 char *fullname;
5714 Vers_TS vers;
5715
5716 assert (toplevel_repos != NULL)((toplevel_repos != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/cvs/src/client.c"
, 5716, __func__, "toplevel_repos != NULL"))
;
5717
5718 if (strncmp (repository, toplevel_repos, strlen (toplevel_repos)) != 0)
5719 error (1, 0,
5720 "internal error: pathname `%s' doesn't specify file in `%s'",
5721 repository, toplevel_repos);
5722
5723 if (strcmp (repository, toplevel_repos) == 0)
5724 {
5725 update_dir = "";
5726 fullname = xstrdup (vfile);
5727 }
5728 else
5729 {
5730 update_dir = repository + strlen (toplevel_repos) + 1;
5731
5732 fullname = xmalloc (strlen (vfile) + strlen (update_dir) + 10);
5733 strcpy (fullname, update_dir);
5734 strcat (fullname, "/");
5735 strcat (fullname, vfile);
5736 }
5737
5738 send_a_repository ("", repository, update_dir);
5739 if (all_files_binary)
5740 {
5741 vers.options = xmalloc (4); /* strlen("-kb") + 1 */
5742 strcpy (vers.options, "-kb");
5743 }
5744 else
5745 {
5746 vers.options = wrap_rcsoption (vfile, 1);
5747 }
5748 if (vers.options != NULL((void*)0))
5749 {
5750 if (supported_request ("Kopt"))
5751 {
5752 send_to_server ("Kopt ", 0);
5753 send_to_server (vers.options, 0);
5754 send_to_server ("\012", 1);
5755 }
5756 else
5757 error (0, 0,
5758 "warning: ignoring -k options due to server limitations");
5759 }
5760 if (modtime)
5761 {
5762 if (supported_request ("Checkin-time"))
5763 {
5764 struct stat sb;
5765 char *rcsdate;
5766 char netdate[MAXDATELEN50];
5767
5768 if (CVS_STATstat (vfile, &sb) < 0)
5769 error (1, errno(*__errno()), "cannot stat %s", fullname);
5770 rcsdate = date_from_time_t (sb.st_mtimest_mtim.tv_sec);
5771 date_to_internet (netdate, rcsdate);
5772 free (rcsdate);
5773
5774 send_to_server ("Checkin-time ", 0);
5775 send_to_server (netdate, 0);
5776 send_to_server ("\012", 1);
5777 }
5778 else
5779 error (0, 0,
5780 "warning: ignoring -d option due to server limitations");
5781 }
5782 send_modified (vfile, fullname, &vers);
5783 if (vers.options != NULL((void*)0))
5784 free (vers.options);
5785 free (fullname);
5786 return 0;
5787}
5788
5789void
5790client_import_done ()
5791{
5792 if (toplevel_repos == NULL((void*)0))
5793 /*
5794 * This happens if we are not processing any files,
5795 * or for checkouts in directories without any existing stuff
5796 * checked out. The following assignment is correct for the
5797 * latter case; I don't think toplevel_repos matters for the
5798 * former.
5799 */
5800 /* FIXME: "can't happen" now that we call client_import_setup
5801 at the beginning. */
5802 toplevel_repos = xstrdup (current_parsed_root->directory);
5803 send_repository ("", toplevel_repos, ".");
5804}
5805
5806static void
5807notified_a_file (data, ent_list, short_pathname, filename)
5808 char *data;
5809 List *ent_list;
5810 char *short_pathname;
5811 char *filename;
5812{
5813 FILE *fp;
5814 FILE *newf;
5815 size_t line_len = 8192;
5816 char *line = xmalloc (line_len);
5817 char *cp;
5818 int nread;
5819 int nwritten;
5820 char *p;
5821
5822 fp = open_file (CVSADM_NOTIFY"CVS/Notify", "r");
5823 if (get_line (&line, &line_len, fp) < 0)
5824 {
5825 if (feof (fp)(!__isthreaded ? (((fp)->_flags & 0x0020) != 0) : (feof
)(fp))
)
5826 error (0, 0, "cannot read %s: end of file", CVSADM_NOTIFY"CVS/Notify");
5827 else
5828 error (0, errno(*__errno()), "cannot read %s", CVSADM_NOTIFY"CVS/Notify");
5829 goto error_exit;
5830 }
5831 cp = strchr (line, '\t');
5832 if (cp == NULL((void*)0))
5833 {
5834 error (0, 0, "malformed %s file", CVSADM_NOTIFY"CVS/Notify");
5835 goto error_exit;
5836 }
5837 *cp = '\0';
5838 if (strcmp (filename, line + 1) != 0)
5839 {
5840 error (0, 0, "protocol error: notified %s, expected %s", filename,
5841 line + 1);
5842 }
5843
5844 if (get_line (&line, &line_len, fp) < 0)
5845 {
5846 if (feof (fp)(!__isthreaded ? (((fp)->_flags & 0x0020) != 0) : (feof
)(fp))
)
5847 {
5848 free (line);
5849 if (fclose (fp) < 0)
5850 error (0, errno(*__errno()), "cannot close %s", CVSADM_NOTIFY"CVS/Notify");
5851 if ( CVS_UNLINKunlink (CVSADM_NOTIFY"CVS/Notify") < 0)
5852 error (0, errno(*__errno()), "cannot remove %s", CVSADM_NOTIFY"CVS/Notify");
5853 return;
5854 }
5855 else
5856 {
5857 error (0, errno(*__errno()), "cannot read %s", CVSADM_NOTIFY"CVS/Notify");
5858 goto error_exit;
5859 }
5860 }
5861 newf = open_file (CVSADM_NOTIFYTMP"CVS/Notify.tmp", "w");
5862 if (fputs (line, newf) < 0)
5863 {
5864 error (0, errno(*__errno()), "cannot write %s", CVSADM_NOTIFYTMP"CVS/Notify.tmp");
5865 goto error2;
5866 }
5867 while ((nread = fread (line, 1, line_len, fp)) > 0)
5868 {
5869 p = line;
5870 while ((nwritten = fwrite (p, 1, nread, newf)) > 0)
5871 {
5872 nread -= nwritten;
5873 p += nwritten;
5874 }
5875 if (ferror (newf)(!__isthreaded ? (((newf)->_flags & 0x0040) != 0) : (ferror
)(newf))
)
5876 {
5877 error (0, errno(*__errno()), "cannot write %s", CVSADM_NOTIFYTMP"CVS/Notify.tmp");
5878 goto error2;
5879 }
5880 }
5881 if (ferror (fp)(!__isthreaded ? (((fp)->_flags & 0x0040) != 0) : (ferror
)(fp))
)
5882 {
5883 error (0, errno(*__errno()), "cannot read %s", CVSADM_NOTIFY"CVS/Notify");
5884 goto error2;
5885 }
5886 if (fclose (newf) < 0)
5887 {
5888 error (0, errno(*__errno()), "cannot close %s", CVSADM_NOTIFYTMP"CVS/Notify.tmp");
5889 goto error_exit;
5890 }
5891 free (line);
5892 if (fclose (fp) < 0)
5893 {
5894 error (0, errno(*__errno()), "cannot close %s", CVSADM_NOTIFY"CVS/Notify");
5895 return;
5896 }
5897
5898 {
5899 /* In this case, we want rename_file() to ignore noexec. */
5900 int saved_noexec = noexec;
5901 noexec = 0;
5902 rename_file (CVSADM_NOTIFYTMP"CVS/Notify.tmp", CVSADM_NOTIFY"CVS/Notify");
5903 noexec = saved_noexec;
5904 }
5905
5906 return;
5907 error2:
5908 (void) fclose (newf);
5909 error_exit:
5910 free (line);
5911 (void) fclose (fp);
5912}
5913
5914static void
5915handle_notified (args, len)
5916 char *args;
5917 int len;
5918{
5919 call_in_directory (args, notified_a_file, NULL((void*)0));
5920}
5921
5922void
5923client_notify (repository, update_dir, filename, notif_type, val)
5924 char *repository;
5925 char *update_dir;
5926 char *filename;
5927 int notif_type;
5928 char *val;
5929{
5930 char buf[2];
5931
5932 send_a_repository ("", repository, update_dir);
5933 send_to_server ("Notify ", 0);
5934 send_to_server (filename, 0);
5935 send_to_server ("\012", 1);
5936 buf[0] = notif_type;
5937 buf[1] = '\0';
5938 send_to_server (buf, 1);
5939 send_to_server ("\t", 1);
5940 send_to_server (val, 0);
5941}
5942
5943/*
5944 * Send an option with an argument, dealing correctly with newlines in
5945 * the argument. If ARG is NULL, forget the whole thing.
5946 */
5947void
5948option_with_arg (option, arg)
5949 char *option;
5950 char *arg;
5951{
5952 if (arg == NULL((void*)0))
5953 return;
5954
5955 send_to_server ("Argument ", 0);
5956 send_to_server (option, 0);
5957 send_to_server ("\012", 1);
5958
5959 send_arg (arg);
5960}
5961
5962/* Send a date to the server. The input DATE is in RCS format.
5963 The time will be GMT.
5964
5965 We then convert that to the format required in the protocol
5966 (including the "-D" option) and send it. According to
5967 cvsclient.texi, RFC 822/1123 format is preferred. */
5968
5969void
5970client_senddate (date)
5971 const char *date;
5972{
5973 char buf[MAXDATELEN50];
5974
5975 date_to_internet (buf, (char *)date);
5976 option_with_arg ("-D", buf);
5977}
5978
5979void
5980send_init_command ()
5981{
5982 /* This is here because we need the current_parsed_root->directory variable. */
5983 send_to_server ("init ", 0);
5984 send_to_server (current_parsed_root->directory, 0);
5985 send_to_server ("\012", 0);
5986}
5987
5988#endif /* CLIENT_SUPPORT */