PageRenderTime 122ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/cvs/src/client.c

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