764 |
static void |
static void |
765 |
serve_root (char *arg) |
serve_root (char *arg) |
766 |
{ |
{ |
|
char *env; |
|
767 |
char *path; |
char *path; |
768 |
|
|
769 |
TRACE (TRACE_FUNCTION, "serve_root (%s)", arg ? arg : "(null)"); |
TRACE (TRACE_FUNCTION, "serve_root (%s)", arg ? arg : "(null)"); |
848 |
} |
} |
849 |
# endif /* PROXY_SUPPORT */ |
# endif /* PROXY_SUPPORT */ |
850 |
|
|
851 |
|
/* Now set the TMPDIR environment variable. If it was set in the config |
852 |
|
* file, we now know it. |
853 |
|
*/ |
854 |
|
push_env_tmp_dir (); |
855 |
|
|
856 |
|
/* OK, now figure out where we stash our temporary files. */ |
857 |
|
{ |
858 |
|
char *p; |
859 |
|
|
860 |
|
/* The code which wants to chdir into server_temp_dir is not set |
861 |
|
* up to deal with it being a relative path. So give an error |
862 |
|
* for that case. |
863 |
|
*/ |
864 |
|
if (!ISABSOLUTE (get_cvs_tmp_dir ())) |
865 |
|
{ |
866 |
|
if (alloc_pending (80 + strlen (get_cvs_tmp_dir ()))) |
867 |
|
sprintf (pending_error_text, |
868 |
|
"E Value of %s for TMPDIR is not absolute", |
869 |
|
get_cvs_tmp_dir ()); |
870 |
|
|
871 |
|
/* FIXME: we would like this error to be persistent, that |
872 |
|
* is, not cleared by print_pending_error. The current client |
873 |
|
* will exit as soon as it gets an error, but the protocol spec |
874 |
|
* does not require a client to do so. |
875 |
|
*/ |
876 |
|
} |
877 |
|
else |
878 |
|
{ |
879 |
|
int status; |
880 |
|
int i = 0; |
881 |
|
|
882 |
|
server_temp_dir = xmalloc (strlen (get_cvs_tmp_dir ()) + 80); |
883 |
|
if (!server_temp_dir) |
884 |
|
{ |
885 |
|
/* Strictly speaking, we're not supposed to output anything |
886 |
|
* now. But we're about to exit(), give it a try. |
887 |
|
*/ |
888 |
|
printf ("E Fatal server error, aborting.\n\ |
889 |
|
error ENOMEM Virtual memory exhausted.\n"); |
890 |
|
|
891 |
|
exit (EXIT_FAILURE); |
892 |
|
} |
893 |
|
strcpy (server_temp_dir, get_cvs_tmp_dir ()); |
894 |
|
|
895 |
|
/* Remove a trailing slash from TMPDIR if present. */ |
896 |
|
p = server_temp_dir + strlen (server_temp_dir) - 1; |
897 |
|
if (*p == '/') |
898 |
|
*p = '\0'; |
899 |
|
|
900 |
|
/* I wanted to use cvs-serv/PID, but then you have to worry about |
901 |
|
* the permissions on the cvs-serv directory being right. So |
902 |
|
* use cvs-servPID. |
903 |
|
*/ |
904 |
|
strcat (server_temp_dir, "/cvs-serv"); |
905 |
|
|
906 |
|
p = server_temp_dir + strlen (server_temp_dir); |
907 |
|
sprintf (p, "%ld", (long) getpid ()); |
908 |
|
|
909 |
|
orig_server_temp_dir = server_temp_dir; |
910 |
|
|
911 |
|
/* Create the temporary directory, and set the mode to |
912 |
|
* 700, to discourage random people from tampering with |
913 |
|
* it. |
914 |
|
*/ |
915 |
|
while ((status = mkdir_p (server_temp_dir)) == EEXIST) |
916 |
|
{ |
917 |
|
static const char suffix[] = "abcdefghijklmnopqrstuvwxyz"; |
918 |
|
|
919 |
|
if (i >= sizeof suffix - 1) break; |
920 |
|
if (i == 0) p = server_temp_dir + strlen (server_temp_dir); |
921 |
|
p[0] = suffix[i++]; |
922 |
|
p[1] = '\0'; |
923 |
|
} |
924 |
|
if (status) |
925 |
|
{ |
926 |
|
if (alloc_pending (80 + strlen (server_temp_dir))) |
927 |
|
sprintf (pending_error_text, |
928 |
|
"E can't create temporary directory %s", |
929 |
|
server_temp_dir); |
930 |
|
pending_error = status; |
931 |
|
} |
932 |
|
#ifndef CHMOD_BROKEN |
933 |
|
else if (chmod (server_temp_dir, S_IRWXU) < 0) |
934 |
|
{ |
935 |
|
int save_errno = errno; |
936 |
|
if (alloc_pending (80 + strlen (server_temp_dir))) |
937 |
|
sprintf (pending_error_text, |
938 |
|
"E cannot change permissions on temporary directory %s", |
939 |
|
server_temp_dir); |
940 |
|
pending_error = save_errno; |
941 |
|
} |
942 |
|
#endif |
943 |
|
else if (CVS_CHDIR (server_temp_dir) < 0) |
944 |
|
{ |
945 |
|
int save_errno = errno; |
946 |
|
if (alloc_pending (80 + strlen (server_temp_dir))) |
947 |
|
sprintf (pending_error_text, |
948 |
|
"E cannot change to temporary directory %s", |
949 |
|
server_temp_dir); |
950 |
|
pending_error = save_errno; |
951 |
|
} |
952 |
|
} |
953 |
|
} |
954 |
|
|
955 |
/* Now that we have a config, verify our compression level. Since |
/* Now that we have a config, verify our compression level. Since |
956 |
* most clients do not send Gzip-stream requests until after the root |
* most clients do not send Gzip-stream requests until after the root |
6050 |
* dont_delete_temp Set when a core dump of a child process is |
* dont_delete_temp Set when a core dump of a child process is |
6051 |
* detected so that the core and related data may |
* detected so that the core and related data may |
6052 |
* be preserved. |
* be preserved. |
|
* Tmpdir The system TMP directory for all temp files. |
|
6053 |
* noexec Whether we are supposed to change the disk. |
* noexec Whether we are supposed to change the disk. |
6054 |
* orig_server_temp_dir The temporary directory we created within |
* orig_server_temp_dir The temporary directory we created within |
6055 |
* Tmpdir for our duplicate of the client |
* Tmpdir for our duplicate of the client |
6209 |
|
|
6210 |
/* Make sure our working directory isn't inside the tree we're |
/* Make sure our working directory isn't inside the tree we're |
6211 |
going to delete. */ |
going to delete. */ |
6212 |
CVS_CHDIR (Tmpdir); |
CVS_CHDIR (get_cvs_tmp_dir ()); |
6213 |
|
|
6214 |
/* Temporarily clear noexec, so that we clean up our temp directory |
/* Temporarily clear noexec, so that we clean up our temp directory |
6215 |
regardless of it (this could more cleanly be handled by moving |
regardless of it (this could more cleanly be handled by moving |
6362 |
protocol to report error messages. */ |
protocol to report error messages. */ |
6363 |
error_use_protocol = 1; |
error_use_protocol = 1; |
6364 |
|
|
|
/* OK, now figure out where we stash our temporary files. */ |
|
|
{ |
|
|
char *p; |
|
|
|
|
|
/* The code which wants to chdir into server_temp_dir is not set |
|
|
up to deal with it being a relative path. So give an error |
|
|
for that case. */ |
|
|
if (!ISABSOLUTE (Tmpdir)) |
|
|
{ |
|
|
if (alloc_pending (80 + strlen (Tmpdir))) |
|
|
sprintf (pending_error_text, |
|
|
"E Value of %s for TMPDIR is not absolute", Tmpdir); |
|
|
|
|
|
/* FIXME: we would like this error to be persistent, that |
|
|
is, not cleared by print_pending_error. The current client |
|
|
will exit as soon as it gets an error, but the protocol spec |
|
|
does not require a client to do so. */ |
|
|
} |
|
|
else |
|
|
{ |
|
|
int status; |
|
|
int i = 0; |
|
|
|
|
|
server_temp_dir = xmalloc (strlen (Tmpdir) + 80); |
|
|
if (server_temp_dir == NULL) |
|
|
{ |
|
|
/* |
|
|
* Strictly speaking, we're not supposed to output anything |
|
|
* now. But we're about to exit(), give it a try. |
|
|
*/ |
|
|
printf ("E Fatal server error, aborting.\n\ |
|
|
error ENOMEM Virtual memory exhausted.\n"); |
|
|
|
|
|
exit (EXIT_FAILURE); |
|
|
} |
|
|
strcpy (server_temp_dir, Tmpdir); |
|
|
|
|
|
/* Remove a trailing slash from TMPDIR if present. */ |
|
|
p = server_temp_dir + strlen (server_temp_dir) - 1; |
|
|
if (*p == '/') |
|
|
*p = '\0'; |
|
|
|
|
|
/* |
|
|
* I wanted to use cvs-serv/PID, but then you have to worry about |
|
|
* the permissions on the cvs-serv directory being right. So |
|
|
* use cvs-servPID. |
|
|
*/ |
|
|
strcat (server_temp_dir, "/cvs-serv"); |
|
|
|
|
|
p = server_temp_dir + strlen (server_temp_dir); |
|
|
sprintf (p, "%ld", (long) getpid ()); |
|
|
|
|
|
orig_server_temp_dir = server_temp_dir; |
|
|
|
|
|
/* Create the temporary directory, and set the mode to |
|
|
700, to discourage random people from tampering with |
|
|
it. */ |
|
|
while ((status = mkdir_p (server_temp_dir)) == EEXIST) |
|
|
{ |
|
|
static const char suffix[] = "abcdefghijklmnopqrstuvwxyz"; |
|
|
|
|
|
if (i >= sizeof suffix - 1) break; |
|
|
if (i == 0) p = server_temp_dir + strlen (server_temp_dir); |
|
|
p[0] = suffix[i++]; |
|
|
p[1] = '\0'; |
|
|
} |
|
|
if (status != 0) |
|
|
{ |
|
|
if (alloc_pending (80 + strlen (server_temp_dir))) |
|
|
sprintf (pending_error_text, |
|
|
"E can't create temporary directory %s", |
|
|
server_temp_dir); |
|
|
pending_error = status; |
|
|
} |
|
|
#ifndef CHMOD_BROKEN |
|
|
else if (chmod (server_temp_dir, S_IRWXU) < 0) |
|
|
{ |
|
|
int save_errno = errno; |
|
|
if (alloc_pending (80 + strlen (server_temp_dir))) |
|
|
sprintf (pending_error_text, |
|
|
"E cannot change permissions on temporary directory %s", |
|
|
server_temp_dir); |
|
|
pending_error = save_errno; |
|
|
} |
|
|
#endif |
|
|
else if (CVS_CHDIR (server_temp_dir) < 0) |
|
|
{ |
|
|
int save_errno = errno; |
|
|
if (alloc_pending (80 + strlen (server_temp_dir))) |
|
|
sprintf (pending_error_text, |
|
|
"E cannot change to temporary directory %s", |
|
|
server_temp_dir); |
|
|
pending_error = save_errno; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
6365 |
/* Now initialize our argument vector (for arguments from the client). */ |
/* Now initialize our argument vector (for arguments from the client). */ |
6366 |
|
|
6367 |
/* Small for testing. */ |
/* Small for testing. */ |
7343 |
|
|
7344 |
|
|
7345 |
#ifdef HAVE_GSSAPI |
#ifdef HAVE_GSSAPI |
7346 |
|
char *canon_host (const char *host); |
7347 |
|
|
7348 |
/* Authenticate a GSSAPI connection. This is called from |
/* Authenticate a GSSAPI connection. This is called from |
7349 |
* pserver_authenticate_connection, and it handles success and failure |
* pserver_authenticate_connection, and it handles success and failure |
7350 |
* the same way. |
* the same way. |