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