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