Sync usage with man page.
[netbsd-mini2440.git] / external / gpl2 / xcvs / dist / src / client.c
blobceab2b047f510908e275c3d3cb821fef8e31df62
1 /* CVS client-related stuff.
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.
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. */
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif /* HAVE_CONFIG_H */
17 #include "cvs.h"
18 #include "getline.h"
19 #include "edit.h"
20 #include "buffer.h"
21 #include "save-cwd.h"
23 #ifdef CLIENT_SUPPORT
25 # include "log-buffer.h"
26 # include "md5.h"
28 #include "socket-client.h"
29 #include "rsh-client.h"
31 # ifdef HAVE_GSSAPI
32 # include "gssapi-client.h"
33 # endif
35 # ifdef HAVE_KERBEROS
36 # include "kerberos4-client.h"
37 # endif
41 /* Keep track of any paths we are sending for Max-dotdot so that we can verify
42 * that uplevel paths coming back form the server are valid.
44 * FIXME: The correct way to do this is probably provide some sort of virtual
45 * path map on the client side. This would be generic enough to be applied to
46 * absolute paths supplied by the user too.
48 static List *uppaths;
52 static void add_prune_candidate (const char *);
54 /* All the commands. */
55 int add (int argc, char **argv);
56 int admin (int argc, char **argv);
57 int checkout (int argc, char **argv);
58 int commit (int argc, char **argv);
59 int diff (int argc, char **argv);
60 int history (int argc, char **argv);
61 int import (int argc, char **argv);
62 int cvslog (int argc, char **argv);
63 int patch (int argc, char **argv);
64 int release (int argc, char **argv);
65 int cvsremove (int argc, char **argv);
66 int rtag (int argc, char **argv);
67 int status (int argc, char **argv);
68 int tag (int argc, char **argv);
69 int update (int argc, char **argv);
71 static size_t try_read_from_server (char *, size_t);
73 static void auth_server (cvsroot_t *, struct buffer *, struct buffer *,
74 int, int);
78 /* This is the referrer who referred us to a primary, or write server, using
79 * the "Redirect" request.
81 static cvsroot_t *client_referrer;
83 /* We need to keep track of the list of directories we've sent to the
84 server. This list, along with the current CVSROOT, will help us
85 decide which command-line arguments to send. */
86 List *dirs_sent_to_server;
87 static int
88 is_arg_a_parent_or_listed_dir (Node *n, void *d)
90 char *directory = n->key; /* name of the dir sent to server */
91 char *this_argv_elem = d; /* this argv element */
93 /* Say we should send this argument if the argument matches the
94 beginning of a directory name sent to the server. This way,
95 the server will know to start at the top of that directory
96 hierarchy and descend. */
98 if (!strncmp (directory, this_argv_elem, strlen (this_argv_elem)))
99 return 1;
101 return 0;
106 /* Return nonzero if this argument should not be sent to the
107 server. */
108 static int
109 arg_should_not_be_sent_to_server (char *arg)
111 /* Decide if we should send this directory name to the server. We
112 should always send argv[i] if:
114 1) the list of directories sent to the server is empty (as it
115 will be for checkout, etc.).
117 2) the argument is "."
119 3) the argument is a file in the cwd and the cwd is checked out
120 from the current root
122 4) the argument lies within one of the paths in
123 dirs_sent_to_server.
127 if (list_isempty (dirs_sent_to_server))
128 return 0; /* always send it */
130 if (!strcmp (arg, "."))
131 return 0; /* always send it */
133 /* We should send arg if it is one of the directories sent to the
134 server or the parent of one; this tells the server to descend
135 the hierarchy starting at this level. */
136 if (isdir (arg))
138 if (walklist (dirs_sent_to_server, is_arg_a_parent_or_listed_dir, arg))
139 return 0;
141 /* If arg wasn't a parent, we don't know anything about it (we
142 would have seen something related to it during the
143 send_files phase). Don't send it. */
144 return 1;
147 /* Try to decide whether we should send arg to the server by
148 checking the contents of the corresponding CVSADM directory. */
150 char *t, *root_string;
151 cvsroot_t *this_root = NULL;
153 /* Calculate "dirname arg" */
154 for (t = arg + strlen (arg) - 1; t >= arg; t--)
156 if (ISSLASH (*t))
157 break;
160 /* Now we're either poiting to the beginning of the
161 string, or we found a path separator. */
162 if (t >= arg)
164 /* Found a path separator. */
165 char c = *t;
166 *t = '\0';
168 /* First, check to see if we sent this directory to the
169 server, because it takes less time than actually
170 opening the stuff in the CVSADM directory. */
171 if (walklist (dirs_sent_to_server, is_arg_a_parent_or_listed_dir,
172 arg))
174 *t = c; /* make sure to un-truncate the arg */
175 return 0;
178 /* Since we didn't find it in the list, check the CVSADM
179 files on disk. */
180 this_root = Name_Root (arg, NULL);
181 root_string = this_root->original;
182 *t = c;
184 else
186 /* We're at the beginning of the string. Look at the
187 CVSADM files in cwd. */
188 if (CVSroot_cmdline)
189 root_string = CVSroot_cmdline;
190 else
192 this_root = Name_Root (NULL, NULL);
193 root_string = this_root->original;
197 /* Now check the value for root. */
198 if (root_string && current_parsed_root
199 && strcmp (root_string, original_parsed_root->original))
201 /* Don't send this, since the CVSROOTs don't match. */
202 return 1;
206 /* OK, let's send it. */
207 return 0;
209 #endif /* CLIENT_SUPPORT */
213 #if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
215 /* Shared with server. */
218 * Return a malloc'd, '\0'-terminated string
219 * corresponding to the mode in SB.
221 char *
222 mode_to_string (mode_t mode)
224 char u[4], g[4], o[4];
225 int i;
227 i = 0;
228 if (mode & S_IRUSR) u[i++] = 'r';
229 if (mode & S_IWUSR) u[i++] = 'w';
230 if (mode & S_IXUSR) u[i++] = 'x';
231 u[i] = '\0';
233 i = 0;
234 if (mode & S_IRGRP) g[i++] = 'r';
235 if (mode & S_IWGRP) g[i++] = 'w';
236 if (mode & S_IXGRP) g[i++] = 'x';
237 g[i] = '\0';
239 i = 0;
240 if (mode & S_IROTH) o[i++] = 'r';
241 if (mode & S_IWOTH) o[i++] = 'w';
242 if (mode & S_IXOTH) o[i++] = 'x';
243 o[i] = '\0';
245 return Xasprintf ("u=%s,g=%s,o=%s", u, g, o);
251 * Change mode of FILENAME to MODE_STRING.
252 * Returns 0 for success or errno code.
253 * If RESPECT_UMASK is set, then honor the umask.
256 change_mode (const char *filename, const char *mode_string, int respect_umask)
258 #ifdef CHMOD_BROKEN
259 char *p;
260 int writeable = 0;
262 /* We can only distinguish between
263 1) readable
264 2) writeable
265 3) Picasso's "Blue Period"
266 We handle the first two. */
267 p = mode_string;
268 while (*p != '\0')
270 if ((p[0] == 'u' || p[0] == 'g' || p[0] == 'o') && p[1] == '=')
272 char *q = p + 2;
273 while (*q != ',' && *q != '\0')
275 if (*q == 'w')
276 writeable = 1;
277 ++q;
280 /* Skip to the next field. */
281 while (*p != ',' && *p != '\0')
282 ++p;
283 if (*p == ',')
284 ++p;
287 /* xchmod honors the umask for us. In the !respect_umask case, we
288 don't try to cope with it (probably to handle that well, the server
289 needs to deal with modes in data structures, rather than via the
290 modes in temporary files). */
291 xchmod (filename, writeable);
292 return 0;
294 #else /* ! CHMOD_BROKEN */
296 const char *p;
297 mode_t mode = 0;
298 mode_t oumask;
300 p = mode_string;
301 while (*p != '\0')
303 if ((p[0] == 'u' || p[0] == 'g' || p[0] == 'o') && p[1] == '=')
305 int can_read = 0, can_write = 0, can_execute = 0;
306 const char *q = p + 2;
307 while (*q != ',' && *q != '\0')
309 if (*q == 'r')
310 can_read = 1;
311 else if (*q == 'w')
312 can_write = 1;
313 else if (*q == 'x')
314 can_execute = 1;
315 ++q;
317 if (p[0] == 'u')
319 if (can_read)
320 mode |= S_IRUSR;
321 if (can_write)
322 mode |= S_IWUSR;
323 if (can_execute)
324 mode |= S_IXUSR;
326 else if (p[0] == 'g')
328 if (can_read)
329 mode |= S_IRGRP;
330 if (can_write)
331 mode |= S_IWGRP;
332 if (can_execute)
333 mode |= S_IXGRP;
335 else if (p[0] == 'o')
337 if (can_read)
338 mode |= S_IROTH;
339 if (can_write)
340 mode |= S_IWOTH;
341 if (can_execute)
342 mode |= S_IXOTH;
345 /* Skip to the next field. */
346 while (*p != ',' && *p != '\0')
347 ++p;
348 if (*p == ',')
349 ++p;
352 if (respect_umask)
354 oumask = umask (0);
355 (void) umask (oumask);
356 mode &= ~oumask;
359 if (chmod (filename, mode) < 0)
360 return errno;
361 return 0;
362 #endif /* ! CHMOD_BROKEN */
364 #endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
368 #ifdef CLIENT_SUPPORT
369 int client_prune_dirs;
371 static List *ignlist = NULL;
373 /* Buffer to write to the server. */
374 static struct buffer *global_to_server;
376 /* Buffer used to read from the server. */
377 static struct buffer *global_from_server;
382 * Read a line from the server. Result does not include the terminating \n.
384 * Space for the result is malloc'd and should be freed by the caller.
386 * Returns number of bytes read.
388 static size_t
389 read_line_via (struct buffer *via_from_buffer, struct buffer *via_to_buffer,
390 char **resultp)
392 int status;
393 char *result;
394 size_t len;
396 status = buf_flush (via_to_buffer, 1);
397 if (status != 0)
398 error (1, status, "writing to server");
400 status = buf_read_line (via_from_buffer, &result, &len);
401 if (status != 0)
403 if (status == -1)
404 error (1, 0,
405 "end of file from server (consult above messages if any)");
406 else if (status == -2)
407 error (1, 0, "out of memory");
408 else
409 error (1, status, "reading from server");
412 if (resultp)
413 *resultp = result;
414 else
415 free (result);
417 return len;
422 static size_t
423 read_line (char **resultp)
425 return read_line_via (global_from_server, global_to_server, resultp);
427 #endif /* CLIENT_SUPPORT */
431 #if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
433 * Zero if compression isn't supported or requested; non-zero to indicate
434 * a compression level to request from gzip.
436 int gzip_level;
439 * Level of compression to use when running gzip on a single file.
441 int file_gzip_level;
443 #endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
445 #ifdef CLIENT_SUPPORT
447 /* Whether the server asked us to force compression. */
448 static bool force_gzip;
451 * The Repository for the top level of this command (not necessarily
452 * the CVSROOT, just the current directory at the time we do it).
454 static char *toplevel_repos;
456 /* Working directory when we first started. Note: we could speed things
457 up on some systems by using savecwd.h here instead of just always
458 storing a name. */
459 char *toplevel_wd;
463 static void
464 handle_ok (char *args, size_t len)
466 return;
471 static void
472 handle_error (char *args, size_t len)
474 int something_printed;
477 * First there is a symbolic error code followed by a space, which
478 * we ignore.
480 char *p = strchr (args, ' ');
481 if (!p)
483 error (0, 0, "invalid data from cvs server");
484 return;
486 ++p;
488 /* Next we print the text of the message from the server. We
489 probably should be prefixing it with "server error" or some
490 such, because if it is something like "Out of memory", the
491 current behavior doesn't say which machine is out of
492 memory. */
494 len -= p - args;
495 something_printed = 0;
496 for (; len > 0; --len)
498 something_printed = 1;
499 putc (*p++, stderr);
501 if (something_printed)
502 putc ('\n', stderr);
507 static void
508 handle_valid_requests (char *args, size_t len)
510 char *p = args;
511 char *q;
512 struct request *rq;
515 q = strchr (p, ' ');
516 if (q)
517 *q++ = '\0';
518 for (rq = requests; rq->name; ++rq)
520 if (!strcmp (rq->name, p))
521 break;
523 if (!rq->name)
525 * It is a request we have never heard of (and thus never
526 * will want to use). So don't worry about it.
529 else
531 if (rq->flags & RQ_ENABLEME)
534 * Server wants to know if we have this, to enable the
535 * feature.
537 send_to_server (rq->name, 0);
538 send_to_server ("\012", 0);
540 else
541 rq->flags |= RQ_SUPPORTED;
543 p = q;
544 } while (q);
545 for (rq = requests; rq->name; ++rq)
547 if ((rq->flags & RQ_SUPPORTED)
548 || (rq->flags & RQ_ENABLEME))
549 continue;
550 if (rq->flags & RQ_ESSENTIAL)
551 error (1, 0, "request `%s' not supported by server", rq->name);
555 static void
556 handle_force_gzip (char *args, size_t len)
558 force_gzip = true;
563 /* Has the server told us its name since the last redirect?
565 static bool referred_since_last_redirect = false;
566 static bool free_client_referrer = false;
570 static void
571 handle_referrer (char *args, size_t len)
573 TRACE (TRACE_FUNCTION, "handle_referrer (%s)", args);
574 client_referrer = parse_cvsroot (args);
575 referred_since_last_redirect = true;
576 free_client_referrer = true;
581 /* Redirect our connection to a different server and start over.
583 * GLOBALS
584 * current_parsed_root The CVSROOT being accessed.
585 * client_referrer Used to track the server which referred us to a
586 * new server. Can be supplied by the referring
587 * server.
588 * free_client_referrer Used to track whether the client_referrer needs
589 * to be freed before changing it.
590 * referred_since_last_redirect
591 * Tracks whether the currect server told us how
592 * to refer to it.
594 * OUTPUTS
595 * current_parsed_root Updated to point to the new CVSROOT.
596 * referred_since_last_redirect
597 * Always cleared.
598 * client_referrer Set automatically to current_parsed_root if
599 * the current server did not give us a name to
600 * refer to it by.
601 * free_client_referrer Reset when necessary.
603 static void
604 handle_redirect (char *args, size_t len)
606 static List *redirects = NULL;
608 TRACE (TRACE_FUNCTION, "handle_redirect (%s)", args);
610 if (redirects && findnode (redirects, args))
611 error (1, 0, "`Redirect' loop detected. Server misconfiguration?");
612 else
614 if (!redirects) redirects = getlist();
615 push_string (redirects, args);
618 if (referred_since_last_redirect)
619 referred_since_last_redirect = false;
620 else
622 if (free_client_referrer) free (client_referrer);
623 client_referrer = current_parsed_root;
624 free_client_referrer = false;
627 current_parsed_root = parse_cvsroot (args);
629 /* We deliberately do not set ORIGINAL_PARSED_ROOT here.
630 * ORIGINAL_PARSED_ROOT is used by the client to determine the current root
631 * being processed for the purpose of looking it up in lists and such, even
632 * after a redirect.
634 * FIXME
635 * CURRENT_PARSED_ROOT should not be reset by this function. Redirects
636 * should be "added" to it. The REDIRECTS list should also be replaced
637 * by this new CURRENT_PARSED_ROOT element. This way, if, for instance,
638 * a multi-root workspace had two secondaries pointing to the same
639 * primary, then the client would not report a looping error.
641 * There is also a potential memory leak above and storing new roots as
642 * part of the original could help avoid it fairly elegantly.
644 if (!current_parsed_root)
645 error (1, 0, "Server requested redirect to invalid root: `%s'",
646 args);
652 * This is a proc for walklist(). It inverts the error return premise of
653 * walklist.
655 * RETURNS
656 * True If this path is prefixed by one of the paths in walklist and
657 * does not step above the prefix path.
658 * False Otherwise.
660 static
661 int path_list_prefixed (Node *p, void *closure)
663 const char *questionable = closure;
664 const char *prefix = p->key;
665 if (strncmp (prefix, questionable, strlen (prefix))) return 0;
666 questionable += strlen (prefix);
667 while (ISSLASH (*questionable)) questionable++;
668 if (*questionable == '\0') return 1;
669 return pathname_levels (questionable);
675 * Need to validate the client pathname. Disallowed paths include:
677 * 1. Absolute paths.
678 * 2. Pathnames that do not reference a specifically requested update
679 * directory.
681 * In case 2, we actually only check that the directory is under the uppermost
682 * directories mentioned on the command line.
684 * RETURNS
685 * True If the path is valid.
686 * False Otherwise.
688 static
689 int is_valid_client_path (const char *pathname)
691 /* 1. Absolute paths. */
692 if (ISABSOLUTE (pathname)) return 0;
693 /* 2. No up-references in path. */
694 if (pathname_levels (pathname) == 0) return 1;
695 /* 2. No Max-dotdot paths registered. */
696 if (!uppaths) return 0;
698 return walklist (uppaths, path_list_prefixed, (void *)pathname);
704 * Do all the processing for PATHNAME, where pathname consists of the
705 * repository and the filename. The parameters we pass to FUNC are:
706 * DATA is just the DATA parameter which was passed to
707 * call_in_directory; ENT_LIST is a pointer to an entries list (which
708 * we manage the storage for); SHORT_PATHNAME is the pathname of the
709 * file relative to the (overall) directory in which the command is
710 * taking place; and FILENAME is the filename portion only of
711 * SHORT_PATHNAME. When we call FUNC, the curent directory points to
712 * the directory portion of SHORT_PATHNAME. */
713 static void
714 call_in_directory (const char *pathname,
715 void (*func) (void *, List *, const char *, const char *),
716 void *data)
718 /* This variable holds the result of Entries_Open. */
719 List *last_entries = NULL;
720 char *dir_name;
721 char *filename;
722 /* This is what we get when we hook up the directory (working directory
723 name) from PATHNAME with the filename from REPOSNAME. For example:
724 pathname: ccvs/src/
725 reposname: /u/src/master/ccvs/foo/ChangeLog
726 short_pathname: ccvs/src/ChangeLog
728 char *short_pathname;
729 char *p;
732 * Do the whole descent in parallel for the repositories, so we
733 * know what to put in CVS/Repository files. I'm not sure the
734 * full hair is necessary since the server does a similar
735 * computation; I suspect that we only end up creating one
736 * directory at a time anyway.
738 * Also note that we must *only* worry about this stuff when we
739 * are creating directories; `cvs co foo/bar; cd foo/bar; cvs co
740 * CVSROOT; cvs update' is legitimate, but in this case
741 * foo/bar/CVSROOT/CVS/Repository is not a subdirectory of
742 * foo/bar/CVS/Repository.
744 char *reposname;
745 char *short_repos;
746 char *reposdirname;
747 char *rdirp;
748 int reposdirname_absolute;
749 int newdir = 0;
751 assert (pathname);
753 reposname = NULL;
754 read_line (&reposname);
755 assert (reposname);
757 reposdirname_absolute = 0;
758 if (strncmp (reposname, toplevel_repos, strlen (toplevel_repos)))
760 reposdirname_absolute = 1;
761 short_repos = reposname;
763 else
765 short_repos = reposname + strlen (toplevel_repos) + 1;
766 if (short_repos[-1] != '/')
768 reposdirname_absolute = 1;
769 short_repos = reposname;
773 /* Now that we have SHORT_REPOS, we can calculate the path to the file we
774 * are being requested to operate on.
776 filename = strrchr (short_repos, '/');
777 if (!filename)
778 filename = short_repos;
779 else
780 ++filename;
782 short_pathname = xmalloc (strlen (pathname) + strlen (filename) + 5);
783 strcpy (short_pathname, pathname);
784 strcat (short_pathname, filename);
786 /* Now that we know the path to the file we were requested to operate on,
787 * we can verify that it is valid.
789 * For security reasons, if SHORT_PATHNAME is absolute or attempts to
790 * ascend outside of the current sanbbox, we abort. The server should not
791 * send us anything but relative paths which remain inside the sandbox
792 * here. Anything less means a trojan CVS server could create and edit
793 * arbitrary files on the client.
795 if (!is_valid_client_path (short_pathname))
797 error (0, 0,
798 "Server attempted to update a file via an invalid pathname:");
799 error (1, 0, "`%s'.", short_pathname);
802 reposdirname = xstrdup (short_repos);
803 p = strrchr (reposdirname, '/');
804 if (!p)
806 reposdirname = xrealloc (reposdirname, 2);
807 reposdirname[0] = '.'; reposdirname[1] = '\0';
809 else
810 *p = '\0';
812 dir_name = xstrdup (pathname);
813 p = strrchr (dir_name, '/');
814 if (!p)
816 dir_name = xrealloc (dir_name, 2);
817 dir_name[0] = '.'; dir_name[1] = '\0';
819 else
820 *p = '\0';
821 if (client_prune_dirs)
822 add_prune_candidate (dir_name);
824 if (!toplevel_wd)
826 toplevel_wd = xgetcwd ();
827 if (!toplevel_wd)
828 error (1, errno, "could not get working directory");
831 if (CVS_CHDIR (toplevel_wd) < 0)
832 error (1, errno, "could not chdir to %s", toplevel_wd);
834 /* Create the CVS directory at the top level if needed. The
835 isdir seems like an unneeded system call, but it *does*
836 need to be called both if the CVS_CHDIR below succeeds
837 (e.g. "cvs co .") or if it fails (e.g. basicb-1a in
838 testsuite). We only need to do this for the "." case,
839 since the server takes care of forcing this directory to be
840 created in all other cases. If we don't create CVSADM
841 here, the call to Entries_Open below will fail. FIXME:
842 perhaps this means that we should change our algorithm
843 below that calls Create_Admin instead of having this code
844 here? */
845 if (/* I think the reposdirname_absolute case has to do with
846 things like "cvs update /foo/bar". In any event, the
847 code below which tries to put toplevel_repos into
848 CVS/Repository is almost surely unsuited to
849 the reposdirname_absolute case. */
850 !reposdirname_absolute
851 && !strcmp (dir_name, ".")
852 && ! isdir (CVSADM))
854 char *repo;
855 char *r;
857 newdir = 1;
859 /* If toplevel_repos doesn't have at least one character, then the
860 * reference to r[-1] below could be out of bounds.
862 assert (*toplevel_repos);
864 repo = xmalloc (strlen (toplevel_repos)
865 + 10);
866 strcpy (repo, toplevel_repos);
867 r = repo + strlen (repo);
868 if (r[-1] != '.' || r[-2] != '/')
869 strcpy (r, "/.");
871 Create_Admin (".", ".", repo, NULL, NULL, 0, 1, 1);
873 free (repo);
876 if (CVS_CHDIR (dir_name) < 0)
878 char *dir;
879 char *dirp;
881 if (! existence_error (errno))
882 error (1, errno, "could not chdir to %s", dir_name);
884 /* Directory does not exist, we need to create it. */
885 newdir = 1;
887 /* Provided we are willing to assume that directories get
888 created one at a time, we could simplify this a lot.
889 Do note that one aspect still would need to walk the
890 dir_name path: the checking for "fncmp (dir, CVSADM)". */
892 dir = xmalloc (strlen (dir_name) + 1);
893 dirp = dir_name;
894 rdirp = reposdirname;
896 /* This algorithm makes nested directories one at a time
897 and create CVS administration files in them. For
898 example, we're checking out foo/bar/baz from the
899 repository:
901 1) create foo, point CVS/Repository to <root>/foo
902 2) .. foo/bar .. <root>/foo/bar
903 3) .. foo/bar/baz .. <root>/foo/bar/baz
905 As you can see, we're just stepping along DIR_NAME (with
906 DIRP) and REPOSDIRNAME (with RDIRP) respectively.
908 We need to be careful when we are checking out a
909 module, however, since DIR_NAME and REPOSDIRNAME are not
910 going to be the same. Since modules will not have any
911 slashes in their names, we should watch the output of
912 STRCHR to decide whether or not we should use STRCHR on
913 the RDIRP. That is, if we're down to a module name,
914 don't keep picking apart the repository directory name. */
918 dirp = strchr (dirp, '/');
919 if (dirp)
921 strncpy (dir, dir_name, dirp - dir_name);
922 dir[dirp - dir_name] = '\0';
923 /* Skip the slash. */
924 ++dirp;
925 if (!rdirp)
926 /* This just means that the repository string has
927 fewer components than the dir_name string. But
928 that is OK (e.g. see modules3-8 in testsuite). */
930 else
931 rdirp = strchr (rdirp, '/');
933 else
935 /* If there are no more slashes in the dir name,
936 we're down to the most nested directory -OR- to
937 the name of a module. In the first case, we
938 should be down to a DIRP that has no slashes,
939 so it won't help/hurt to do another STRCHR call
940 on DIRP. It will definitely hurt, however, if
941 we're down to a module name, since a module
942 name can point to a nested directory (that is,
943 DIRP will still have slashes in it. Therefore,
944 we should set it to NULL so the routine below
945 copies the contents of REMOTEDIRNAME onto the
946 root repository directory (does this if rdirp
947 is set to NULL, because we used to do an extra
948 STRCHR call here). */
950 rdirp = NULL;
951 strcpy (dir, dir_name);
954 if (fncmp (dir, CVSADM) == 0)
956 error (0, 0, "cannot create a directory named %s", dir);
957 error (0, 0, "because CVS uses \"%s\" for its own uses",
958 CVSADM);
959 error (1, 0, "rename the directory and try again");
962 if (mkdir_if_needed (dir))
964 /* It already existed, fine. Just keep going. */
966 else if (!strcmp (cvs_cmd_name, "export"))
967 /* Don't create CVSADM directories if this is export. */
969 else
972 * Put repository in CVS/Repository. For historical
973 * (pre-CVS/Root) reasons, this is an absolute pathname,
974 * but what really matters is the part of it which is
975 * relative to cvsroot.
977 char *repo;
978 char *r, *b;
980 repo = xmalloc (strlen (reposdirname)
981 + strlen (toplevel_repos)
982 + 80);
983 if (reposdirname_absolute)
984 r = repo;
985 else
987 strcpy (repo, toplevel_repos);
988 strcat (repo, "/");
989 r = repo + strlen (repo);
992 if (rdirp)
994 /* See comment near start of function; the only
995 way that the server can put the right thing
996 in each CVS/Repository file is to create the
997 directories one at a time. I think that the
998 CVS server has been doing this all along. */
999 error (0, 0, "\
1000 warning: server is not creating directories one at a time");
1001 strncpy (r, reposdirname, rdirp - reposdirname);
1002 r[rdirp - reposdirname] = '\0';
1004 else
1005 strcpy (r, reposdirname);
1007 Create_Admin (dir, dir, repo, NULL, NULL, 0, 0, 1);
1008 free (repo);
1010 b = strrchr (dir, '/');
1011 if (!b)
1012 Subdir_Register (NULL, NULL, dir);
1013 else
1015 *b = '\0';
1016 Subdir_Register (NULL, dir, b + 1);
1017 *b = '/';
1021 if (rdirp)
1023 /* Skip the slash. */
1024 ++rdirp;
1027 } while (dirp);
1028 free (dir);
1029 /* Now it better work. */
1030 if (CVS_CHDIR (dir_name) < 0)
1031 error (1, errno, "could not chdir to %s", dir_name);
1033 else if (!strcmp (cvs_cmd_name, "export"))
1034 /* Don't create CVSADM directories if this is export. */
1036 else if (!isdir (CVSADM))
1039 * Put repository in CVS/Repository. For historical
1040 * (pre-CVS/Root) reasons, this is an absolute pathname,
1041 * but what really matters is the part of it which is
1042 * relative to cvsroot.
1044 char *repo;
1046 if (reposdirname_absolute)
1047 repo = reposdirname;
1048 else
1049 repo = Xasprintf ("%s/%s", toplevel_repos, reposdirname);
1051 Create_Admin (".", ".", repo, NULL, NULL, 0, 1, 1);
1052 if (repo != reposdirname)
1053 free (repo);
1056 if (strcmp (cvs_cmd_name, "export"))
1058 last_entries = Entries_Open (0, dir_name);
1060 /* If this is a newly created directory, we will record
1061 all subdirectory information, so call Subdirs_Known in
1062 case there are no subdirectories. If this is not a
1063 newly created directory, it may be an old working
1064 directory from before we recorded subdirectory
1065 information in the Entries file. We force a search for
1066 all subdirectories now, to make sure our subdirectory
1067 information is up to date. If the Entries file does
1068 record subdirectory information, then this call only
1069 does list manipulation. */
1070 if (newdir)
1071 Subdirs_Known (last_entries);
1072 else
1074 List *dirlist;
1076 dirlist = Find_Directories (NULL, W_LOCAL, last_entries);
1077 dellist (&dirlist);
1080 free (reposdirname);
1081 (*func) (data, last_entries, short_pathname, filename);
1082 if (last_entries)
1083 Entries_Close (last_entries);
1084 free (dir_name);
1085 free (short_pathname);
1086 free (reposname);
1091 static void
1092 copy_a_file (void *data, List *ent_list, const char *short_pathname,
1093 const char *filename)
1095 char *newname;
1097 read_line (&newname);
1099 #ifdef USE_VMS_FILENAMES
1101 /* Mogrify the filename so VMS is happy with it. */
1102 char *p;
1103 for(p = newname; *p; p++)
1104 if(*p == '.' || *p == '#') *p = '_';
1106 #endif
1107 /* cvsclient.texi has said for a long time that newname must be in the
1108 same directory. Wouldn't want a malicious or buggy server overwriting
1109 ~/.profile, /etc/passwd, or anything like that. */
1110 if (last_component (newname) != newname)
1111 error (1, 0, "protocol error: Copy-file tried to specify directory");
1113 if (unlink_file (newname) && !existence_error (errno))
1114 error (0, errno, "unable to remove %s", newname);
1115 copy_file (filename, newname);
1116 free (newname);
1121 static void
1122 handle_copy_file (char *args, size_t len)
1124 call_in_directory (args, copy_a_file, NULL);
1129 /* Read from the server the count for the length of a file, then read
1130 the contents of that file and write them to FILENAME. FULLNAME is
1131 the name of the file for use in error messages. FIXME-someday:
1132 extend this to deal with compressed files and make update_entries
1133 use it. On error, gives a fatal error. */
1134 static void
1135 read_counted_file (const char *filename, const char *fullname)
1137 char *size_string;
1138 size_t size;
1139 char *buf;
1141 /* Pointers in buf to the place to put data which will be read,
1142 and the data which needs to be written, respectively. */
1143 char *pread;
1144 char *pwrite;
1145 /* Number of bytes left to read and number of bytes in buf waiting to
1146 be written, respectively. */
1147 size_t nread;
1148 size_t nwrite;
1150 FILE *fp;
1152 read_line (&size_string);
1153 if (size_string[0] == 'z')
1154 error (1, 0, "\
1155 protocol error: compressed files not supported for that operation");
1156 /* FIXME: should be doing more error checking, probably. Like using
1157 strtoul and making sure we used up the whole line. */
1158 size = atoi (size_string);
1159 free (size_string);
1161 /* A more sophisticated implementation would use only a limited amount
1162 of buffer space (8K perhaps), and read that much at a time. We allocate
1163 a buffer for the whole file only to make it easy to keep track what
1164 needs to be read and written. */
1165 buf = xmalloc (size);
1167 /* FIXME-someday: caller should pass in a flag saying whether it
1168 is binary or not. I haven't carefully looked into whether
1169 CVS/Template files should use local text file conventions or
1170 not. */
1171 fp = CVS_FOPEN (filename, "wb");
1172 if (!fp)
1173 error (1, errno, "cannot write %s", fullname);
1174 nread = size;
1175 nwrite = 0;
1176 pread = buf;
1177 pwrite = buf;
1178 while (nread > 0 || nwrite > 0)
1180 size_t n;
1182 if (nread > 0)
1184 n = try_read_from_server (pread, nread);
1185 nread -= n;
1186 pread += n;
1187 nwrite += n;
1190 if (nwrite > 0)
1192 n = fwrite (pwrite, sizeof *pwrite, nwrite, fp);
1193 if (ferror (fp))
1194 error (1, errno, "cannot write %s", fullname);
1195 nwrite -= n;
1196 pwrite += n;
1199 free (buf);
1200 if (fclose (fp) < 0)
1201 error (1, errno, "cannot close %s", fullname);
1206 /* OK, we want to swallow the "U foo.c" response and then output it only
1207 if we can update the file. In the future we probably want some more
1208 systematic approach to parsing tagged text, but for now we keep it
1209 ad hoc. "Why," I hear you cry, "do we not just look at the
1210 Update-existing and Created responses?" That is an excellent question,
1211 and the answer is roughly conservatism/laziness--I haven't read through
1212 update.c enough to figure out the exact correspondence or lack thereof
1213 between those responses and a "U foo.c" line (note that Merged, from
1214 join_file, can be either "C foo" or "U foo" depending on the context). */
1215 /* Nonzero if we have seen +updated and not -updated. */
1216 static int updated_seen;
1217 /* Filename from an "fname" tagged response within +updated/-updated. */
1218 static char *updated_fname;
1220 /* This struct is used to hold data when reading the +importmergecmd
1221 and -importmergecmd tags. We put the variables in a struct only
1222 for namespace issues. FIXME: As noted above, we need to develop a
1223 more systematic approach. */
1224 static struct
1226 /* Nonzero if we have seen +importmergecmd and not -importmergecmd. */
1227 int seen;
1228 /* Number of conflicts, from a "conflicts" tagged response. */
1229 int conflicts;
1230 /* First merge tag, from a "mergetag1" tagged response. */
1231 char *mergetag1;
1232 /* Second merge tag, from a "mergetag2" tagged response. */
1233 char *mergetag2;
1234 /* Repository, from a "repository" tagged response. */
1235 char *repository;
1236 } importmergecmd;
1238 /* Nonzero if we should arrange to return with a failure exit status. */
1239 static bool failure_exit;
1243 * The time stamp of the last file we registered.
1245 static time_t last_register_time;
1250 * The Checksum response gives the checksum for the file transferred
1251 * over by the next Updated, Merged or Patch response. We just store
1252 * it here, and then check it in update_entries.
1254 static int stored_checksum_valid;
1255 static unsigned char stored_checksum[16];
1256 static void
1257 handle_checksum (char *args, size_t len)
1259 char *s;
1260 char buf[3];
1261 int i;
1263 if (stored_checksum_valid)
1264 error (1, 0, "Checksum received before last one was used");
1266 s = args;
1267 buf[2] = '\0';
1268 for (i = 0; i < 16; i++)
1270 char *bufend;
1272 buf[0] = *s++;
1273 buf[1] = *s++;
1274 stored_checksum[i] = (char) strtol (buf, &bufend, 16);
1275 if (bufend != buf + 2)
1276 break;
1279 if (i < 16 || *s != '\0')
1280 error (1, 0, "Invalid Checksum response: `%s'", args);
1282 stored_checksum_valid = 1;
1287 /* Mode that we got in a "Mode" response (malloc'd), or NULL if none. */
1288 static char *stored_mode;
1289 static void
1290 handle_mode (char *args, size_t len)
1292 if (stored_mode)
1293 error (1, 0, "protocol error: duplicate Mode");
1294 stored_mode = xstrdup (args);
1299 /* Nonzero if time was specified in Mod-time. */
1300 static int stored_modtime_valid;
1301 /* Time specified in Mod-time. */
1302 static time_t stored_modtime;
1303 static void
1304 handle_mod_time (char *args, size_t len)
1306 struct timespec newtime;
1307 if (stored_modtime_valid)
1308 error (0, 0, "protocol error: duplicate Mod-time");
1309 if (get_date (&newtime, args, NULL))
1311 /* Truncate nanoseconds. */
1312 stored_modtime = newtime.tv_sec;
1313 stored_modtime_valid = 1;
1315 else
1316 error (0, 0, "protocol error: cannot parse date %s", args);
1322 * If we receive a patch, but the patch program fails to apply it, we
1323 * want to request the original file. We keep a list of files whose
1324 * patches have failed.
1327 char **failed_patches;
1328 int failed_patches_count;
1330 struct update_entries_data
1332 enum {
1334 * We are just getting an Entries line; the local file is
1335 * correct.
1337 UPDATE_ENTRIES_CHECKIN,
1338 /* We are getting the file contents as well. */
1339 UPDATE_ENTRIES_UPDATE,
1341 * We are getting a patch against the existing local file, not
1342 * an entire new file.
1344 UPDATE_ENTRIES_PATCH,
1346 * We are getting an RCS change text (diff -n output) against
1347 * the existing local file, not an entire new file.
1349 UPDATE_ENTRIES_RCS_DIFF
1350 } contents;
1352 enum {
1353 /* We are replacing an existing file. */
1354 UPDATE_ENTRIES_EXISTING,
1355 /* We are creating a new file. */
1356 UPDATE_ENTRIES_NEW,
1357 /* We don't know whether it is existing or new. */
1358 UPDATE_ENTRIES_EXISTING_OR_NEW
1359 } existp;
1362 * String to put in the timestamp field or NULL to use the timestamp
1363 * of the file.
1365 char *timestamp;
1370 /* Update the Entries line for this file. */
1371 static void
1372 update_entries (void *data_arg, List *ent_list, const char *short_pathname,
1373 const char *filename)
1375 char *entries_line;
1376 struct update_entries_data *data = data_arg;
1378 char *cp;
1379 char *user;
1380 char *vn;
1381 /* Timestamp field. Always empty according to the protocol. */
1382 char *ts;
1383 char *options = NULL;
1384 char *tag = NULL;
1385 char *date = NULL;
1386 char *tag_or_date;
1387 char *scratch_entries = NULL;
1388 int bin;
1390 #ifdef UTIME_EXPECTS_WRITABLE
1391 int change_it_back = 0;
1392 #endif
1394 read_line (&entries_line);
1397 * Parse the entries line.
1399 scratch_entries = xstrdup (entries_line);
1401 if (scratch_entries[0] != '/')
1402 error (1, 0, "bad entries line `%s' from server", entries_line);
1403 user = scratch_entries + 1;
1404 if (!(cp = strchr (user, '/')))
1405 error (1, 0, "bad entries line `%s' from server", entries_line);
1406 *cp++ = '\0';
1407 vn = cp;
1408 if (!(cp = strchr (vn, '/')))
1409 error (1, 0, "bad entries line `%s' from server", entries_line);
1410 *cp++ = '\0';
1412 ts = cp;
1413 if (!(cp = strchr (ts, '/')))
1414 error (1, 0, "bad entries line `%s' from server", entries_line);
1415 *cp++ = '\0';
1416 options = cp;
1417 if (!(cp = strchr (options, '/')))
1418 error (1, 0, "bad entries line `%s' from server", entries_line);
1419 *cp++ = '\0';
1420 tag_or_date = cp;
1422 /* If a slash ends the tag_or_date, ignore everything after it. */
1423 cp = strchr (tag_or_date, '/');
1424 if (cp)
1425 *cp = '\0';
1426 if (*tag_or_date == 'T')
1427 tag = tag_or_date + 1;
1428 else if (*tag_or_date == 'D')
1429 date = tag_or_date + 1;
1431 /* Done parsing the entries line. */
1433 if (data->contents == UPDATE_ENTRIES_UPDATE
1434 || data->contents == UPDATE_ENTRIES_PATCH
1435 || data->contents == UPDATE_ENTRIES_RCS_DIFF)
1437 char *size_string;
1438 char *mode_string;
1439 int size;
1440 char *buf;
1441 char *temp_filename;
1442 int use_gzip;
1443 int patch_failed;
1445 read_line (&mode_string);
1447 read_line (&size_string);
1448 if (size_string[0] == 'z')
1450 use_gzip = 1;
1451 size = atoi (size_string+1);
1453 else
1455 use_gzip = 0;
1456 size = atoi (size_string);
1458 free (size_string);
1460 /* Note that checking this separately from writing the file is
1461 a race condition: if the existence or lack thereof of the
1462 file changes between now and the actual calls which
1463 operate on it, we lose. However (a) there are so many
1464 cases, I'm reluctant to try to fix them all, (b) in some
1465 cases the system might not even have a system call which
1466 does the right thing, and (c) it isn't clear this needs to
1467 work. */
1468 if (data->existp == UPDATE_ENTRIES_EXISTING
1469 && !isfile (filename))
1470 /* Emit a warning and update the file anyway. */
1471 error (0, 0, "warning: %s unexpectedly disappeared",
1472 short_pathname);
1474 if (data->existp == UPDATE_ENTRIES_NEW
1475 && isfile (filename))
1477 /* Emit a warning and refuse to update the file; we don't want
1478 to clobber a user's file. */
1479 size_t nread;
1480 size_t toread;
1482 /* size should be unsigned, but until we get around to fixing
1483 that, work around it. */
1484 size_t usize;
1486 char buf[8192];
1488 /* This error might be confusing; it isn't really clear to
1489 the user what to do about it. Keep in mind that it has
1490 several causes: (1) something/someone creates the file
1491 during the time that CVS is running, (2) the repository
1492 has two files whose names clash for the client because
1493 of case-insensitivity or similar causes, See 3 for
1494 additional notes. (3) a special case of this is that a
1495 file gets renamed for example from a.c to A.C. A
1496 "cvs update" on a case-insensitive client will get this
1497 error. In this case and in case 2, the filename
1498 (short_pathname) printed in the error message will likely _not_
1499 have the same case as seen by the user in a directory listing.
1500 (4) the client has a file which the server doesn't know
1501 about (e.g. "? foo" file), and that name clashes with a file
1502 the server does know about, (5) classify.c will print the same
1503 message for other reasons.
1505 I hope the above paragraph makes it clear that making this
1506 clearer is not a one-line fix. */
1507 error (0, 0, "move away `%s'; it is in the way", short_pathname);
1508 if (updated_fname)
1510 cvs_output ("C ", 0);
1511 cvs_output (updated_fname, 0);
1512 cvs_output ("\n", 1);
1514 failure_exit = true;
1516 discard_file_and_return:
1517 /* Now read and discard the file contents. */
1518 usize = size;
1519 nread = 0;
1520 while (nread < usize)
1522 toread = usize - nread;
1523 if (toread > sizeof buf)
1524 toread = sizeof buf;
1526 nread += try_read_from_server (buf, toread);
1527 if (nread == usize)
1528 break;
1531 free (mode_string);
1532 free (scratch_entries);
1533 free (entries_line);
1535 /* The Mode, Mod-time, and Checksum responses should not carry
1536 over to a subsequent Created (or whatever) response, even
1537 in the error case. */
1538 if (stored_mode)
1540 free (stored_mode);
1541 stored_mode = NULL;
1543 stored_modtime_valid = 0;
1544 stored_checksum_valid = 0;
1546 if (updated_fname)
1548 free (updated_fname);
1549 updated_fname = NULL;
1551 return;
1554 temp_filename = xmalloc (strlen (filename) + 80);
1555 #ifdef USE_VMS_FILENAMES
1556 /* A VMS rename of "blah.dat" to "foo" to implies a
1557 destination of "foo.dat" which is unfortinate for CVS */
1558 sprintf (temp_filename, "%s_new_", filename);
1559 #else
1560 #ifdef _POSIX_NO_TRUNC
1561 sprintf (temp_filename, ".new.%.9s", filename);
1562 #else /* _POSIX_NO_TRUNC */
1563 sprintf (temp_filename, ".new.%s", filename);
1564 #endif /* _POSIX_NO_TRUNC */
1565 #endif /* USE_VMS_FILENAMES */
1567 buf = xmalloc (size);
1569 /* Some systems, like OS/2 and Windows NT, end lines with CRLF
1570 instead of just LF. Format translation is done in the C
1571 library I/O funtions. Here we tell them whether or not to
1572 convert -- if this file is marked "binary" with the RCS -kb
1573 flag, then we don't want to convert, else we do (because
1574 CVS assumes text files by default). */
1576 if (options)
1577 bin = !strcmp (options, "-kb");
1578 else
1579 bin = 0;
1581 if (data->contents == UPDATE_ENTRIES_RCS_DIFF)
1583 /* This is an RCS change text. We just hold the change
1584 text in memory. */
1586 if (use_gzip)
1587 error (1, 0,
1588 "server error: gzip invalid with RCS change text");
1590 read_from_server (buf, size);
1592 else
1594 int fd;
1596 fd = CVS_OPEN (temp_filename,
1597 (O_WRONLY | O_CREAT | O_TRUNC
1598 | (bin ? OPEN_BINARY : 0)),
1599 0777);
1601 if (fd < 0)
1603 /* I can see a case for making this a fatal error; for
1604 a condition like disk full or network unreachable
1605 (for a file server), carrying on and giving an
1606 error on each file seems unnecessary. But if it is
1607 a permission problem, or some such, then it is
1608 entirely possible that future files will not have
1609 the same problem. */
1610 error (0, errno, "cannot write %s", short_pathname);
1611 free (temp_filename);
1612 free (buf);
1613 goto discard_file_and_return;
1616 if (size > 0)
1618 read_from_server (buf, size);
1620 if (use_gzip)
1622 if (gunzip_and_write (fd, short_pathname,
1623 (unsigned char *) buf, size))
1624 error (1, 0, "aborting due to compression error");
1626 else if (write (fd, buf, size) != size)
1627 error (1, errno, "writing %s", short_pathname);
1630 if (close (fd) < 0)
1631 error (1, errno, "writing %s", short_pathname);
1634 /* This is after we have read the file from the net (a change
1635 from previous versions, where the server would send us
1636 "M U foo.c" before Update-existing or whatever), but before
1637 we finish writing the file (arguably a bug). The timing
1638 affects a user who wants status info about how far we have
1639 gotten, and also affects whether "U foo.c" appears in addition
1640 to various error messages. */
1641 if (updated_fname)
1643 cvs_output ("U ", 0);
1644 cvs_output (updated_fname, 0);
1645 cvs_output ("\n", 1);
1646 free (updated_fname);
1647 updated_fname = 0;
1650 patch_failed = 0;
1652 if (data->contents == UPDATE_ENTRIES_UPDATE)
1654 rename_file (temp_filename, filename);
1656 else if (data->contents == UPDATE_ENTRIES_PATCH)
1658 /* You might think we could just leave Patched out of
1659 Valid-responses and not get this response. However, if
1660 memory serves, the CVS 1.9 server bases this on -u
1661 (update-patches), and there is no way for us to send -u
1662 or not based on whether the server supports "Rcs-diff".
1664 Fall back to transmitting entire files. */
1665 patch_failed = 1;
1667 else
1669 char *filebuf;
1670 size_t filebufsize;
1671 size_t nread;
1672 char *patchedbuf;
1673 size_t patchedlen;
1675 /* Handle UPDATE_ENTRIES_RCS_DIFF. */
1677 if (!isfile (filename))
1678 error (1, 0, "patch original file %s does not exist",
1679 short_pathname);
1680 filebuf = NULL;
1681 filebufsize = 0;
1682 nread = 0;
1684 get_file (filename, short_pathname, bin ? FOPEN_BINARY_READ : "r",
1685 &filebuf, &filebufsize, &nread);
1686 /* At this point the contents of the existing file are in
1687 FILEBUF, and the length of the contents is in NREAD.
1688 The contents of the patch from the network are in BUF,
1689 and the length of the patch is in SIZE. */
1691 if (! rcs_change_text (short_pathname, filebuf, nread, buf, size,
1692 &patchedbuf, &patchedlen))
1693 patch_failed = 1;
1694 else
1696 if (stored_checksum_valid)
1698 unsigned char checksum[16];
1700 /* We have a checksum. Check it before writing
1701 the file out, so that we don't have to read it
1702 back in again. */
1703 md5_buffer (patchedbuf, patchedlen, checksum);
1704 if (memcmp (checksum, stored_checksum, 16) != 0)
1706 error (0, 0,
1707 "checksum failure after patch to %s; will refetch",
1708 short_pathname);
1710 patch_failed = 1;
1713 stored_checksum_valid = 0;
1716 if (! patch_failed)
1718 FILE *e;
1720 e = xfopen (temp_filename,
1721 bin ? FOPEN_BINARY_WRITE : "w");
1722 if (fwrite (patchedbuf, sizeof *patchedbuf, patchedlen, e)
1723 != patchedlen)
1724 error (1, errno, "cannot write %s", temp_filename);
1725 if (fclose (e) == EOF)
1726 error (1, errno, "cannot close %s", temp_filename);
1727 rename_file (temp_filename, filename);
1730 free (patchedbuf);
1733 free (filebuf);
1736 free (temp_filename);
1738 if (stored_checksum_valid && ! patch_failed)
1740 FILE *e;
1741 struct md5_ctx context;
1742 unsigned char buf[8192];
1743 unsigned len;
1744 unsigned char checksum[16];
1747 * Compute the MD5 checksum. This will normally only be
1748 * used when receiving a patch, so we always compute it
1749 * here on the final file, rather than on the received
1750 * data.
1752 * Note that if the file is a text file, we should read it
1753 * here using text mode, so its lines will be terminated the same
1754 * way they were transmitted.
1756 e = CVS_FOPEN (filename, "r");
1757 if (!e)
1758 error (1, errno, "could not open %s", short_pathname);
1760 md5_init_ctx (&context);
1761 while ((len = fread (buf, 1, sizeof buf, e)) != 0)
1762 md5_process_bytes (buf, len, &context);
1763 if (ferror (e))
1764 error (1, errno, "could not read %s", short_pathname);
1765 md5_finish_ctx (&context, checksum);
1767 fclose (e);
1769 stored_checksum_valid = 0;
1771 if (memcmp (checksum, stored_checksum, 16) != 0)
1773 if (data->contents != UPDATE_ENTRIES_PATCH)
1774 error (1, 0, "checksum failure on %s",
1775 short_pathname);
1777 error (0, 0,
1778 "checksum failure after patch to %s; will refetch",
1779 short_pathname);
1781 patch_failed = 1;
1785 if (patch_failed)
1787 /* Save this file to retrieve later. */
1788 failed_patches = xnrealloc (failed_patches,
1789 failed_patches_count + 1,
1790 sizeof (char *));
1791 failed_patches[failed_patches_count] = xstrdup (short_pathname);
1792 ++failed_patches_count;
1794 stored_checksum_valid = 0;
1796 free (mode_string);
1797 free (buf);
1798 free (scratch_entries);
1799 free (entries_line);
1801 return;
1805 int status = change_mode (filename, mode_string, 1);
1806 if (status != 0)
1807 error (0, status, "cannot change mode of %s", short_pathname);
1810 free (mode_string);
1811 free (buf);
1814 if (stored_mode)
1816 change_mode (filename, stored_mode, 1);
1817 free (stored_mode);
1818 stored_mode = NULL;
1821 if (stored_modtime_valid)
1823 struct utimbuf t;
1825 memset (&t, 0, sizeof (t));
1826 t.modtime = stored_modtime;
1827 (void) time (&t.actime);
1829 #ifdef UTIME_EXPECTS_WRITABLE
1830 if (!iswritable (filename))
1832 xchmod (filename, 1);
1833 change_it_back = 1;
1835 #endif /* UTIME_EXPECTS_WRITABLE */
1837 if (utime (filename, &t) < 0)
1838 error (0, errno, "cannot set time on %s", filename);
1840 #ifdef UTIME_EXPECTS_WRITABLE
1841 if (change_it_back)
1843 xchmod (filename, 0);
1844 change_it_back = 0;
1846 #endif /* UTIME_EXPECTS_WRITABLE */
1848 stored_modtime_valid = 0;
1852 * Process the entries line. Do this after we've written the file,
1853 * since we need the timestamp.
1855 if (strcmp (cvs_cmd_name, "export"))
1857 char *local_timestamp;
1858 char *file_timestamp;
1860 (void) time (&last_register_time);
1862 local_timestamp = data->timestamp;
1863 if (!local_timestamp || ts[0] == '+')
1864 file_timestamp = time_stamp (filename);
1865 else
1866 file_timestamp = NULL;
1869 * These special version numbers signify that it is not up to
1870 * date. Create a dummy timestamp which will never compare
1871 * equal to the timestamp of the file.
1873 if (vn[0] == '\0' || !strcmp (vn, "0") || vn[0] == '-')
1874 local_timestamp = "dummy timestamp";
1875 else if (!local_timestamp)
1877 local_timestamp = file_timestamp;
1879 /* Checking for cvs_cmd_name of "commit" doesn't seem like
1880 the cleanest way to handle this, but it seem to roughly
1881 parallel what the :local: code which calls
1882 mark_up_to_date ends up amounting to. Some day, should
1883 think more about what the Checked-in response means
1884 vis-a-vis both Entries and Base and clarify
1885 cvsclient.texi accordingly. */
1887 if (!strcmp (cvs_cmd_name, "commit"))
1888 mark_up_to_date (filename);
1891 Register (ent_list, filename, vn, local_timestamp,
1892 options, tag, date, ts[0] == '+' ? file_timestamp : NULL);
1894 if (file_timestamp)
1895 free (file_timestamp);
1898 free (scratch_entries);
1899 free (entries_line);
1904 static void
1905 handle_checked_in (char *args, size_t len)
1907 struct update_entries_data dat;
1908 dat.contents = UPDATE_ENTRIES_CHECKIN;
1909 dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
1910 dat.timestamp = NULL;
1911 call_in_directory (args, update_entries, &dat);
1916 static void
1917 handle_new_entry (char *args, size_t len)
1919 struct update_entries_data dat;
1920 dat.contents = UPDATE_ENTRIES_CHECKIN;
1921 dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
1922 dat.timestamp = "dummy timestamp from new-entry";
1923 call_in_directory (args, update_entries, &dat);
1928 static void
1929 handle_updated (char *args, size_t len)
1931 struct update_entries_data dat;
1932 dat.contents = UPDATE_ENTRIES_UPDATE;
1933 dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
1934 dat.timestamp = NULL;
1935 call_in_directory (args, update_entries, &dat);
1940 static void
1941 handle_created (char *args, size_t len)
1943 struct update_entries_data dat;
1944 dat.contents = UPDATE_ENTRIES_UPDATE;
1945 dat.existp = UPDATE_ENTRIES_NEW;
1946 dat.timestamp = NULL;
1947 call_in_directory (args, update_entries, &dat);
1952 static void
1953 handle_update_existing (char *args, size_t len)
1955 struct update_entries_data dat;
1956 dat.contents = UPDATE_ENTRIES_UPDATE;
1957 dat.existp = UPDATE_ENTRIES_EXISTING;
1958 dat.timestamp = NULL;
1959 call_in_directory (args, update_entries, &dat);
1964 static void
1965 handle_merged (char *args, size_t len)
1967 struct update_entries_data dat;
1968 dat.contents = UPDATE_ENTRIES_UPDATE;
1969 /* Think this could be UPDATE_ENTRIES_EXISTING, but just in case... */
1970 dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
1971 dat.timestamp = "Result of merge";
1972 call_in_directory (args, update_entries, &dat);
1977 static void
1978 handle_patched (char *args, size_t len)
1980 struct update_entries_data dat;
1981 dat.contents = UPDATE_ENTRIES_PATCH;
1982 /* Think this could be UPDATE_ENTRIES_EXISTING, but just in case... */
1983 dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
1984 dat.timestamp = NULL;
1985 call_in_directory (args, update_entries, &dat);
1990 static void
1991 handle_rcs_diff (char *args, size_t len)
1993 struct update_entries_data dat;
1994 dat.contents = UPDATE_ENTRIES_RCS_DIFF;
1995 /* Think this could be UPDATE_ENTRIES_EXISTING, but just in case... */
1996 dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
1997 dat.timestamp = NULL;
1998 call_in_directory (args, update_entries, &dat);
2003 static void
2004 remove_entry (void *data, List *ent_list, const char *short_pathname,
2005 const char *filename)
2007 Scratch_Entry (ent_list, filename);
2012 static void
2013 handle_remove_entry (char *args, size_t len)
2015 call_in_directory (args, remove_entry, NULL);
2020 static void
2021 remove_entry_and_file (void *data, List *ent_list, const char *short_pathname,
2022 const char *filename)
2024 Scratch_Entry (ent_list, filename);
2025 /* Note that we don't ignore existence_error's here. The server
2026 should be sending Remove-entry rather than Removed in cases
2027 where the file does not exist. And if the user removes the
2028 file halfway through a cvs command, we should be printing an
2029 error. */
2030 if (unlink_file (filename) < 0)
2031 error (0, errno, "unable to remove %s", short_pathname);
2036 static void
2037 handle_removed (char *args, size_t len)
2039 call_in_directory (args, remove_entry_and_file, NULL);
2044 /* Is this the top level (directory containing CVSROOT)? */
2045 static int
2046 is_cvsroot_level (char *pathname)
2048 if (strcmp (toplevel_repos, current_parsed_root->directory))
2049 return 0;
2051 return !strchr (pathname, '/');
2056 static void
2057 set_static (void *data, List *ent_list, const char *short_pathname,
2058 const char *filename)
2060 FILE *fp;
2061 fp = xfopen (CVSADM_ENTSTAT, "w+");
2062 if (fclose (fp) == EOF)
2063 error (1, errno, "cannot close %s", CVSADM_ENTSTAT);
2068 static void
2069 handle_set_static_directory (char *args, size_t len)
2071 if (!strcmp (cvs_cmd_name, "export"))
2073 /* Swallow the repository. */
2074 read_line (NULL);
2075 return;
2077 call_in_directory (args, set_static, NULL);
2082 static void
2083 clear_static (void *data, List *ent_list, const char *short_pathname,
2084 const char *filename)
2086 if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno))
2087 error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
2092 static void
2093 handle_clear_static_directory (char *pathname, size_t len)
2095 if (!strcmp (cvs_cmd_name, "export"))
2097 /* Swallow the repository. */
2098 read_line (NULL);
2099 return;
2102 if (is_cvsroot_level (pathname))
2105 * Top level (directory containing CVSROOT). This seems to normally
2106 * lack a CVS directory, so don't try to create files in it.
2108 return;
2110 call_in_directory (pathname, clear_static, NULL);
2115 static void
2116 set_sticky (void *data, List *ent_list, const char *short_pathname,
2117 const char *filename)
2119 char *tagspec;
2120 FILE *f;
2122 read_line (&tagspec);
2124 /* FIXME-update-dir: error messages should include the directory. */
2125 f = CVS_FOPEN (CVSADM_TAG, "w+");
2126 if (!f)
2128 /* Making this non-fatal is a bit of a kludge (see dirs2
2129 in testsuite). A better solution would be to avoid having
2130 the server tell us about a directory we shouldn't be doing
2131 anything with anyway (e.g. by handling directory
2132 addition/removal better). */
2133 error (0, errno, "cannot open %s", CVSADM_TAG);
2134 free (tagspec);
2135 return;
2137 if (fprintf (f, "%s\n", tagspec) < 0)
2138 error (1, errno, "writing %s", CVSADM_TAG);
2139 if (fclose (f) == EOF)
2140 error (1, errno, "closing %s", CVSADM_TAG);
2141 free (tagspec);
2146 static void
2147 handle_set_sticky (char *pathname, size_t len)
2149 if (!strcmp (cvs_cmd_name, "export"))
2151 /* Swallow the repository. */
2152 read_line (NULL);
2153 /* Swallow the tag line. */
2154 read_line (NULL);
2155 return;
2157 if (is_cvsroot_level (pathname))
2160 * Top level (directory containing CVSROOT). This seems to normally
2161 * lack a CVS directory, so don't try to create files in it.
2164 /* Swallow the repository. */
2165 read_line (NULL);
2166 /* Swallow the tag line. */
2167 read_line (NULL);
2168 return;
2171 call_in_directory (pathname, set_sticky, NULL);
2176 static void
2177 clear_sticky (void *data, List *ent_list, const char *short_pathname,
2178 const char *filename)
2180 if (unlink_file (CVSADM_TAG) < 0 && ! existence_error (errno))
2181 error (1, errno, "cannot remove %s", CVSADM_TAG);
2186 static void
2187 handle_clear_sticky (char *pathname, size_t len)
2189 if (!strcmp (cvs_cmd_name, "export"))
2191 /* Swallow the repository. */
2192 read_line (NULL);
2193 return;
2196 if (is_cvsroot_level (pathname))
2199 * Top level (directory containing CVSROOT). This seems to normally
2200 * lack a CVS directory, so don't try to create files in it.
2202 return;
2205 call_in_directory (pathname, clear_sticky, NULL);
2210 /* Handle the client-side support for a successful edit.
2212 static void
2213 handle_edit_file (char *pathname, size_t len)
2215 call_in_directory (pathname, edit_file, NULL);
2220 static void
2221 template (void *data, List *ent_list, const char *short_pathname,
2222 const char *filename)
2224 char *buf = Xasprintf ("%s/%s", short_pathname, CVSADM_TEMPLATE);
2225 read_counted_file (CVSADM_TEMPLATE, buf);
2226 free (buf);
2231 static void
2232 handle_template (char *pathname, size_t len)
2234 call_in_directory (pathname, template, NULL);
2239 static void
2240 clear_template (void *data, List *ent_list, const char *short_pathname,
2241 const char *filename)
2243 if (unlink_file (CVSADM_TEMPLATE) < 0 && ! existence_error (errno))
2244 error (1, errno, "cannot remove %s", CVSADM_TEMPLATE);
2249 static void
2250 handle_clear_template (char *pathname, size_t len)
2252 call_in_directory (pathname, clear_template, NULL);
2257 struct save_dir {
2258 char *dir;
2259 struct save_dir *next;
2262 struct save_dir *prune_candidates;
2264 static void
2265 add_prune_candidate (const char *dir)
2267 struct save_dir *p;
2269 if ((dir[0] == '.' && dir[1] == '\0')
2270 || (prune_candidates && !strcmp (dir, prune_candidates->dir)))
2271 return;
2272 p = xmalloc (sizeof (struct save_dir));
2273 p->dir = xstrdup (dir);
2274 p->next = prune_candidates;
2275 prune_candidates = p;
2280 static void
2281 process_prune_candidates (void)
2283 struct save_dir *p;
2284 struct save_dir *q;
2286 if (toplevel_wd)
2288 if (CVS_CHDIR (toplevel_wd) < 0)
2289 error (1, errno, "could not chdir to %s", toplevel_wd);
2291 for (p = prune_candidates; p; )
2293 if (isemptydir (p->dir, 1))
2295 char *b;
2297 if (unlink_file_dir (p->dir) < 0)
2298 error (0, errno, "cannot remove %s", p->dir);
2299 b = strrchr (p->dir, '/');
2300 if (!b)
2301 Subdir_Deregister (NULL, NULL, p->dir);
2302 else
2304 *b = '\0';
2305 Subdir_Deregister (NULL, p->dir, b + 1);
2308 free (p->dir);
2309 q = p->next;
2310 free (p);
2311 p = q;
2313 prune_candidates = NULL;
2318 /* Send a Repository line. */
2319 static char *last_repos;
2320 static char *last_update_dir;
2321 static void
2322 send_repository (const char *dir, const char *repos, const char *update_dir)
2324 char *adm_name;
2326 /* FIXME: this is probably not the best place to check; I wish I
2327 * knew where in here's callers to really trap this bug. To
2328 * reproduce the bug, just do this:
2330 * mkdir junk
2331 * cd junk
2332 * cvs -d some_repos update foo
2334 * Poof, CVS seg faults and dies! It's because it's trying to
2335 * send a NULL string to the server but dies in send_to_server.
2336 * That string was supposed to be the repository, but it doesn't
2337 * get set because there's no CVSADM dir, and somehow it's not
2338 * getting set from the -d argument either... ?
2340 if (!repos)
2342 /* Lame error. I want a real fix but can't stay up to track
2343 this down right now. */
2344 error (1, 0, "no repository");
2347 if (!update_dir || update_dir[0] == '\0')
2348 update_dir = ".";
2350 if (last_repos && !strcmp (repos, last_repos)
2351 && last_update_dir && !strcmp (update_dir, last_update_dir))
2352 /* We've already sent it. */
2353 return;
2355 if (client_prune_dirs)
2356 add_prune_candidate (update_dir);
2358 /* Add a directory name to the list of those sent to the
2359 server. */
2360 if (update_dir && *update_dir != '\0' && strcmp (update_dir, ".")
2361 && !findnode (dirs_sent_to_server, update_dir))
2363 Node *n;
2364 n = getnode ();
2365 n->type = NT_UNKNOWN;
2366 n->key = xstrdup (update_dir);
2367 n->data = NULL;
2369 if (addnode (dirs_sent_to_server, n))
2370 error (1, 0, "cannot add directory %s to list", n->key);
2373 /* 80 is large enough for any of CVSADM_*. */
2374 adm_name = xmalloc (strlen (dir) + 80);
2376 send_to_server ("Directory ", 0);
2378 /* Send the directory name. I know that this
2379 sort of duplicates code elsewhere, but each
2380 case seems slightly different... */
2381 char buf[1];
2382 const char *p = update_dir;
2383 while (*p != '\0')
2385 assert (*p != '\012');
2386 if (ISSLASH (*p))
2388 buf[0] = '/';
2389 send_to_server (buf, 1);
2391 else
2393 buf[0] = *p;
2394 send_to_server (buf, 1);
2396 ++p;
2399 send_to_server ("\012", 1);
2400 if (supported_request ("Relative-directory"))
2402 const char *short_repos = Short_Repository (repos);
2403 send_to_server (short_repos, 0);
2405 else
2406 send_to_server (repos, 0);
2407 send_to_server ("\012", 1);
2409 if (supported_request ("Static-directory"))
2411 adm_name[0] = '\0';
2412 if (dir[0] != '\0')
2414 strcat (adm_name, dir);
2415 strcat (adm_name, "/");
2417 strcat (adm_name, CVSADM_ENTSTAT);
2418 if (isreadable (adm_name))
2420 send_to_server ("Static-directory\012", 0);
2423 if (supported_request ("Sticky"))
2425 FILE *f;
2426 if (dir[0] == '\0')
2427 strcpy (adm_name, CVSADM_TAG);
2428 else
2429 sprintf (adm_name, "%s/%s", dir, CVSADM_TAG);
2431 f = CVS_FOPEN (adm_name, "r");
2432 if (!f)
2434 if (! existence_error (errno))
2435 error (1, errno, "reading %s", adm_name);
2437 else
2439 char line[80];
2440 char *nl = NULL;
2441 send_to_server ("Sticky ", 0);
2442 while (fgets (line, sizeof (line), f))
2444 send_to_server (line, 0);
2445 nl = strchr (line, '\n');
2446 if (nl)
2447 break;
2449 if (!nl)
2450 send_to_server ("\012", 1);
2451 if (fclose (f) == EOF)
2452 error (0, errno, "closing %s", adm_name);
2455 free (adm_name);
2456 if (last_repos) free (last_repos);
2457 if (last_update_dir) free (last_update_dir);
2458 last_repos = xstrdup (repos);
2459 last_update_dir = xstrdup (update_dir);
2464 /* Send a Repository line and set toplevel_repos. */
2465 void
2466 send_a_repository (const char *dir, const char *repository,
2467 const char *update_dir_in)
2469 char *update_dir = xstrdup (update_dir_in);
2471 if (!toplevel_repos && repository)
2473 if (update_dir[0] == '\0'
2474 || (update_dir[0] == '.' && update_dir[1] == '\0'))
2475 toplevel_repos = xstrdup (repository);
2476 else
2479 * Get the repository from a CVS/Repository file if update_dir
2480 * is absolute. This is not correct in general, because
2481 * the CVS/Repository file might not be the top-level one.
2482 * This is for cases like "cvs update /foo/bar" (I'm not
2483 * sure it matters what toplevel_repos we get, but it does
2484 * matter that we don't hit the "internal error" code below).
2486 if (update_dir[0] == '/')
2487 toplevel_repos = Name_Repository (update_dir, update_dir);
2488 else
2491 * Guess the repository of that directory by looking at a
2492 * subdirectory and removing as many pathname components
2493 * as are in update_dir. I think that will always (or at
2494 * least almost always) be 1.
2496 * So this deals with directories which have been
2497 * renamed, though it doesn't necessarily deal with
2498 * directories which have been put inside other
2499 * directories (and cvs invoked on the containing
2500 * directory). I'm not sure the latter case needs to
2501 * work.
2503 * 21 Aug 1998: Well, Mr. Above-Comment-Writer, it
2504 * does need to work after all. When we are using the
2505 * client in a multi-cvsroot environment, it will be
2506 * fairly common that we have the above case (e.g.,
2507 * cwd checked out from one repository but
2508 * subdirectory checked out from another). We can't
2509 * assume that by walking up a directory in our wd we
2510 * necessarily walk up a directory in the repository.
2513 * This gets toplevel_repos wrong for "cvs update ../foo"
2514 * but I'm not sure toplevel_repos matters in that case.
2517 int repository_len, update_dir_len;
2519 strip_trailing_slashes (update_dir);
2521 repository_len = strlen (repository);
2522 update_dir_len = strlen (update_dir);
2524 /* Try to remove the path components in UPDATE_DIR
2525 from REPOSITORY. If the path elements don't exist
2526 in REPOSITORY, or the removal of those path
2527 elements mean that we "step above"
2528 current_parsed_root->directory, set toplevel_repos to
2529 current_parsed_root->directory. */
2530 if (repository_len > update_dir_len
2531 && !strcmp (repository + repository_len - update_dir_len,
2532 update_dir)
2533 /* TOPLEVEL_REPOS shouldn't be above current_parsed_root->directory */
2534 && ((size_t)(repository_len - update_dir_len)
2535 > strlen (current_parsed_root->directory)))
2537 /* The repository name contains UPDATE_DIR. Set
2538 toplevel_repos to the repository name without
2539 UPDATE_DIR. */
2541 toplevel_repos = xmalloc (repository_len - update_dir_len);
2542 /* Note that we don't copy the trailing '/'. */
2543 strncpy (toplevel_repos, repository,
2544 repository_len - update_dir_len - 1);
2545 toplevel_repos[repository_len - update_dir_len - 1] = '\0';
2547 else
2549 toplevel_repos = xstrdup (current_parsed_root->directory);
2555 send_repository (dir, repository, update_dir);
2556 free (update_dir);
2561 static void
2562 notified_a_file (void *data, List *ent_list, const char *short_pathname,
2563 const char *filename)
2565 FILE *fp;
2566 FILE *newf;
2567 size_t line_len = 8192;
2568 char *line = xmalloc (line_len);
2569 char *cp;
2570 int nread;
2571 int nwritten;
2572 char *p;
2574 fp = xfopen (CVSADM_NOTIFY, "r");
2575 if (getline (&line, &line_len, fp) < 0)
2577 if (feof (fp))
2578 error (0, 0, "cannot read %s: end of file", CVSADM_NOTIFY);
2579 else
2580 error (0, errno, "cannot read %s", CVSADM_NOTIFY);
2581 goto error_exit;
2583 cp = strchr (line, '\t');
2584 if (!cp)
2586 error (0, 0, "malformed %s file", CVSADM_NOTIFY);
2587 goto error_exit;
2589 *cp = '\0';
2590 if (strcmp (filename, line + 1))
2591 error (0, 0, "protocol error: notified %s, expected %s", filename,
2592 line + 1);
2594 if (getline (&line, &line_len, fp) < 0)
2596 if (feof (fp))
2598 free (line);
2599 if (fclose (fp) < 0)
2600 error (0, errno, "cannot close %s", CVSADM_NOTIFY);
2601 if ( CVS_UNLINK (CVSADM_NOTIFY) < 0)
2602 error (0, errno, "cannot remove %s", CVSADM_NOTIFY);
2603 return;
2605 else
2607 error (0, errno, "cannot read %s", CVSADM_NOTIFY);
2608 goto error_exit;
2611 newf = xfopen (CVSADM_NOTIFYTMP, "w");
2612 if (fputs (line, newf) < 0)
2614 error (0, errno, "cannot write %s", CVSADM_NOTIFYTMP);
2615 goto error2;
2617 while ((nread = fread (line, 1, line_len, fp)) > 0)
2619 p = line;
2620 while ((nwritten = fwrite (p, sizeof *p, nread, newf)) > 0)
2622 nread -= nwritten;
2623 p += nwritten;
2625 if (ferror (newf))
2627 error (0, errno, "cannot write %s", CVSADM_NOTIFYTMP);
2628 goto error2;
2631 if (ferror (fp))
2633 error (0, errno, "cannot read %s", CVSADM_NOTIFY);
2634 goto error2;
2636 if (fclose (newf) < 0)
2638 error (0, errno, "cannot close %s", CVSADM_NOTIFYTMP);
2639 goto error_exit;
2641 free (line);
2642 if (fclose (fp) < 0)
2644 error (0, errno, "cannot close %s", CVSADM_NOTIFY);
2645 return;
2649 /* In this case, we want rename_file() to ignore noexec. */
2650 int saved_noexec = noexec;
2651 noexec = 0;
2652 rename_file (CVSADM_NOTIFYTMP, CVSADM_NOTIFY);
2653 noexec = saved_noexec;
2656 return;
2657 error2:
2658 (void)fclose (newf);
2659 error_exit:
2660 free (line);
2661 (void)fclose (fp);
2666 static void
2667 handle_notified (char *args, size_t len)
2669 call_in_directory (args, notified_a_file, NULL);
2674 /* The "expanded" modules. */
2675 static int modules_count;
2676 static int modules_allocated;
2677 static char **modules_vector;
2679 static void
2680 handle_module_expansion (char *args, size_t len)
2682 if (!modules_vector)
2684 modules_allocated = 1; /* Small for testing */
2685 modules_vector = xnmalloc (modules_allocated,
2686 sizeof (modules_vector[0]));
2688 else if (modules_count >= modules_allocated)
2690 modules_allocated *= 2;
2691 modules_vector = xnrealloc (modules_vector,
2692 modules_allocated,
2693 sizeof (modules_vector[0]));
2695 modules_vector[modules_count] = xstrdup (args);
2696 ++modules_count;
2701 /* Original, not "expanded" modules. */
2702 static int module_argc;
2703 static char **module_argv;
2705 void
2706 client_expand_modules (int argc, char **argv, int local)
2708 int errs;
2709 int i;
2711 module_argc = argc;
2712 module_argv = xnmalloc (argc + 1, sizeof (module_argv[0]));
2713 for (i = 0; i < argc; ++i)
2714 module_argv[i] = xstrdup (argv[i]);
2715 module_argv[argc] = NULL;
2717 for (i = 0; i < argc; ++i)
2718 send_arg (argv[i]);
2719 send_a_repository ("", current_parsed_root->directory, "");
2721 send_to_server ("expand-modules\012", 0);
2723 errs = get_server_responses ();
2725 if (last_repos) free (last_repos);
2726 last_repos = NULL;
2728 if (last_update_dir) free (last_update_dir);
2729 last_update_dir = NULL;
2731 if (errs)
2732 error (errs, 0, "cannot expand modules");
2737 void
2738 client_send_expansions (int local, char *where, int build_dirs)
2740 int i;
2741 char *argv[1];
2743 /* Send the original module names. The "expanded" module name might
2744 not be suitable as an argument to a co request (e.g. it might be
2745 the result of a -d argument in the modules file). It might be
2746 cleaner if we genuinely expanded module names, all the way to a
2747 local directory and repository, but that isn't the way it works
2748 now. */
2749 send_file_names (module_argc, module_argv, 0);
2751 for (i = 0; i < modules_count; ++i)
2753 argv[0] = where ? where : modules_vector[i];
2754 if (isfile (argv[0]))
2755 send_files (1, argv, local, 0, build_dirs ? SEND_BUILD_DIRS : 0);
2757 send_a_repository ("", current_parsed_root->directory, "");
2762 void
2763 client_nonexpanded_setup (void)
2765 send_a_repository ("", current_parsed_root->directory, "");
2770 /* Receive a cvswrappers line from the server; it must be a line
2771 containing an RCS option (e.g., "*.exe -k 'b'").
2773 Note that this doesn't try to handle -t/-f options (which are a
2774 whole separate issue which noone has thought much about, as far
2775 as I know).
2777 We need to know the keyword expansion mode so we know whether to
2778 read the file in text or binary mode. */
2779 static void
2780 handle_wrapper_rcs_option (char *args, size_t len)
2782 char *p;
2784 /* Enforce the notes in cvsclient.texi about how the response is not
2785 as free-form as it looks. */
2786 p = strchr (args, ' ');
2787 if (!p)
2788 goto handle_error;
2789 if (*++p != '-'
2790 || *++p != 'k'
2791 || *++p != ' '
2792 || *++p != '\'')
2793 goto handle_error;
2794 if (!strchr (p, '\''))
2795 goto handle_error;
2797 /* Add server-side cvswrappers line to our wrapper list. */
2798 wrap_add (args, 0);
2799 return;
2800 handle_error:
2801 error (0, errno, "protocol error: ignoring invalid wrappers %s", args);
2807 static void
2808 handle_m (char *args, size_t len)
2810 /* In the case where stdout and stderr point to the same place,
2811 fflushing stderr will make output happen in the correct order.
2812 Often stderr will be line-buffered and this won't be needed,
2813 but not always (is that true? I think the comment is probably
2814 based on being confused between default buffering between
2815 stdout and stderr. But I'm not sure). */
2816 fflush (stderr);
2817 fwrite (args, sizeof *args, len, stdout);
2818 putc ('\n', stdout);
2823 static void
2824 handle_mbinary (char *args, size_t len)
2826 char *size_string;
2827 size_t size;
2828 size_t totalread;
2829 size_t nread;
2830 size_t toread;
2831 char buf[8192];
2833 /* See comment at handle_m about (non)flush of stderr. */
2835 /* Get the size. */
2836 read_line (&size_string);
2837 size = atoi (size_string);
2838 free (size_string);
2840 /* OK, now get all the data. The algorithm here is that we read
2841 as much as the network wants to give us in
2842 try_read_from_server, and then we output it all, and then
2843 repeat, until we get all the data. */
2844 totalread = 0;
2845 while (totalread < size)
2847 toread = size - totalread;
2848 if (toread > sizeof buf)
2849 toread = sizeof buf;
2851 nread = try_read_from_server (buf, toread);
2852 cvs_output_binary (buf, nread);
2853 totalread += nread;
2859 static void
2860 handle_e (char *args, size_t len)
2862 /* In the case where stdout and stderr point to the same place,
2863 fflushing stdout will make output happen in the correct order. */
2864 fflush (stdout);
2865 fwrite (args, sizeof *args, len, stderr);
2866 putc ('\n', stderr);
2871 /*ARGSUSED*/
2872 static void
2873 handle_f (char *args, size_t len)
2875 fflush (stderr);
2880 static void
2881 handle_mt (char *args, size_t len)
2883 char *p;
2884 char *tag = args;
2885 char *text;
2887 /* See comment at handle_m for more details. */
2888 fflush (stderr);
2890 p = strchr (args, ' ');
2891 if (!p)
2892 text = NULL;
2893 else
2895 *p++ = '\0';
2896 text = p;
2899 switch (tag[0])
2901 case '+':
2902 if (!strcmp (tag, "+updated"))
2903 updated_seen = 1;
2904 else if (!strcmp (tag, "+importmergecmd"))
2905 importmergecmd.seen = 1;
2906 break;
2907 case '-':
2908 if (!strcmp (tag, "-updated"))
2909 updated_seen = 0;
2910 else if (!strcmp (tag, "-importmergecmd"))
2912 char buf[80];
2914 /* Now that we have gathered the information, we can
2915 output the suggested merge command. */
2917 if (importmergecmd.conflicts == 0
2918 || !importmergecmd.mergetag1
2919 || !importmergecmd.mergetag2
2920 || !importmergecmd.repository)
2922 error (0, 0,
2923 "invalid server: incomplete importmergecmd tags");
2924 break;
2927 if (importmergecmd.conflicts == -1)
2928 sprintf (buf, "\nNo conflicts created by this import.\n");
2929 else
2930 sprintf (buf, "\n%d conflicts created by this import.\n",
2931 importmergecmd.conflicts);
2932 cvs_output (buf, 0);
2933 cvs_output ("Use the following command to help the merge:\n\n",
2935 cvs_output ("\t", 1);
2936 cvs_output (program_name, 0);
2937 if (CVSroot_cmdline)
2939 cvs_output (" -d ", 0);
2940 cvs_output (CVSroot_cmdline, 0);
2942 cvs_output (" checkout -j", 0);
2943 cvs_output (importmergecmd.mergetag1, 0);
2944 cvs_output (" -j", 0);
2945 cvs_output (importmergecmd.mergetag2, 0);
2946 cvs_output (" ", 1);
2947 cvs_output (importmergecmd.repository, 0);
2948 cvs_output ("\n\n", 0);
2950 /* Clear the static variables so that everything is
2951 ready for any subsequent importmergecmd tag. */
2952 importmergecmd.conflicts = 0;
2953 free (importmergecmd.mergetag1);
2954 importmergecmd.mergetag1 = NULL;
2955 free (importmergecmd.mergetag2);
2956 importmergecmd.mergetag2 = NULL;
2957 free (importmergecmd.repository);
2958 importmergecmd.repository = NULL;
2960 importmergecmd.seen = 0;
2962 break;
2963 default:
2964 if (updated_seen)
2966 if (!strcmp (tag, "fname"))
2968 if (updated_fname)
2970 /* Output the previous message now. This can happen
2971 if there was no Update-existing or other such
2972 response, due to the -n global option. */
2973 cvs_output ("U ", 0);
2974 cvs_output (updated_fname, 0);
2975 cvs_output ("\n", 1);
2976 free (updated_fname);
2978 updated_fname = xstrdup (text);
2980 /* Swallow all other tags. Either they are extraneous
2981 or they reflect future extensions that we can
2982 safely ignore. */
2984 else if (importmergecmd.seen)
2986 if (!strcmp (tag, "conflicts"))
2988 if (!strcmp (text, "No"))
2989 importmergecmd.conflicts = -1;
2990 else
2991 importmergecmd.conflicts = atoi (text);
2993 else if (!strcmp (tag, "mergetag1"))
2994 importmergecmd.mergetag1 = xstrdup (text);
2995 else if (!strcmp (tag, "mergetag2"))
2996 importmergecmd.mergetag2 = xstrdup (text);
2997 else if (!strcmp (tag, "repository"))
2998 importmergecmd.repository = xstrdup (text);
2999 /* Swallow all other tags. Either they are text for
3000 which we are going to print our own version when we
3001 see -importmergecmd, or they are future extensions
3002 we can safely ignore. */
3004 else if (!strcmp (tag, "newline"))
3005 printf ("\n");
3006 else if (!strcmp (tag, "date"))
3008 char *date = format_date_alloc (text);
3009 printf ("%s", date);
3010 free (date);
3012 else if (text)
3013 printf ("%s", text);
3019 #endif /* CLIENT_SUPPORT */
3020 #if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
3022 /* This table must be writeable if the server code is included. */
3023 struct response responses[] =
3025 #ifdef CLIENT_SUPPORT
3026 #define RSP_LINE(n, f, t, s) {n, f, t, s}
3027 #else /* ! CLIENT_SUPPORT */
3028 #define RSP_LINE(n, f, t, s) {n, s}
3029 #endif /* CLIENT_SUPPORT */
3031 RSP_LINE("ok", handle_ok, response_type_ok, rs_essential),
3032 RSP_LINE("error", handle_error, response_type_error, rs_essential),
3033 RSP_LINE("Valid-requests", handle_valid_requests, response_type_normal,
3034 rs_essential),
3035 RSP_LINE("Force-gzip", handle_force_gzip, response_type_normal,
3036 rs_optional),
3037 RSP_LINE("Referrer", handle_referrer, response_type_normal, rs_optional),
3038 RSP_LINE("Redirect", handle_redirect, response_type_redirect, rs_optional),
3039 RSP_LINE("Checked-in", handle_checked_in, response_type_normal,
3040 rs_essential),
3041 RSP_LINE("New-entry", handle_new_entry, response_type_normal, rs_optional),
3042 RSP_LINE("Checksum", handle_checksum, response_type_normal, rs_optional),
3043 RSP_LINE("Copy-file", handle_copy_file, response_type_normal, rs_optional),
3044 RSP_LINE("Updated", handle_updated, response_type_normal, rs_essential),
3045 RSP_LINE("Created", handle_created, response_type_normal, rs_optional),
3046 RSP_LINE("Update-existing", handle_update_existing, response_type_normal,
3047 rs_optional),
3048 RSP_LINE("Merged", handle_merged, response_type_normal, rs_essential),
3049 RSP_LINE("Patched", handle_patched, response_type_normal, rs_optional),
3050 RSP_LINE("Rcs-diff", handle_rcs_diff, response_type_normal, rs_optional),
3051 RSP_LINE("Mode", handle_mode, response_type_normal, rs_optional),
3052 RSP_LINE("Mod-time", handle_mod_time, response_type_normal, rs_optional),
3053 RSP_LINE("Removed", handle_removed, response_type_normal, rs_essential),
3054 RSP_LINE("Remove-entry", handle_remove_entry, response_type_normal,
3055 rs_optional),
3056 RSP_LINE("Set-static-directory", handle_set_static_directory,
3057 response_type_normal,
3058 rs_optional),
3059 RSP_LINE("Clear-static-directory", handle_clear_static_directory,
3060 response_type_normal,
3061 rs_optional),
3062 RSP_LINE("Set-sticky", handle_set_sticky, response_type_normal,
3063 rs_optional),
3064 RSP_LINE("Clear-sticky", handle_clear_sticky, response_type_normal,
3065 rs_optional),
3066 RSP_LINE("Edit-file", handle_edit_file, response_type_normal,
3067 rs_optional),
3068 RSP_LINE("Template", handle_template, response_type_normal,
3069 rs_optional),
3070 RSP_LINE("Clear-template", handle_clear_template, response_type_normal,
3071 rs_optional),
3072 RSP_LINE("Notified", handle_notified, response_type_normal, rs_optional),
3073 RSP_LINE("Module-expansion", handle_module_expansion, response_type_normal,
3074 rs_optional),
3075 RSP_LINE("Wrapper-rcsOption", handle_wrapper_rcs_option,
3076 response_type_normal,
3077 rs_optional),
3078 RSP_LINE("M", handle_m, response_type_normal, rs_essential),
3079 RSP_LINE("Mbinary", handle_mbinary, response_type_normal, rs_optional),
3080 RSP_LINE("E", handle_e, response_type_normal, rs_essential),
3081 RSP_LINE("F", handle_f, response_type_normal, rs_optional),
3082 RSP_LINE("MT", handle_mt, response_type_normal, rs_optional),
3083 /* Possibly should be response_type_error. */
3084 RSP_LINE(NULL, NULL, response_type_normal, rs_essential)
3086 #undef RSP_LINE
3089 #endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
3090 #ifdef CLIENT_SUPPORT
3095 * If LEN is 0, then send_to_server_via() computes string's length itself.
3097 * Therefore, pass the real length when transmitting data that might
3098 * contain 0's.
3100 void
3101 send_to_server_via (struct buffer *via_buffer, const char *str, size_t len)
3103 static int nbytes;
3105 if (len == 0)
3106 len = strlen (str);
3108 buf_output (via_buffer, str, len);
3110 /* There is no reason not to send data to the server, so do it
3111 whenever we've accumulated enough information in the buffer to
3112 make it worth sending. */
3113 nbytes += len;
3114 if (nbytes >= 2 * BUFFER_DATA_SIZE)
3116 int status;
3118 status = buf_send_output (via_buffer);
3119 if (status != 0)
3120 error (1, status, "error writing to server");
3121 nbytes = 0;
3127 void
3128 send_to_server (const char *str, size_t len)
3130 send_to_server_via (global_to_server, str, len);
3135 /* Read up to LEN bytes from the server. Returns actual number of
3136 bytes read, which will always be at least one; blocks if there is
3137 no data available at all. Gives a fatal error on EOF or error. */
3138 static size_t
3139 try_read_from_server( char *buf, size_t len )
3141 int status;
3142 size_t nread;
3143 char *data;
3145 status = buf_read_data (global_from_server, len, &data, &nread);
3146 if (status != 0)
3148 if (status == -1)
3149 error (1, 0,
3150 "end of file from server (consult above messages if any)");
3151 else if (status == -2)
3152 error (1, 0, "out of memory");
3153 else
3154 error (1, status, "reading from server");
3157 memcpy (buf, data, nread);
3159 return nread;
3165 * Read LEN bytes from the server or die trying.
3167 void
3168 read_from_server (char *buf, size_t len)
3170 size_t red = 0;
3171 while (red < len)
3173 red += try_read_from_server (buf + red, len - red);
3174 if (red == len)
3175 break;
3181 /* Get some server responses and process them.
3183 * RETURNS
3184 * 0 Success
3185 * 1 Error
3186 * 2 Redirect
3189 get_server_responses (void)
3191 struct response *rs;
3194 char *cmd;
3195 size_t len;
3197 len = read_line (&cmd);
3198 for (rs = responses; rs->name; ++rs)
3199 if (!strncmp (cmd, rs->name, strlen (rs->name)))
3201 size_t cmdlen = strlen (rs->name);
3202 if (cmd[cmdlen] == '\0')
3204 else if (cmd[cmdlen] == ' ')
3205 ++cmdlen;
3206 else
3208 * The first len characters match, but it's a different
3209 * response. e.g. the response is "oklahoma" but we
3210 * matched "ok".
3212 continue;
3213 (*rs->func) (cmd + cmdlen, len - cmdlen);
3214 break;
3216 if (!rs->name)
3217 /* It's OK to print just to the first '\0'. */
3218 /* We might want to handle control characters and the like
3219 in some other way other than just sending them to stdout.
3220 One common reason for this error is if people use :ext:
3221 with a version of rsh which is doing CRLF translation or
3222 something, and so the client gets "ok^M" instead of "ok".
3223 Right now that will tend to print part of this error
3224 message over the other part of it. It seems like we could
3225 do better (either in general, by quoting or omitting all
3226 control characters, and/or specifically, by detecting the CRLF
3227 case and printing a specific error message). */
3228 error (0, 0,
3229 "warning: unrecognized response `%s' from cvs server",
3230 cmd);
3231 free (cmd);
3232 } while (rs->type == response_type_normal);
3234 if (updated_fname)
3236 /* Output the previous message now. This can happen
3237 if there was no Update-existing or other such
3238 response, due to the -n global option. */
3239 cvs_output ("U ", 0);
3240 cvs_output (updated_fname, 0);
3241 cvs_output ("\n", 1);
3242 free (updated_fname);
3243 updated_fname = NULL;
3246 if (rs->type == response_type_redirect) return 2;
3247 if (rs->type == response_type_error) return 1;
3248 if (failure_exit) return 1;
3249 return 0;
3254 static inline void
3255 close_connection_to_server (struct buffer **to, struct buffer **from)
3257 int status;
3259 /* First we shut down GLOBAL_TO_SERVER. That tells the server that its
3260 * input is finished. It then shuts down the buffer it is sending to us,
3261 * at which point our shut down of GLOBAL_FROM_SERVER will complete.
3264 TRACE (TRACE_FUNCTION, "close_connection_to_server ()");
3266 status = buf_shutdown (*to);
3267 if (status != 0)
3268 error (0, status, "shutting down buffer to server");
3269 buf_free (*to);
3270 *to = NULL;
3272 status = buf_shutdown (*from);
3273 if (status != 0)
3274 error (0, status, "shutting down buffer from server");
3275 buf_free (*from);
3276 *from = NULL;
3281 /* Get the responses and then close the connection. */
3284 * Flag var; we'll set it in start_server() and not one of its
3285 * callees, such as start_rsh_server(). This means that there might
3286 * be a small window between the starting of the server and the
3287 * setting of this var, but all the code in that window shouldn't care
3288 * because it's busy checking return values to see if the server got
3289 * started successfully anyway.
3291 int server_started = 0;
3294 get_responses_and_close (void)
3296 int errs = get_server_responses ();
3298 /* The following is necessary when working with multiple cvsroots, at least
3299 * with commit. It used to be buried nicely in do_deferred_progs() before
3300 * that function was removed. I suspect it wouldn't be necessary if
3301 * call_in_directory() saved its working directory via save_cwd() before
3302 * changing its directory and restored the saved working directory via
3303 * restore_cwd() before exiting. Of course, calling CVS_CHDIR only once,
3304 * here, may be more efficient.
3306 if (toplevel_wd)
3308 if (CVS_CHDIR (toplevel_wd) < 0)
3309 error (1, errno, "could not chdir to %s", toplevel_wd);
3312 if (client_prune_dirs)
3313 process_prune_candidates ();
3315 close_connection_to_server (&global_to_server, &global_from_server);
3316 server_started = 0;
3318 /* see if we need to sleep before returning to avoid time-stamp races */
3319 if (last_register_time)
3320 sleep_past (last_register_time);
3322 return errs;
3327 bool
3328 supported_request (const char *name)
3330 struct request *rq;
3332 for (rq = requests; rq->name; rq++)
3333 if (!strcmp (rq->name, name))
3334 return (rq->flags & RQ_SUPPORTED) != 0;
3335 error (1, 0, "internal error: testing support for unknown request?");
3336 /* NOTREACHED */
3337 return 0;
3342 #if defined (AUTH_CLIENT_SUPPORT) || defined (SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
3345 /* Generic function to do port number lookup tasks.
3347 * In order of precedence, will return:
3348 * getenv (envname), if defined
3349 * getservbyname (portname), if defined
3350 * defaultport
3352 static int
3353 get_port_number (const char *envname, const char *portname, int defaultport)
3355 struct servent *s;
3356 char *port_s;
3358 if (envname && (port_s = getenv (envname)))
3360 int port = atoi (port_s);
3361 if (port <= 0)
3363 error (0, 0, "%s must be a positive integer! If you", envname);
3364 error (0, 0, "are trying to force a connection via rsh, please");
3365 error (0, 0, "put \":server:\" at the beginning of your CVSROOT");
3366 error (1, 0, "variable.");
3368 return port;
3370 else if (portname && (s = getservbyname (portname, "tcp")))
3371 return ntohs (s->s_port);
3372 else
3373 return defaultport;
3378 /* get the port number for a client to connect to based on the port
3379 * and method of a cvsroot_t.
3381 * we do this here instead of in parse_cvsroot so that we can keep network
3382 * code confined to a localized area and also to delay the lookup until the
3383 * last possible moment so it remains possible to run cvs client commands that
3384 * skip opening connections to the server (i.e. skip network operations
3385 * entirely)
3387 * and yes, I know none of the commands do that now, but here's to planning
3388 * for the future, eh? cheers.
3391 get_cvs_port_number (const cvsroot_t *root)
3394 if (root->port) return root->port;
3396 switch (root->method)
3398 # ifdef HAVE_GSSAPI
3399 case gserver_method:
3400 # endif /* HAVE_GSSAPI */
3401 # ifdef AUTH_CLIENT_SUPPORT
3402 case pserver_method:
3403 # endif /* AUTH_CLIENT_SUPPORT */
3404 # if defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_GSSAPI)
3405 return get_port_number ("CVS_CLIENT_PORT", "cvspserver",
3406 CVS_AUTH_PORT);
3407 # endif /* defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_GSSAPI) */
3408 # ifdef HAVE_KERBEROS
3409 case kserver_method:
3410 return get_port_number ("CVS_CLIENT_PORT", "cvs", CVS_PORT);
3411 # endif /* HAVE_KERBEROS */
3412 default:
3413 error(1, EINVAL,
3414 "internal error: get_cvs_port_number called for invalid connection method (%s)",
3415 method_names[root->method]);
3416 break;
3418 /* NOTREACHED */
3419 return -1;
3424 /* get the port number for a client to connect to based on the proxy port
3425 * of a cvsroot_t.
3427 static int
3428 get_proxy_port_number (const cvsroot_t *root)
3431 if (root->proxy_port) return root->proxy_port;
3433 return get_port_number ("CVS_PROXY_PORT", NULL, CVS_PROXY_PORT);
3438 void
3439 make_bufs_from_fds(int tofd, int fromfd, int child_pid, cvsroot_t *root,
3440 struct buffer **to_server_p,
3441 struct buffer **from_server_p, int is_sock)
3443 # ifdef NO_SOCKET_TO_FD
3444 if (is_sock)
3446 assert (tofd == fromfd);
3447 *to_server_p = socket_buffer_initialize (tofd, 0, NULL);
3448 *from_server_p = socket_buffer_initialize (tofd, 1, NULL);
3450 else
3451 # endif /* NO_SOCKET_TO_FD */
3453 /* todo: some OS's don't need these calls... */
3454 close_on_exec (tofd);
3455 close_on_exec (fromfd);
3457 /* SCO 3 and AIX have a nasty bug in the I/O libraries which precludes
3458 fdopening the same file descriptor twice, so dup it if it is the
3459 same. */
3460 if (tofd == fromfd)
3462 fromfd = dup (tofd);
3463 if (fromfd < 0)
3464 error (1, errno, "cannot dup net connection");
3467 /* These will use binary mode on systems which have it. */
3469 * Also, we know that from_server is shut down second, so we pass
3470 * child_pid in there. In theory, it should be stored in both
3471 * buffers with a ref count...
3473 *to_server_p = fd_buffer_initialize (tofd, 0, root, false, NULL);
3474 *from_server_p = fd_buffer_initialize (fromfd, child_pid, root,
3475 true, NULL);
3478 #endif /* defined (AUTH_CLIENT_SUPPORT) || defined (SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined(HAVE_GSSAPI) */
3482 #if defined (AUTH_CLIENT_SUPPORT) || defined(HAVE_GSSAPI)
3483 /* Connect to the authenticating server.
3485 If VERIFY_ONLY is non-zero, then just verify that the password is
3486 correct and then shutdown the connection.
3488 If VERIFY_ONLY is 0, then really connect to the server.
3490 If DO_GSSAPI is non-zero, then we use GSSAPI authentication rather
3491 than the pserver password authentication.
3493 If we fail to connect or if access is denied, then die with fatal
3494 error. */
3495 void
3496 connect_to_pserver (cvsroot_t *root, struct buffer **to_server_p,
3497 struct buffer **from_server_p, int verify_only,
3498 int do_gssapi)
3500 int sock;
3501 int port_number,
3502 proxy_port_number = 0; /* Initialize to silence -Wall. Dumb. */
3503 char no_passwd = 0; /* gets set if no password found */
3504 struct buffer *to_server, *from_server;
3506 port_number = get_cvs_port_number (root);
3508 /* if we have a proxy connect to that instead */
3509 if (root->proxy_hostname)
3511 TRACE (TRACE_FUNCTION, "Connecting to %s:%d via proxy %s:%d.",
3512 root->hostname, port_number, root->proxy_hostname,
3513 proxy_port_number);
3514 proxy_port_number = get_proxy_port_number (root);
3515 sock = connect_to(root->proxy_hostname, proxy_port_number);
3517 else
3519 TRACE (TRACE_FUNCTION, "Connecting to %s:%d.",
3520 root->hostname, port_number);
3521 sock = connect_to(root->hostname, port_number);
3524 if (sock == -1)
3525 error (1, 0, "connect to %s:%d failed: %s",
3526 root->proxy_hostname ? root->proxy_hostname : root->hostname,
3527 root->proxy_hostname ? proxy_port_number : port_number,
3528 SOCK_STRERROR (SOCK_ERRNO));
3530 make_bufs_from_fds (sock, sock, 0, root, &to_server, &from_server, 1);
3532 /* if we have proxy then connect to the proxy first */
3533 if (root->proxy_hostname)
3535 #define CONNECT_STRING "CONNECT %s:%d HTTP/1.0\r\n\r\n"
3536 /* Send a "CONNECT" command to proxy: */
3537 char* read_buf;
3538 int codenum;
3539 size_t count;
3540 /* 4 characters for port covered by the length of %s & %d */
3541 char* write_buf = Xasnprintf (NULL, &count, CONNECT_STRING,
3542 root->hostname, port_number);
3543 send_to_server_via (to_server, write_buf, count);
3545 /* Wait for HTTP status code, bail out if you don't get back a 2xx
3546 * code.
3548 read_line_via (from_server, to_server, &read_buf);
3549 sscanf (read_buf, "%s %d", write_buf, &codenum);
3551 if ((codenum / 100) != 2)
3552 error (1, 0, "proxy server %s:%d does not support http tunnelling",
3553 root->proxy_hostname, proxy_port_number);
3554 free (read_buf);
3555 free (write_buf);
3557 /* Skip through remaining part of MIME header, recv_line
3558 consumes the trailing \n */
3559 while (read_line_via (from_server, to_server, &read_buf) > 0)
3561 if (read_buf[0] == '\r' || read_buf[0] == 0)
3563 free (read_buf);
3564 break;
3566 free (read_buf);
3570 auth_server (root, to_server, from_server, verify_only, do_gssapi);
3572 if (verify_only)
3574 int status;
3576 status = buf_shutdown (to_server);
3577 if (status != 0)
3578 error (0, status, "shutting down buffer to server");
3579 buf_free (to_server);
3580 to_server = NULL;
3582 status = buf_shutdown (from_server);
3583 if (status != 0)
3584 error (0, status, "shutting down buffer from server");
3585 buf_free (from_server);
3586 from_server = NULL;
3588 /* Don't need to set server_started = 0 since we don't set it to 1
3589 * until returning from this call.
3592 else
3594 *to_server_p = to_server;
3595 *from_server_p = from_server;
3598 return;
3603 static void
3604 auth_server (cvsroot_t *root, struct buffer *to_server,
3605 struct buffer *from_server, int verify_only, int do_gssapi)
3607 char *username = NULL; /* the username we use to connect */
3608 char no_passwd = 0; /* gets set if no password found */
3610 /* Run the authorization mini-protocol before anything else. */
3611 if (do_gssapi)
3613 # ifdef HAVE_GSSAPI
3614 int fd = buf_get_fd (to_server);
3615 struct stat s;
3617 if ((fd < 0) || (fstat (fd, &s) < 0) || !S_ISSOCK(s.st_mode))
3619 error (1, 0,
3620 "gserver currently only enabled for socket connections");
3623 if (! connect_to_gserver (root, fd, root->hostname))
3625 error (1, 0,
3626 "authorization failed: server %s rejected access to %s",
3627 root->hostname, root->directory);
3629 # else /* ! HAVE_GSSAPI */
3630 error (1, 0,
3631 "INTERNAL ERROR: This client does not support GSSAPI authentication");
3632 # endif /* HAVE_GSSAPI */
3634 else /* ! do_gssapi */
3636 # ifdef AUTH_CLIENT_SUPPORT
3637 char *begin = NULL;
3638 char *password = NULL;
3639 char *end = NULL;
3641 if (verify_only)
3643 begin = "BEGIN VERIFICATION REQUEST";
3644 end = "END VERIFICATION REQUEST";
3646 else
3648 begin = "BEGIN AUTH REQUEST";
3649 end = "END AUTH REQUEST";
3652 /* Get the password, probably from ~/.cvspass. */
3653 password = get_cvs_password ();
3654 username = root->username ? root->username : getcaller();
3656 /* Send the empty string by default. This is so anonymous CVS
3657 access doesn't require client to have done "cvs login". */
3658 if (!password)
3660 no_passwd = 1;
3661 password = scramble ("");
3664 /* Announce that we're starting the authorization protocol. */
3665 send_to_server_via(to_server, begin, 0);
3666 send_to_server_via(to_server, "\012", 1);
3668 /* Send the data the server needs. */
3669 send_to_server_via(to_server, root->directory, 0);
3670 send_to_server_via(to_server, "\012", 1);
3671 send_to_server_via(to_server, username, 0);
3672 send_to_server_via(to_server, "\012", 1);
3673 send_to_server_via(to_server, password, 0);
3674 send_to_server_via(to_server, "\012", 1);
3676 /* Announce that we're ending the authorization protocol. */
3677 send_to_server_via(to_server, end, 0);
3678 send_to_server_via(to_server, "\012", 1);
3680 /* Paranoia. */
3681 free_cvs_password (password);
3682 password = NULL;
3683 # else /* ! AUTH_CLIENT_SUPPORT */
3684 error (1, 0, "INTERNAL ERROR: This client does not support pserver authentication");
3685 # endif /* AUTH_CLIENT_SUPPORT */
3686 } /* if (do_gssapi) */
3689 char *read_buf;
3691 /* Loop, getting responses from the server. */
3692 while (1)
3694 read_line_via (from_server, to_server, &read_buf);
3696 if (!strcmp (read_buf, "I HATE YOU"))
3698 /* Authorization not granted.
3700 * This is a little confusing since we can reach this while
3701 * loop in GSSAPI mode, but if GSSAPI authentication failed,
3702 * we already jumped to the rejected label (there is no case
3703 * where the connect_to_gserver function can return 1 and we
3704 * will not receive "I LOVE YOU" from the server, barring
3705 * broken connections and garbled messages, of course). The
3706 * GSSAPI case is also the case where username can be NULL
3707 * since username is initialized in the !gssapi section.
3709 * i.e. This is a pserver specific error message and should be
3710 * since GSSAPI doesn't use username.
3712 error (0, 0,
3713 "authorization failed: server %s rejected access to %s for user %s",
3714 root->hostname, root->directory,
3715 username ? username : "(null)");
3717 /* Output a special error message if authentication was attempted
3718 with no password -- the user should be made aware that they may
3719 have missed a step. */
3720 if (no_passwd)
3722 error (0, 0,
3723 "used empty password; try \"cvs login\" with a real password");
3725 exit (EXIT_FAILURE);
3727 else if (!strncmp (read_buf, "E ", 2))
3729 fprintf (stderr, "%s\n", read_buf + 2);
3731 /* Continue with the authentication protocol. */
3733 else if (!strncmp (read_buf, "error ", 6))
3735 char *p;
3737 /* First skip the code. */
3738 p = read_buf + 6;
3739 while (*p != ' ' && *p != '\0')
3740 ++p;
3742 /* Skip the space that follows the code. */
3743 if (*p == ' ')
3744 ++p;
3746 /* Now output the text. */
3747 fprintf (stderr, "%s\n", p);
3748 exit (EXIT_FAILURE);
3750 else if (!strcmp (read_buf, "I LOVE YOU"))
3752 free (read_buf);
3753 break;
3755 else
3757 error (1, 0,
3758 "unrecognized auth response from %s: %s",
3759 root->hostname, read_buf);
3761 free (read_buf);
3765 #endif /* defined (AUTH_CLIENT_SUPPORT) || defined(HAVE_GSSAPI) */
3769 #if defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT)
3771 * Connect to a forked server process.
3773 static void
3774 connect_to_forked_server (cvsroot_t *root, struct buffer **to_server_p,
3775 struct buffer **from_server_p)
3777 int tofd, fromfd;
3778 int child_pid;
3780 /* This is pretty simple. All we need to do is choose the correct
3781 cvs binary and call piped_child. */
3783 char *command[3];
3785 command[0] = (root->cvs_server
3786 ? root->cvs_server : getenv ("CVS_SERVER"));
3787 if (!command[0])
3788 # ifdef SERVER_SUPPORT
3789 /* FIXME:
3790 * I'm casting out the const below because I know that piped_child, the
3791 * only function we pass COMMAND to, accepts COMMAND as a
3792 * (char *const *) and won't alter it, and we don't alter it in this
3793 * function. This is yucky, there should be a way to declare COMMAND
3794 * such that this casting isn't needed, but I don't know how. If I
3795 * declare it as (const char *command[]), the compiler complains about
3796 * an incompatible arg 1 being passed to piped_child and if I declare
3797 * it as (char *const command[3]), then the compiler complains when I
3798 * assign values to command[i].
3800 command[0] = (char *)program_path;
3801 # else /* SERVER_SUPPORT */
3803 error( 0, 0, "You must set the CVS_SERVER environment variable when" );
3804 error( 0, 0, "using the :fork: access method." );
3805 error( 1, 0, "This CVS was not compiled with server support." );
3807 # endif /* SERVER_SUPPORT */
3809 command[1] = "server";
3810 command[2] = NULL;
3812 TRACE (TRACE_FUNCTION, "Forking server: %s %s",
3813 command[0] ? command[0] : "(null)", command[1]);
3815 child_pid = piped_child (command, &tofd, &fromfd, false);
3816 if (child_pid < 0)
3817 error (1, 0, "could not fork server process");
3819 make_bufs_from_fds (tofd, fromfd, child_pid, root, to_server_p,
3820 from_server_p, 0);
3822 #endif /* CLIENT_SUPPORT || SERVER_SUPPORT */
3826 static int
3827 send_variable_proc (Node *node, void *closure)
3829 send_to_server ("Set ", 0);
3830 send_to_server (node->key, 0);
3831 send_to_server ("=", 1);
3832 send_to_server (node->data, 0);
3833 send_to_server ("\012", 1);
3834 return 0;
3839 /* Open up the connection to the server and perform any necessary
3840 * authentication.
3842 void
3843 open_connection_to_server (cvsroot_t *root, struct buffer **to_server_p,
3844 struct buffer **from_server_p)
3846 /* Note that generally speaking we do *not* fall back to a different
3847 way of connecting if the first one does not work. This is slow
3848 (*really* slow on a 14.4kbps link); the clean way to have a CVS
3849 which supports several ways of connecting is with access methods. */
3851 TRACE (TRACE_FUNCTION, "open_connection_to_server (%s)", root->original);
3853 switch (root->method)
3855 case pserver_method:
3856 #ifdef AUTH_CLIENT_SUPPORT
3857 /* Toss the return value. It will die with an error message if
3858 * anything goes wrong anyway.
3860 connect_to_pserver (root, to_server_p, from_server_p, 0, 0);
3861 #else /* AUTH_CLIENT_SUPPORT */
3862 error (0, 0, "CVSROOT is set for a pserver access method but your");
3863 error (1, 0, "CVS executable doesn't support it.");
3864 #endif /* AUTH_CLIENT_SUPPORT */
3865 break;
3867 case kserver_method:
3868 #if HAVE_KERBEROS
3869 start_kerberos4_server (root, to_server_p,
3870 from_server_p);
3871 #else /* !HAVE_KERBEROS */
3872 error (0, 0,
3873 "CVSROOT is set for a kerberos access method but your");
3874 error (1, 0, "CVS executable doesn't support it.");
3875 #endif /* HAVE_KERBEROS */
3876 break;
3878 case gserver_method:
3879 #ifdef HAVE_GSSAPI
3880 /* GSSAPI authentication is handled by the pserver. */
3881 connect_to_pserver (root, to_server_p, from_server_p, 0, 1);
3882 #else /* !HAVE_GSSAPI */
3883 error (0, 0, "CVSROOT is set for a GSSAPI access method but your");
3884 error (1, 0, "CVS executable doesn't support it.");
3885 #endif /* HAVE_GSSAPI */
3886 break;
3888 case ext_method:
3889 #ifdef NO_EXT_METHOD
3890 error (0, 0, ":ext: method not supported by this port of CVS");
3891 error (1, 0, "try :server: instead");
3892 #else /* ! NO_EXT_METHOD */
3893 start_rsh_server (root, to_server_p,
3894 from_server_p);
3895 #endif /* NO_EXT_METHOD */
3896 break;
3898 case server_method:
3899 #ifdef START_SERVER
3901 int tofd, fromfd;
3902 START_SERVER (&tofd, &fromfd, getcaller (),
3903 root->username,
3904 root->hostname,
3905 root->directory);
3906 # ifdef START_SERVER_RETURNS_SOCKET
3907 make_bufs_from_fds (tofd, fromfd, 0, root, to_server_p,
3908 from_server_p, 1);
3909 # else /* ! START_SERVER_RETURNS_SOCKET */
3910 make_bufs_from_fds (tofd, fromfd, 0, root, to_server_p,
3911 from_server_p, 0);
3912 # endif /* START_SERVER_RETURNS_SOCKET */
3914 #else /* ! START_SERVER */
3915 /* FIXME: It should be possible to implement this portably,
3916 like pserver, which would get rid of the duplicated code
3917 in {vms,windows-NT,...}/startserver.c. */
3918 error (1, 0,
3919 "the :server: access method is not supported by this port of CVS");
3920 #endif /* START_SERVER */
3921 break;
3923 case fork_method:
3924 connect_to_forked_server (root, to_server_p, from_server_p);
3925 break;
3927 default:
3928 error (1, 0,
3929 "(start_server internal error): unknown access method");
3930 break;
3933 /* "Hi, I'm Darlene and I'll be your server tonight..." */
3934 server_started = 1;
3939 /* Contact the server. */
3940 void
3941 start_server (void)
3943 bool rootless;
3944 int status;
3945 bool have_global;
3949 /* Clear our static variables for this invocation. */
3950 if (toplevel_repos)
3951 free (toplevel_repos);
3952 toplevel_repos = NULL;
3954 open_connection_to_server (current_parsed_root, &global_to_server,
3955 &global_from_server);
3956 setup_logfiles ("CVS_CLIENT_LOG", &global_to_server,
3957 &global_from_server);
3959 /* Clear static variables. */
3960 if (toplevel_repos)
3962 free (toplevel_repos);
3963 toplevel_repos = NULL;
3965 if (last_repos)
3967 free (last_repos);
3968 last_repos = NULL;
3970 if (last_update_dir)
3972 free (last_update_dir);
3973 last_update_dir = NULL;
3975 stored_checksum_valid = 0;
3976 if (stored_mode)
3978 free (stored_mode);
3979 stored_mode = NULL;
3982 rootless = !strcmp (cvs_cmd_name, "init");
3983 if (!rootless)
3985 send_to_server ("Root ", 0);
3986 send_to_server (current_parsed_root->directory, 0);
3987 send_to_server ("\012", 1);
3991 struct response *rs;
3992 bool suppress_redirect = !current_parsed_root->redirect;
3994 send_to_server ("Valid-responses", 0);
3996 for (rs = responses; rs->name; ++rs)
3998 if (suppress_redirect && !strcmp (rs->name, "Redirect"))
3999 continue;
4001 send_to_server (" ", 0);
4002 send_to_server (rs->name, 0);
4004 send_to_server ("\012", 1);
4006 send_to_server ("valid-requests\012", 0);
4008 if (get_server_responses ())
4009 exit (EXIT_FAILURE);
4011 have_global = supported_request ("Global_option");
4013 /* Encryption needs to come before compression. Good encryption can
4014 * render compression useless in the other direction.
4016 if (cvsencrypt && !rootless)
4018 #ifdef ENCRYPTION
4019 /* Turn on encryption before turning on compression. We do
4020 * not want to try to compress the encrypted stream. Instead,
4021 * we want to encrypt the compressed stream. If we can't turn
4022 * on encryption, bomb out; don't let the user think the data
4023 * is being encrypted when it is not.
4025 # ifdef HAVE_KERBEROS
4026 if (current_parsed_root->method == kserver_method)
4028 if (!supported_request ("Kerberos-encrypt"))
4029 error (1, 0, "This server does not support encryption");
4030 send_to_server ("Kerberos-encrypt\012", 0);
4031 initialize_kerberos4_encryption_buffers (&global_to_server,
4032 &global_from_server);
4034 else
4035 # endif /* HAVE_KERBEROS */
4036 # ifdef HAVE_GSSAPI
4037 if (current_parsed_root->method == gserver_method)
4039 if (!supported_request ("Gssapi-encrypt"))
4040 error (1, 0, "This server does not support encryption");
4041 send_to_server ("Gssapi-encrypt\012", 0);
4042 initialize_gssapi_buffers (&global_to_server,
4043 &global_from_server);
4044 cvs_gssapi_encrypt = 1;
4046 else
4047 # endif /* HAVE_GSSAPI */
4048 error (1, 0,
4049 "Encryption is only supported when using GSSAPI or Kerberos");
4050 #else /* ! ENCRYPTION */
4051 error (1, 0, "This client does not support encryption");
4052 #endif /* ! ENCRYPTION */
4055 if (nolock && !noexec)
4057 if (have_global)
4059 send_to_server ("Global_option -u\012", 0);
4061 else
4062 error (1, 0,
4063 "This server does not support the global -u option.");
4065 /* Send this before compression to enable supression of the
4066 * "Forcing compression level Z" messages.
4068 if (quiet)
4070 if (have_global)
4072 send_to_server ("Global_option -q\012", 0);
4074 else
4075 error (1, 0,
4076 "This server does not support the global -q option.");
4078 if (really_quiet)
4080 if (have_global)
4082 send_to_server ("Global_option -Q\012", 0);
4084 else
4085 error (1, 0,
4086 "This server does not support the global -Q option.");
4089 /* Compression needs to come before any of the rooted requests to
4090 * work with compression limits.
4092 if (!rootless && (gzip_level || force_gzip))
4094 if (supported_request ("Gzip-stream"))
4096 char *gzip_level_buf = Xasprintf ("%d", gzip_level);
4097 send_to_server ("Gzip-stream ", 0);
4098 send_to_server (gzip_level_buf, 0);
4099 free (gzip_level_buf);
4100 send_to_server ("\012", 1);
4102 /* All further communication with the server will be
4103 compressed. */
4105 global_to_server =
4106 compress_buffer_initialize (global_to_server, 0,
4107 gzip_level, NULL);
4108 global_from_server =
4109 compress_buffer_initialize (global_from_server, 1,
4110 gzip_level, NULL);
4112 #ifndef NO_CLIENT_GZIP_PROCESS
4113 else if (supported_request ("gzip-file-contents"))
4115 char *gzip_level_buf = Xasprintf ("%d", gzip_level);
4116 send_to_server ("gzip-file-contents ", 0);
4117 send_to_server (gzip_level_buf, 0);
4118 free (gzip_level_buf);
4119 send_to_server ("\012", 1);
4121 file_gzip_level = gzip_level;
4123 #endif
4124 else
4126 fprintf (stderr, "server doesn't support gzip-file-contents\n");
4127 /* Setting gzip_level to 0 prevents us from giving the
4128 error twice if update has to contact the server again
4129 to fetch unpatchable files. */
4130 gzip_level = 0;
4134 if (client_referrer && supported_request ("Referrer"))
4136 send_to_server ("Referrer ", 0);
4137 send_to_server (client_referrer->original, 0);
4138 send_to_server ("\012", 0);
4141 /* FIXME: I think we should still be sending this for init. */
4142 if (!rootless && supported_request ("Command-prep"))
4144 send_to_server ("Command-prep ", 0);
4145 send_to_server (cvs_cmd_name, 0);
4146 send_to_server ("\012", 0);
4147 status = get_server_responses ();
4148 if (status == 1) exit (EXIT_FAILURE);
4149 if (status == 2) close_connection_to_server (&global_to_server,
4150 &global_from_server);
4152 else status = 0;
4153 } while (status == 2);
4157 * Now handle global options.
4159 * -H, -f, -d, -e should be handled OK locally.
4161 * -b we ignore (treating it as a server installation issue).
4162 * FIXME: should be an error message.
4164 * -v we print local version info; FIXME: Add a protocol request to get
4165 * the version from the server so we can print that too.
4167 * -l -t -r -w -q -n and -Q need to go to the server.
4169 if (noexec)
4171 if (have_global)
4173 send_to_server ("Global_option -n\012", 0);
4175 else
4176 error (1, 0,
4177 "This server does not support the global -n option.");
4179 if (!cvswrite)
4181 if (have_global)
4183 send_to_server ("Global_option -r\012", 0);
4185 else
4186 error (1, 0,
4187 "This server does not support the global -r option.");
4189 if (trace)
4191 if (have_global)
4193 int count = trace;
4194 while (count--) send_to_server ("Global_option -t\012", 0);
4196 else
4197 error (1, 0,
4198 "This server does not support the global -t option.");
4201 /* Find out about server-side cvswrappers. An extra network
4202 turnaround for cvs import seems to be unavoidable, unless we
4203 want to add some kind of client-side place to configure which
4204 filenames imply binary. For cvs add, we could avoid the
4205 problem by keeping a copy of the wrappers in CVSADM (the main
4206 reason to bother would be so we could make add work without
4207 contacting the server, I suspect). */
4209 if (!strcmp (cvs_cmd_name, "import") || !strcmp (cvs_cmd_name, "add"))
4211 if (supported_request ("wrapper-sendme-rcsOptions"))
4213 int err;
4214 send_to_server ("wrapper-sendme-rcsOptions\012", 0);
4215 err = get_server_responses ();
4216 if (err != 0)
4217 error (err, 0, "error reading from server");
4221 if (cvsauthenticate && ! cvsencrypt && !rootless)
4223 /* Turn on authentication after turning on compression, so
4224 that we can compress the authentication information. We
4225 assume that encrypted data is always authenticated--the
4226 ability to decrypt the data stream is itself a form of
4227 authentication. */
4228 #ifdef HAVE_GSSAPI
4229 if (current_parsed_root->method == gserver_method)
4231 if (! supported_request ("Gssapi-authenticate"))
4232 error (1, 0,
4233 "This server does not support stream authentication");
4234 send_to_server ("Gssapi-authenticate\012", 0);
4235 initialize_gssapi_buffers(&global_to_server, &global_from_server);
4238 else
4239 error (1, 0, "Stream authentication is only supported when using GSSAPI");
4240 #else /* ! HAVE_GSSAPI */
4241 error (1, 0, "This client does not support stream authentication");
4242 #endif /* ! HAVE_GSSAPI */
4245 /* If "Set" is not supported, just silently fail to send the variables.
4246 Users with an old server should get a useful error message when it
4247 fails to recognize the ${=foo} syntax. This way if someone uses
4248 several servers, some of which are new and some old, they can still
4249 set user variables in their .cvsrc without trouble. */
4250 if (supported_request ("Set"))
4251 walklist (variable_list, send_variable_proc, NULL);
4256 /* Send an argument STRING. */
4257 void
4258 send_arg (const char *string)
4260 const char *p = string;
4262 send_to_server ("Argument ", 0);
4264 while (*p)
4266 if (*p == '\n')
4267 send_to_server ("\012Argumentx ", 0);
4268 else
4269 send_to_server (p, 1);
4270 ++p;
4272 send_to_server ("\012", 1);
4277 /* VERS->OPTIONS specifies whether the file is binary or not. NOTE: BEFORE
4278 using any other fields of the struct vers, we would need to fix
4279 client_process_import_file to set them up. */
4280 static void
4281 send_modified (const char *file, const char *short_pathname, Vers_TS *vers)
4283 /* File was modified, send it. */
4284 struct stat sb;
4285 int fd;
4286 unsigned char *buf;
4287 char *mode_string;
4288 size_t bufsize;
4289 int bin;
4291 TRACE (TRACE_FUNCTION, "Sending file `%s' to server", file);
4293 /* Don't think we can assume fstat exists. */
4294 if (stat (file, &sb) < 0)
4295 error (1, errno, "reading %s", short_pathname);
4297 mode_string = mode_to_string (sb.st_mode);
4299 /* Beware: on systems using CRLF line termination conventions,
4300 the read and write functions will convert CRLF to LF, so the
4301 number of characters read is not the same as sb.st_size. Text
4302 files should always be transmitted using the LF convention, so
4303 we don't want to disable this conversion. */
4304 bufsize = sb.st_size;
4305 buf = xmalloc (bufsize);
4307 /* Is the file marked as containing binary data by the "-kb" flag?
4308 If so, make sure to open it in binary mode: */
4310 if (vers && vers->options)
4311 bin = !strcmp (vers->options, "-kb");
4312 else
4313 bin = 0;
4315 #ifdef BROKEN_READWRITE_CONVERSION
4316 if (!bin)
4318 /* If only stdio, not open/write/etc., do text/binary
4319 conversion, use convert_file which can compensate
4320 (FIXME: we could just use stdio instead which would
4321 avoid the whole problem). */
4322 char *tfile = Xasprintf ("%s.CVSBFCTMP", file);
4323 convert_file (file, O_RDONLY,
4324 tfile, O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY);
4325 fd = CVS_OPEN (tfile, O_RDONLY | OPEN_BINARY);
4326 if (fd < 0)
4327 error (1, errno, "reading %s", short_pathname);
4328 free (tfile);
4330 else
4331 fd = CVS_OPEN (file, O_RDONLY | OPEN_BINARY);
4332 #else
4333 fd = CVS_OPEN (file, O_RDONLY | (bin ? OPEN_BINARY : 0));
4334 #endif
4336 if (fd < 0)
4337 error (1, errno, "reading %s", short_pathname);
4339 if (file_gzip_level && sb.st_size > 100)
4341 size_t newsize = 0;
4343 if (read_and_gzip (fd, short_pathname, &buf,
4344 &bufsize, &newsize,
4345 file_gzip_level))
4346 error (1, 0, "aborting due to compression error");
4348 if (close (fd) < 0)
4349 error (0, errno, "warning: can't close %s", short_pathname);
4352 char tmp[80];
4354 send_to_server ("Modified ", 0);
4355 send_to_server (file, 0);
4356 send_to_server ("\012", 1);
4357 send_to_server (mode_string, 0);
4358 send_to_server ("\012z", 2);
4359 sprintf (tmp, "%lu\n", (unsigned long) newsize);
4360 send_to_server (tmp, 0);
4362 send_to_server (buf, newsize);
4365 else
4367 int newsize;
4370 unsigned char *bufp = buf;
4371 int len;
4373 /* FIXME: This is gross. It assumes that we might read
4374 less than st_size bytes (true on NT), but not more.
4375 Instead of this we should just be reading a block of
4376 data (e.g. 8192 bytes), writing it to the network, and
4377 so on until EOF. */
4378 while ((len = read (fd, bufp, (buf + sb.st_size) - bufp)) > 0)
4379 bufp += len;
4381 if (len < 0)
4382 error (1, errno, "reading %s", short_pathname);
4384 newsize = bufp - buf;
4386 if (close (fd) < 0)
4387 error (0, errno, "warning: can't close %s", short_pathname);
4390 char tmp[80];
4392 send_to_server ("Modified ", 0);
4393 send_to_server (file, 0);
4394 send_to_server ("\012", 1);
4395 send_to_server (mode_string, 0);
4396 send_to_server ("\012", 1);
4397 sprintf (tmp, "%lu\012", (unsigned long) newsize);
4398 send_to_server (tmp, 0);
4400 #ifdef BROKEN_READWRITE_CONVERSION
4401 if (!bin)
4403 char *tfile = Xasprintf ("%s.CVSBFCTMP", file);
4404 if (CVS_UNLINK (tfile) < 0)
4405 error (0, errno, "warning: can't remove temp file %s", tfile);
4406 free (tfile);
4408 #endif
4411 * Note that this only ends with a newline if the file ended with
4412 * one.
4414 if (newsize > 0)
4415 send_to_server (buf, newsize);
4417 free (buf);
4418 free (mode_string);
4423 /* The address of an instance of this structure is passed to
4424 send_fileproc, send_filesdoneproc, and send_direntproc, as the
4425 callerdat parameter. */
4426 struct send_data
4428 /* Each of the following flags are zero for clear or nonzero for set. */
4429 int build_dirs;
4430 int force;
4431 int no_contents;
4432 int backup_modified;
4435 /* Deal with one file. */
4436 static int
4437 send_fileproc (void *callerdat, struct file_info *finfo)
4439 struct send_data *args = callerdat;
4440 Vers_TS *vers;
4441 struct file_info xfinfo;
4442 /* File name to actually use. Might differ in case from
4443 finfo->file. */
4444 const char *filename;
4446 send_a_repository ("", finfo->repository, finfo->update_dir);
4448 xfinfo = *finfo;
4449 xfinfo.repository = NULL;
4450 xfinfo.rcs = NULL;
4451 vers = Version_TS (&xfinfo, NULL, NULL, NULL, 0, 0);
4453 if (vers->entdata)
4454 filename = vers->entdata->user;
4455 else
4456 filename = finfo->file;
4458 if (vers->vn_user)
4460 /* The Entries request. */
4461 send_to_server ("Entry /", 0);
4462 send_to_server (filename, 0);
4463 send_to_server ("/", 0);
4464 send_to_server (vers->vn_user, 0);
4465 send_to_server ("/", 0);
4466 if (vers->ts_conflict)
4468 if (vers->ts_user && !strcmp (vers->ts_conflict, vers->ts_user))
4469 send_to_server ("+=", 0);
4470 else
4471 send_to_server ("+modified", 0);
4473 send_to_server ("/", 0);
4474 send_to_server (vers->entdata ? vers->entdata->options : vers->options,
4476 send_to_server ("/", 0);
4477 if (vers->entdata && vers->entdata->tag)
4479 send_to_server ("T", 0);
4480 send_to_server (vers->entdata->tag, 0);
4482 else if (vers->entdata && vers->entdata->date)
4484 send_to_server ("D", 0);
4485 send_to_server (vers->entdata->date, 0);
4487 send_to_server ("\012", 1);
4489 else
4491 /* It seems a little silly to re-read this on each file, but
4492 send_dirent_proc doesn't get called if filenames are specified
4493 explicitly on the command line. */
4494 wrap_add_file (CVSDOTWRAPPER, 1);
4496 if (wrap_name_has (filename, WRAP_RCSOPTION))
4498 /* No "Entry", but the wrappers did give us a kopt so we better
4499 send it with "Kopt". As far as I know this only happens
4500 for "cvs add". Question: is there any reason why checking
4501 for options from wrappers isn't done in Version_TS?
4503 Note: it might have been better to just remember all the
4504 kopts on the client side, rather than send them to the server,
4505 and have it send us back the same kopts. But that seemed like
4506 a bigger change than I had in mind making now. */
4508 if (supported_request ("Kopt"))
4510 char *opt;
4512 send_to_server ("Kopt ", 0);
4513 opt = wrap_rcsoption (filename, 1);
4514 send_to_server (opt, 0);
4515 send_to_server ("\012", 1);
4516 free (opt);
4518 else
4519 error (0, 0, "\
4520 warning: ignoring -k options due to server limitations");
4524 if (!vers->ts_user)
4527 * Do we want to print "file was lost" like normal CVS?
4528 * Would it always be appropriate?
4530 /* File no longer exists. Don't do anything, missing files
4531 just happen. */
4533 else if (!vers->ts_rcs || args->force
4534 || strcmp (vers->ts_conflict
4535 ? vers->ts_conflict : vers->ts_rcs, vers->ts_user)
4536 || (vers->ts_conflict && !strcmp (cvs_cmd_name, "diff")))
4538 if (args->no_contents
4539 && supported_request ("Is-modified"))
4541 send_to_server ("Is-modified ", 0);
4542 send_to_server (filename, 0);
4543 send_to_server ("\012", 1);
4545 else
4546 send_modified (filename, finfo->fullname, vers);
4548 if (args->backup_modified)
4550 char *bakname;
4551 bakname = backup_file (filename, vers->vn_user);
4552 /* This behavior is sufficiently unexpected to
4553 justify overinformativeness, I think. */
4554 if (! really_quiet)
4555 printf ("(Locally modified %s moved to %s)\n",
4556 filename, bakname);
4557 free (bakname);
4560 else
4562 send_to_server ("Unchanged ", 0);
4563 send_to_server (filename, 0);
4564 send_to_server ("\012", 1);
4567 /* if this directory has an ignore list, add this file to it */
4568 if (ignlist)
4570 Node *p;
4572 p = getnode ();
4573 p->type = FILES;
4574 p->key = xstrdup (finfo->file);
4575 (void) addnode (ignlist, p);
4578 freevers_ts (&vers);
4579 return 0;
4584 static void
4585 send_ignproc (const char *file, const char *dir)
4587 if (ign_inhibit_server || !supported_request ("Questionable"))
4589 if (dir[0] != '\0')
4590 (void) printf ("? %s/%s\n", dir, file);
4591 else
4592 (void) printf ("? %s\n", file);
4594 else
4596 send_to_server ("Questionable ", 0);
4597 send_to_server (file, 0);
4598 send_to_server ("\012", 1);
4604 static int
4605 send_filesdoneproc (void *callerdat, int err, const char *repository,
4606 const char *update_dir, List *entries)
4608 /* if this directory has an ignore list, process it then free it */
4609 if (ignlist)
4611 ignore_files (ignlist, entries, update_dir, send_ignproc);
4612 dellist (&ignlist);
4615 return err;
4621 * send_dirent_proc () is called back by the recursion processor before a
4622 * sub-directory is processed for update.
4623 * A return code of 0 indicates the directory should be
4624 * processed by the recursion code. A return of non-zero indicates the
4625 * recursion code should skip this directory.
4628 static Dtype
4629 send_dirent_proc (void *callerdat, const char *dir, const char *repository,
4630 const char *update_dir, List *entries)
4632 struct send_data *args = callerdat;
4633 int dir_exists;
4634 char *cvsadm_name;
4636 if (ignore_directory (update_dir))
4638 /* print the warm fuzzy message */
4639 if (!quiet)
4640 error (0, 0, "Ignoring %s", update_dir);
4641 return R_SKIP_ALL;
4645 * If the directory does not exist yet (e.g. "cvs update -d foo"),
4646 * no need to send any files from it. If the directory does not
4647 * have a CVS directory, then we pretend that it does not exist.
4648 * Otherwise, we will fail when trying to open the Entries file.
4649 * This case will happen when checking out a module defined as
4650 * ``-a .''.
4652 cvsadm_name = Xasprintf ("%s/%s", dir, CVSADM);
4653 dir_exists = isdir (cvsadm_name);
4654 free (cvsadm_name);
4657 * If there is an empty directory (e.g. we are doing `cvs add' on a
4658 * newly-created directory), the server still needs to know about it.
4661 if (dir_exists)
4664 * Get the repository from a CVS/Repository file whenever possible.
4665 * The repository variable is wrong if the names in the local
4666 * directory don't match the names in the repository.
4668 char *repos = Name_Repository (dir, update_dir);
4669 send_a_repository (dir, repos, update_dir);
4670 free (repos);
4672 /* initialize the ignore list for this directory */
4673 ignlist = getlist ();
4675 else
4677 /* It doesn't make sense to send a non-existent directory,
4678 because there is no way to get the correct value for
4679 the repository (I suppose maybe via the expand-modules
4680 request). In the case where the "obvious" choice for
4681 repository is correct, the server can figure out whether
4682 to recreate the directory; in the case where it is wrong
4683 (that is, does not match what modules give us), we might as
4684 well just fail to recreate it.
4686 Checking for noexec is a kludge for "cvs -n add dir". */
4687 /* Don't send a non-existent directory unless we are building
4688 new directories (build_dirs is true). Otherwise, CVS may
4689 see a D line in an Entries file, and recreate a directory
4690 which the user removed by hand. */
4691 if (args->build_dirs && noexec)
4692 send_a_repository (dir, repository, update_dir);
4695 return dir_exists ? R_PROCESS : R_SKIP_ALL;
4701 * send_dirleave_proc () is called back by the recursion code upon leaving
4702 * a directory. All it does is delete the ignore list if it hasn't already
4703 * been done (by send_filesdone_proc).
4705 /* ARGSUSED */
4706 static int
4707 send_dirleave_proc (void *callerdat, const char *dir, int err,
4708 const char *update_dir, List *entries )
4711 /* Delete the ignore list if it hasn't already been done. */
4712 if (ignlist)
4713 dellist (&ignlist);
4714 return err;
4720 * Send each option in an array to the server, one by one.
4721 * argv might be "--foo=bar", "-C", "5", "-y".
4724 void
4725 send_options (int argc, char * const *argv)
4727 int i;
4728 for (i = 0; i < argc; i++)
4729 send_arg (argv[i]);
4734 /* Send the names of all the argument files to the server. */
4735 void
4736 send_file_names (int argc, char **argv, unsigned int flags)
4738 int i;
4740 /* The fact that we do this here as well as start_recursion is a bit
4741 of a performance hit. Perhaps worth cleaning up someday. */
4742 if (flags & SEND_EXPAND_WILD)
4743 expand_wild (argc, argv, &argc, &argv);
4745 for (i = 0; i < argc; ++i)
4747 char buf[1];
4748 char *p;
4749 #ifdef FILENAMES_CASE_INSENSITIVE
4750 char *line = NULL;
4751 #endif /* FILENAMES_CASE_INSENSITIVE */
4753 if (arg_should_not_be_sent_to_server (argv[i]))
4754 continue;
4756 #ifdef FILENAMES_CASE_INSENSITIVE
4757 /* We want to send the path as it appears in the
4758 CVS/Entries files. We put this inside an ifdef
4759 to avoid doing all these system calls in
4760 cases where fncmp is just strcmp anyway. */
4761 /* The isdir (CVSADM) check could more gracefully be replaced
4762 with a way of having Entries_Open report back the
4763 error to us and letting us ignore existence_error.
4764 Or some such. */
4766 List *stack;
4767 size_t line_len = 0;
4768 char *q, *r;
4769 struct saved_cwd sdir;
4771 /* Split the argument onto the stack. */
4772 stack = getlist();
4773 r = xstrdup (argv[i]);
4774 /* It's okay to discard the const from the last_component return
4775 * below since we know we passed in an arg that was not const.
4777 while ((q = (char *)last_component (r)) != r)
4779 push (stack, xstrdup (q));
4780 *--q = '\0';
4782 push (stack, r);
4784 /* Normalize the path into outstr. */
4785 save_cwd (&sdir);
4786 while (q = pop (stack))
4788 Node *node = NULL;
4789 if (isdir (CVSADM))
4791 List *entries;
4793 /* Note that if we are adding a directory,
4794 the following will read the entry
4795 that we just wrote there, that is, we
4796 will get the case specified on the
4797 command line, not the case of the
4798 directory in the filesystem. This
4799 is correct behavior. */
4800 entries = Entries_Open (0, NULL);
4801 node = findnode_fn (entries, q);
4802 if (node)
4804 /* Add the slash unless this is our first element. */
4805 if (line_len)
4806 xrealloc_and_strcat (&line, &line_len, "/");
4807 xrealloc_and_strcat (&line, &line_len, node->key);
4808 delnode (node);
4810 Entries_Close (entries);
4813 /* If node is still NULL then we either didn't find CVSADM or
4814 * we didn't find an entry there.
4816 if (!node)
4818 /* Add the slash unless this is our first element. */
4819 if (line_len)
4820 xrealloc_and_strcat (&line, &line_len, "/");
4821 xrealloc_and_strcat (&line, &line_len, q);
4822 break;
4825 /* And descend the tree. */
4826 if (isdir (q))
4827 CVS_CHDIR (q);
4828 free (q);
4830 restore_cwd (&sdir);
4831 free_cwd (&sdir);
4833 /* Now put everything we didn't find entries for back on. */
4834 while (q = pop (stack))
4836 if (line_len)
4837 xrealloc_and_strcat (&line, &line_len, "/");
4838 xrealloc_and_strcat (&line, &line_len, q);
4839 free (q);
4842 p = line;
4844 dellist (&stack);
4846 #else /* !FILENAMES_CASE_INSENSITIVE */
4847 p = argv[i];
4848 #endif /* FILENAMES_CASE_INSENSITIVE */
4850 send_to_server ("Argument ", 0);
4852 while (*p)
4854 if (*p == '\n')
4856 send_to_server ("\012Argumentx ", 0);
4858 else if (ISSLASH (*p))
4860 buf[0] = '/';
4861 send_to_server (buf, 1);
4863 else
4865 buf[0] = *p;
4866 send_to_server (buf, 1);
4868 ++p;
4870 send_to_server ("\012", 1);
4871 #ifdef FILENAMES_CASE_INSENSITIVE
4872 free (line);
4873 #endif /* FILENAMES_CASE_INSENSITIVE */
4876 if (flags & SEND_EXPAND_WILD)
4878 int i;
4879 for (i = 0; i < argc; ++i)
4880 free (argv[i]);
4881 free (argv);
4887 /* Calculate and send max-dotdot to the server */
4888 static void
4889 send_max_dotdot (argc, argv)
4890 int argc;
4891 char **argv;
4893 int i;
4894 int level = 0;
4895 int max_level = 0;
4897 /* Send Max-dotdot if needed. */
4898 for (i = 0; i < argc; ++i)
4900 level = pathname_levels (argv[i]);
4901 if (level > 0)
4903 if (!uppaths) uppaths = getlist();
4904 push_string (uppaths, xstrdup (argv[i]));
4906 if (level > max_level)
4907 max_level = level;
4910 if (max_level > 0)
4912 if (supported_request ("Max-dotdot"))
4914 char buf[10];
4915 sprintf (buf, "%d", max_level);
4917 send_to_server ("Max-dotdot ", 0);
4918 send_to_server (buf, 0);
4919 send_to_server ("\012", 1);
4921 else
4923 error (1, 0,
4924 "backreference in path (`..') not supported by old (pre-Max-dotdot) servers");
4931 /* Send Repository, Modified and Entry. argc and argv contain only
4932 the files to operate on (or empty for everything), not options.
4933 local is nonzero if we should not recurse (-l option). flags &
4934 SEND_BUILD_DIRS is nonzero if nonexistent directories should be
4935 sent. flags & SEND_FORCE is nonzero if we should send unmodified
4936 files to the server as though they were modified. flags &
4937 SEND_NO_CONTENTS means that this command only needs to know
4938 _whether_ a file is modified, not the contents. Also sends Argument
4939 lines for argc and argv, so should be called after options are sent. */
4940 void
4941 send_files (int argc, char **argv, int local, int aflag, unsigned int flags)
4943 struct send_data args;
4944 int err;
4946 send_max_dotdot (argc, argv);
4949 * aflag controls whether the tag/date is copied into the vers_ts.
4950 * But we don't actually use it, so I don't think it matters what we pass
4951 * for aflag here.
4953 args.build_dirs = flags & SEND_BUILD_DIRS;
4954 args.force = flags & SEND_FORCE;
4955 args.no_contents = flags & SEND_NO_CONTENTS;
4956 args.backup_modified = flags & BACKUP_MODIFIED_FILES;
4957 err = start_recursion
4958 (send_fileproc, send_filesdoneproc, send_dirent_proc,
4959 send_dirleave_proc, &args, argc, argv, local, W_LOCAL, aflag,
4960 CVS_LOCK_NONE, NULL, 0, NULL);
4961 if (err)
4962 exit (EXIT_FAILURE);
4963 if (!toplevel_repos)
4965 * This happens if we are not processing any files,
4966 * or for checkouts in directories without any existing stuff
4967 * checked out. The following assignment is correct for the
4968 * latter case; I don't think toplevel_repos matters for the
4969 * former.
4971 toplevel_repos = xstrdup (current_parsed_root->directory);
4972 send_repository ("", toplevel_repos, ".");
4977 void
4978 client_import_setup (char *repository)
4980 if (!toplevel_repos) /* should always be true */
4981 send_a_repository ("", repository, "");
4987 * Process the argument import file.
4990 client_process_import_file (char *message, char *vfile, char *vtag, int targc,
4991 char *targv[], char *repository,
4992 int all_files_binary,
4993 int modtime /* Nonzero for "import -d". */ )
4995 char *update_dir;
4996 char *fullname;
4997 Vers_TS vers;
4999 assert (toplevel_repos);
5001 if (strncmp (repository, toplevel_repos, strlen (toplevel_repos)))
5002 error (1, 0,
5003 "internal error: pathname `%s' doesn't specify file in `%s'",
5004 repository, toplevel_repos);
5006 if (!strcmp (repository, toplevel_repos))
5008 update_dir = "";
5009 fullname = xstrdup (vfile);
5011 else
5013 update_dir = repository + strlen (toplevel_repos) + 1;
5015 fullname = Xasprintf ("%s/%s", update_dir, vfile);
5018 send_a_repository ("", repository, update_dir);
5019 if (all_files_binary)
5020 vers.options = xstrdup ("-kb");
5021 else
5022 vers.options = wrap_rcsoption (vfile, 1);
5024 if (vers.options)
5026 if (supported_request ("Kopt"))
5028 send_to_server ("Kopt ", 0);
5029 send_to_server (vers.options, 0);
5030 send_to_server ("\012", 1);
5032 else
5033 error (0, 0,
5034 "warning: ignoring -k options due to server limitations");
5036 if (modtime)
5038 if (supported_request ("Checkin-time"))
5040 struct stat sb;
5041 char *rcsdate;
5042 char netdate[MAXDATELEN];
5044 if (stat (vfile, &sb) < 0)
5045 error (1, errno, "cannot stat %s", fullname);
5046 rcsdate = date_from_time_t (sb.st_mtime);
5047 date_to_internet (netdate, rcsdate);
5048 free (rcsdate);
5050 send_to_server ("Checkin-time ", 0);
5051 send_to_server (netdate, 0);
5052 send_to_server ("\012", 1);
5054 else
5055 error (0, 0,
5056 "warning: ignoring -d option due to server limitations");
5058 send_modified (vfile, fullname, &vers);
5059 if (vers.options)
5060 free (vers.options);
5061 free (fullname);
5062 return 0;
5067 void
5068 client_import_done (void)
5070 if (!toplevel_repos)
5072 * This happens if we are not processing any files,
5073 * or for checkouts in directories without any existing stuff
5074 * checked out. The following assignment is correct for the
5075 * latter case; I don't think toplevel_repos matters for the
5076 * former.
5078 /* FIXME: "can't happen" now that we call client_import_setup
5079 at the beginning. */
5080 toplevel_repos = xstrdup (current_parsed_root->directory);
5081 send_repository ("", toplevel_repos, ".");
5086 void
5087 client_notify (const char *repository, const char *update_dir,
5088 const char *filename, int notif_type, const char *val)
5090 char buf[2];
5092 send_a_repository ("", repository, update_dir);
5093 send_to_server ("Notify ", 0);
5094 send_to_server (filename, 0);
5095 send_to_server ("\012", 1);
5096 buf[0] = notif_type;
5097 buf[1] = '\0';
5098 send_to_server (buf, 1);
5099 send_to_server ("\t", 1);
5100 send_to_server (val, 0);
5106 * Send an option with an argument, dealing correctly with newlines in
5107 * the argument. If ARG is NULL, forget the whole thing.
5109 void
5110 option_with_arg (const char *option, const char *arg)
5112 if (!arg)
5113 return;
5115 send_to_server ("Argument ", 0);
5116 send_to_server (option, 0);
5117 send_to_server ("\012", 1);
5119 send_arg (arg);
5124 /* Send a date to the server. The input DATE is in RCS format.
5125 The time will be GMT.
5127 We then convert that to the format required in the protocol
5128 (including the "-D" option) and send it. According to
5129 cvsclient.texi, RFC 822/1123 format is preferred. */
5130 void
5131 client_senddate (const char *date)
5133 char buf[MAXDATELEN];
5135 date_to_internet (buf, date);
5136 option_with_arg ("-D", buf);
5141 void
5142 send_init_command (void)
5144 /* This is here because we need the current_parsed_root->directory variable. */
5145 send_to_server ("init ", 0);
5146 send_to_server (current_parsed_root->directory, 0);
5147 send_to_server ("\012", 0);
5152 #if defined AUTH_CLIENT_SUPPORT || defined HAVE_KERBEROS || defined HAVE_GSSAPI
5155 connect_to(char *hostname, unsigned int port)
5157 struct addrinfo hints, *res, *res0 = NULL;
5158 char pbuf[10];
5159 int e, sock;
5161 memset(&hints, 0, sizeof(hints));
5162 hints.ai_family = PF_UNSPEC;
5163 hints.ai_socktype = SOCK_STREAM;
5164 hints.ai_flags = AI_CANONNAME;
5166 snprintf(pbuf, sizeof(pbuf), "%d", port);
5167 e = getaddrinfo(hostname, pbuf, &hints, &res0);
5168 if (e)
5170 error (1, 0, "%s", gai_strerror(e));
5172 sock = -1;
5173 for (res = res0; res; res = res->ai_next) {
5174 sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
5175 if (sock < 0)
5176 continue;
5178 TRACE (TRACE_FUNCTION, " -> Connecting to %s\n", hostname);
5179 if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
5180 close(sock);
5181 sock = -1;
5182 continue;
5184 break;
5186 freeaddrinfo(res0);
5187 return sock;
5190 #endif /* defined AUTH_CLIENT_SUPPORT || defined HAVE_KERBEROS
5191 * || defined HAVE_GSSAPI
5194 #endif /* CLIENT_SUPPORT */