diff options
Diffstat (limited to 'contrib/cvs/src/server.c')
-rw-r--r-- | contrib/cvs/src/server.c | 172 |
1 files changed, 125 insertions, 47 deletions
diff --git a/contrib/cvs/src/server.c b/contrib/cvs/src/server.c index bc6578d76d20..29aab007efda 100644 --- a/contrib/cvs/src/server.c +++ b/contrib/cvs/src/server.c @@ -16,6 +16,8 @@ #include "getline.h" #include "buffer.h" +int server_active = 0; + #if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT) # ifdef HAVE_GSSAPI /* This stuff isn't included solely with SERVER_SUPPORT since some of these @@ -356,13 +358,20 @@ create_adm_p (base_dir, dir) dir_where_cvsadm_lives = xmalloc (strlen (base_dir) + strlen (dir) + 100); if (dir_where_cvsadm_lives == NULL) + { + free (p); return ENOMEM; + } /* Allocate some space for the temporary string in which we will construct filenames. */ tmp = xmalloc (strlen (base_dir) + strlen (dir) + 100); if (tmp == NULL) + { + free (p); + free (dir_where_cvsadm_lives); return ENOMEM; + } /* We make several passes through this loop. On the first pass, @@ -1227,6 +1236,7 @@ serve_sticky (arg) if (alloc_pending (80 + strlen (CVSADM_TAG))) sprintf (pending_error_text, "E cannot write to %s", CVSADM_TAG); pending_error = save_errno; + (void) fclose (f); return; } if (fclose (f) == EOF) @@ -1675,7 +1685,9 @@ serve_unchanged (arg) * is allowed, but broken versions of WinCVS & TortoiseCVS rely on * this behavior. */ - *timefield = '='; + if (*timefield != '+') + /* Skip this for entries with conflict markers. */ + *timefield = '='; break; } } @@ -1746,7 +1758,10 @@ serve_is_modified (arg) * is allowed, but broken versions of WinCVS & TortoiseCVS rely on * this behavior. */ - *timefield = 'M'; + if (*timefield != '+') + /* Skip this for entries with conflict markers. */ + *timefield = 'M'; + if (kopt != NULL) { if (alloc_pending (strlen (name) + 80)) @@ -1833,6 +1848,7 @@ serve_entry (arg) cp = xmalloc (strlen (arg) + 2); if (cp == NULL) { + free (p); pending_error = ENOMEM; return; } @@ -2696,6 +2712,25 @@ set_nonblock_fd (fd) +/* + * Set buffer FD to blocking I/O. Returns 0 for success or errno code. + */ +int +set_block_fd (fd) + int fd; +{ + int flags; + + flags = fcntl (fd, F_GETFL, 0); + if (flags < 0) + return errno; + if (fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) < 0) + return errno; + return 0; +} + + + static void do_cvs_command (cmd_name, command) char *cmd_name; @@ -2919,22 +2954,31 @@ error \n"); { char junk; ssize_t status; - while ((status = read (flowcontrol_pipe[0], &junk, 1)) > 0 - || (status == -1 && errno == EAGAIN)); + set_block_fd (flowcontrol_pipe[0]); + while ((status = read (flowcontrol_pipe[0], &junk, 1)) > 0); } /* FIXME: No point in printing an error message with error(), * as STDERR is already closed, but perhaps this could be syslogged? */ #endif + rcs_cleanup (); + Lock_Cleanup (); + /* Don't call server_cleanup - the parent will handle that. */ +#ifdef SYSTEM_CLEANUP + /* Hook for OS-specific behavior, for example socket subsystems on + NT and OS2 or dealing with windows and arguments on Mac. */ + SYSTEM_CLEANUP (); +#endif exit (exitstatus); } /* OK, sit around getting all the input from the child. */ { - struct buffer *stdoutbuf; - struct buffer *stderrbuf; - struct buffer *protocol_inbuf; + struct buffer *stdoutbuf = NULL; + struct buffer *stderrbuf = NULL; + struct buffer *protocol_inbuf = NULL; + int err_exit = 0; /* Number of file descriptors to check in select (). */ int num_to_check; int count_needed = 1; @@ -2987,7 +3031,8 @@ error \n"); { buf_output0 (buf_to_net, "E close failed\n"); print_error (errno); - goto error_exit; + err_exit = 1; + goto child_finish; } stdout_pipe[1] = -1; @@ -2995,7 +3040,8 @@ error \n"); { buf_output0 (buf_to_net, "E close failed\n"); print_error (errno); - goto error_exit; + err_exit = 1; + goto child_finish; } stderr_pipe[1] = -1; @@ -3003,7 +3049,8 @@ error \n"); { buf_output0 (buf_to_net, "E close failed\n"); print_error (errno); - goto error_exit; + err_exit = 1; + goto child_finish; } protocol_pipe[1] = -1; @@ -3012,7 +3059,8 @@ error \n"); { buf_output0 (buf_to_net, "E close failed\n"); print_error (errno); - goto error_exit; + err_exit = 1; + goto child_finish; } flowcontrol_pipe[0] = -1; #endif /* SERVER_FLOWCONTROL */ @@ -3021,7 +3069,9 @@ error \n"); { buf_output0 (buf_to_net, "E close failed\n"); print_error (errno); - goto error_exit; + dev_null_fd = -1; /* Do not try to close it again. */ + err_exit = 1; + goto child_finish; } dev_null_fd = -1; @@ -3108,7 +3158,8 @@ error \n"); { buf_output0 (buf_to_net, "E select failed\n"); print_error (errno); - goto error_exit; + err_exit = 1; + goto child_finish; } } while (numfds < 0); @@ -3141,7 +3192,8 @@ error \n"); { buf_output0 (buf_to_net, "E buf_input_data failed\n"); print_error (status); - goto error_exit; + err_exit = 1; + goto child_finish; } /* @@ -3215,7 +3267,8 @@ error \n"); { buf_output0 (buf_to_net, "E buf_input_data failed\n"); print_error (status); - goto error_exit; + err_exit = 1; + goto child_finish; } /* What should we do with errors? syslog() them? */ @@ -3240,7 +3293,8 @@ error \n"); { buf_output0 (buf_to_net, "E buf_input_data failed\n"); print_error (status); - goto error_exit; + err_exit = 1; + goto child_finish; } /* What should we do with errors? syslog() them? */ @@ -3320,21 +3374,33 @@ E CVS locks may need cleaning up.\n"); command_pid = -1; } + child_finish: /* * OK, we've waited for the child. By now all CVS locks are free * and it's OK to block on the network. */ set_block (buf_to_net); buf_flush (buf_to_net, 1); - buf_shutdown (protocol_inbuf); - buf_free (protocol_inbuf); - protocol_inbuf = NULL; - buf_shutdown (stderrbuf); - buf_free (stderrbuf); - stderrbuf = NULL; - buf_shutdown (stdoutbuf); - buf_free (stdoutbuf); - stdoutbuf = NULL; + if (protocol_inbuf) + { + buf_shutdown (protocol_inbuf); + buf_free (protocol_inbuf); + protocol_inbuf = NULL; + } + if (stderrbuf) + { + buf_shutdown (stderrbuf); + buf_free (stderrbuf); + stderrbuf = NULL; + } + if (stdoutbuf) + { + buf_shutdown (stdoutbuf); + buf_free (stdoutbuf); + stdoutbuf = NULL; + } + if (err_exit) + goto error_exit; } if (errs) @@ -3358,7 +3424,8 @@ E CVS locks may need cleaning up.\n"); command_pid = -1; } - close (dev_null_fd); + if (dev_null_fd >= 0) + close (dev_null_fd); close (protocol_pipe[0]); close (protocol_pipe[1]); close (stderr_pipe[0]); @@ -3686,6 +3753,10 @@ server_checked_in (file, update_dir, repository) const char *update_dir; const char *repository; { + assert (file); + assert (update_dir); + assert (repository); + if (noexec) return; if (scratched_file != NULL && entries_line == NULL) @@ -4119,6 +4190,7 @@ server_updated (finfo, vers, updated, mode, checksum, filebuf) free (scratched_file); scratched_file = NULL; } + buf_send_counted (protocol); return; } @@ -4197,7 +4269,6 @@ CVS server internal error: no mode in server_updated"); if (updated == SERVER_UPDATED) { Node *node; - Entnode *entnode; if (!(supported_response ("Created") && supported_response ("Update-existing"))) @@ -4215,9 +4286,13 @@ CVS server internal error: no mode in server_updated"); in case we end up processing it again (e.g. modules3-6 in the testsuite). */ node = findnode_fn (finfo->entries, finfo->file); - entnode = node->data; - free (entnode->timestamp); - entnode->timestamp = xstrdup ("="); + assert (node != NULL); + if (node != NULL) + { + Entnode *entnode = node->data; + free (entnode->timestamp); + entnode->timestamp = xstrdup ("="); + } } else if (updated == SERVER_MERGED) buf_output0 (protocol, "Merged "); @@ -4505,9 +4580,12 @@ struct template_proc_data static struct template_proc_data *tpd; static int +template_proc PROTO((const char *repository, const char *template)); + +static int template_proc (repository, template) - char *repository; - char *template; + const char *repository; + const char *template; { FILE *fp; char buf[1024]; @@ -4785,6 +4863,7 @@ struct request requests[] = REQ_LINE("Checkin-time", serve_checkin_time, 0), REQ_LINE("Modified", serve_modified, RQ_ESSENTIAL), REQ_LINE("Is-modified", serve_is_modified, 0), + REQ_LINE("Empty-conflicts", serve_noop, 0), /* The client must send this request to interoperate with CVS 1.5 through 1.9 servers. The server must support it (although it can @@ -5039,8 +5118,6 @@ server_cleanup (sig) } } -int server_active = 0; - int server (argc, argv) int argc; @@ -5472,6 +5549,7 @@ check_repository_password (username, password, repository, host_user_ptr) { if (!existence_error (errno)) error (0, errno, "cannot open %s", filename); + free (filename); return 0; } @@ -5902,6 +5980,8 @@ pserver_authenticate_connection () printf ("I LOVE YOU\n"); fflush (stdout); + /* It's okay to skip rcs_cleanup() and Lock_Cleanup() here. */ + #ifdef SYSTEM_CLEANUP /* Hook for OS-specific behavior, for example socket subsystems on NT and OS2 or dealing with windows and arguments on Mac. */ @@ -6415,12 +6495,10 @@ cvs_output (str, len) size_t to_write = len; const char *p = str; - /* For symmetry with cvs_outerr we would call fflush (stderr) - here. I guess the assumption is that stderr will be - unbuffered, so we don't need to. That sounds like a sound - assumption from the manpage I looked at, but if there was - something fishy about it, my guess is that calling fflush - would not produce a significant performance problem. */ + /* Local users that do 'cvs status 2>&1' on a local repository + may see the informational messages out-of-order with the + status messages unless we use the fflush (stderr) here. */ + fflush (stderr); while (to_write > 0) { @@ -6477,16 +6555,16 @@ this client does not support writing binary files to stdout"); size_t written; size_t to_write = len; const char *p = str; - - /* For symmetry with cvs_outerr we would call fflush (stderr) - here. I guess the assumption is that stderr will be - unbuffered, so we don't need to. That sounds like a sound - assumption from the manpage I looked at, but if there was - something fishy about it, my guess is that calling fflush - would not produce a significant performance problem. */ #ifdef USE_SETMODE_STDOUT int oldmode; +#endif + /* Local users that do 'cvs status 2>&1' on a local repository + may see the informational messages out-of-order with the + status messages unless we use the fflush (stderr) here. */ + fflush (stderr); + +#ifdef USE_SETMODE_STDOUT /* It is possible that this should be the same ifdef as USE_SETMODE_BINARY but at least for the moment we keep them separate. Mostly this is just laziness and/or a question |