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