Bug Summary

File:src/gnu/usr.bin/cvs/src/client.c
Warning:line 1237, column 23
Null pointer passed as 1st argument to string length function

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)
2
Assuming the condition is false
3
Assuming the condition is false
4
Taking false branch
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"))
;
5
Assuming 'reposname' is not equal to null
6
'?' condition is true
1023
1024 reposdirname_absolute = 0;
1025 if (strncmp (reposname, toplevel_repos, strlen (toplevel_repos)) != 0)
7
Assuming the condition is false
8
Taking false branch
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] != '/')
9
Assuming the condition is false
10
Taking false branch
1034 {
1035 reposdirname_absolute = 1;
1036 short_repos = reposname;
1037 }
1038 }
1039 reposdirname = xstrdup (short_repos);
11
Value assigned to 'reposdirname'
1040 p = strrchr (reposdirname, '/');
1041 if (p == NULL((void*)0))
12
Assuming 'p' is not equal to NULL
13
Taking false branch
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))
14
Assuming 'p' is not equal to NULL
15
Taking false branch
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)
16
Assuming 'client_prune_dirs' is 0
17
Taking false branch
1059 add_prune_candidate (dir_name);
1060
1061 filename = strrchr (short_repos, '/');
1062 if (filename == NULL((void*)0))
18
Assuming 'filename' is not equal to NULL
19
Taking false branch
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)
20
Assuming 'last_dir_name' is equal to NULL
1072 || strcmp (last_dir_name, dir_name) != 0)
1073 {
1074 int newdir;
1075
1076 if (strcmp (command_name, "export") != 0)
21
Taking false branch
1077 if (last_entries)
1078 Entries_Close (last_entries);
1079
1080 if (last_dir_name
21.1
'last_dir_name' is null
)
22
Taking false branch
1081 free (last_dir_name);
1082 last_dir_name = dir_name;
1083
1084 if (toplevel_wd == NULL((void*)0))
23
Assuming 'toplevel_wd' is not equal to NULL
24
Taking false branch
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)
25
Assuming the condition is false
26
Taking false branch
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
26.1
'reposdirname_absolute' is 0
1112 && (strcmp (dir_name, ".") == 0)
27
Assuming the condition is false
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)
28
Assuming the condition is true
29
Taking true branch
1134 { 1135 char *dir; 1136 char *dirp; 1137 1138 if (! existence_error (errno)(((*__errno())) == 2))
30
Assuming the condition is true
31
Taking false branch
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)
32
Assuming 'dirp' is non-null
33
Taking true branch
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))
34
Assuming 'rdirp' is equal to NULL
35
Assuming pointer value is null
36
Taking true branch
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)
37
Assuming the condition is false
38
Taking false branch
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))
39
Assuming the condition is false
40
Taking false branch
1220 { 1221 /* It already existed, fine. Just keep going. */ 1222 } 1223 else if (strcmp (command_name, "export") == 0)
41
Assuming the condition is false
42
Taking false branch
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)
43
Null pointer passed as 1st argument to string length function
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
))
; 3695 hostinfo = gethostbyname (hostname); 3696 if (hostinfo == NULL((void*)0)) 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]; 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));
1
Calling 'call_in_directory'
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 */