xref: /netbsd-src/external/gpl2/xcvs/dist/src/filesubr.c (revision d909946ca08dceb44d7d0f22ec9488679695d976)
1 /* filesubr.c --- subroutines for dealing with files
2    Jim Blandy <jimb@cyclic.com>
3 
4    This file is part of GNU CVS.
5 
6    GNU CVS is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.  */
15 #include <sys/cdefs.h>
16 __RCSID("$NetBSD: filesubr.c,v 1.5 2016/05/17 14:00:09 christos Exp $");
17 
18 /* These functions were moved out of subr.c because they need different
19    definitions under operating systems (like, say, Windows NT) with different
20    file system semantics.  */
21 
22 #include "cvs.h"
23 #include "lstat.h"
24 #include "save-cwd.h"
25 #include "xsize.h"
26 
27 static int deep_remove_dir (const char *path);
28 
29 /*
30  * Copies "from" to "to".
31  */
32 void
33 copy_file (const char *from, const char *to)
34 {
35     struct stat sb;
36     struct utimbuf t;
37     int fdin, fdout;
38     ssize_t rsize;
39 
40     TRACE (TRACE_FUNCTION, "copy(%s,%s)", from, to);
41 
42     if (noexec)
43 	return;
44 
45     /* If the file to be copied is a link or a device, then just create
46        the new link or device appropriately. */
47     if ((rsize = islink (from)) > 0)
48     {
49 	char *source = Xreadlink (from, rsize);
50 	if (symlink (source, to) == -1)
51 	    error (1, errno, "cannot symlink %s to %s", source, to);
52 	free (source);
53 	return;
54     }
55 
56     if (isdevice (from))
57     {
58 #if defined(HAVE_MKNOD) && defined(HAVE_STRUCT_STAT_ST_RDEV)
59 	if (stat (from, &sb) < 0)
60 	    error (1, errno, "cannot stat %s", from);
61 	mknod (to, sb.st_mode, sb.st_rdev);
62 #else
63 	error (1, 0, "cannot copy device files on this system (%s)", from);
64 #endif
65     }
66     else
67     {
68 	/* Not a link or a device... probably a regular file. */
69 	if ((fdin = open (from, O_RDONLY)) < 0)
70 	    error (1, errno, "cannot open %s for copying", from);
71 	if (fstat (fdin, &sb) < 0)
72 	    error (1, errno, "cannot fstat %s", from);
73 	if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0)
74 	    error (1, errno, "cannot create %s for copying", to);
75 	if (sb.st_size > 0)
76 	{
77 	    char buf[BUFSIZ];
78 	    int n;
79 
80 	    for (;;)
81 	    {
82 		n = read (fdin, buf, sizeof(buf));
83 		if (n == -1)
84 		{
85 #ifdef EINTR
86 		    if (errno == EINTR)
87 			continue;
88 #endif
89 		    error (1, errno, "cannot read file %s for copying", from);
90 		}
91 		else if (n == 0)
92 		    break;
93 
94 		if (write(fdout, buf, n) != n) {
95 		    error (1, errno, "cannot write file %s for copying", to);
96 		}
97 	    }
98 	}
99 
100 	if (close (fdin) < 0)
101 	    error (0, errno, "cannot close %s", from);
102 	if (close (fdout) < 0)
103 	    error (1, errno, "cannot close %s", to);
104     }
105 
106     /* preserve last access & modification times */
107     memset ((char *) &t, 0, sizeof (t));
108     t.actime = sb.st_atime;
109     t.modtime = sb.st_mtime;
110     (void) utime (to, &t);
111 }
112 
113 
114 
115 /* FIXME-krp: these functions would benefit from caching the char * &
116    stat buf.  */
117 
118 /*
119  * Returns true if the argument file is a directory, or is a symbolic
120  * link which points to a directory.
121  */
122 bool
123 isdir (const char *file)
124 {
125     struct stat sb;
126 
127     if (stat (file, &sb) < 0)
128 	return false;
129     return S_ISDIR (sb.st_mode);
130 }
131 
132 
133 
134 /*
135  * Returns 0 if the argument file is not a symbolic link.
136  * Returns size of the link if it is a symbolic link.
137  */
138 ssize_t
139 islink (const char *file)
140 {
141     ssize_t retsize = 0;
142 #ifdef S_ISLNK
143     struct stat sb;
144 
145     if ((lstat (file, &sb) >= 0) && S_ISLNK (sb.st_mode))
146 	retsize = sb.st_size;
147 #endif
148     return retsize;
149 }
150 
151 
152 
153 /*
154  * Returns true if the argument file is a block or
155  * character special device.
156  */
157 bool
158 isdevice (const char *file)
159 {
160     struct stat sb;
161 
162     if (lstat (file, &sb) < 0)
163 	return false;
164 #ifdef S_ISBLK
165     if (S_ISBLK (sb.st_mode))
166 	return true;
167 #endif
168 #ifdef S_ISCHR
169     if (S_ISCHR (sb.st_mode))
170 	return true;
171 #endif
172     return false;
173 }
174 
175 
176 
177 /*
178  * Returns true if the argument file exists.
179  */
180 bool
181 isfile (const char *file)
182 {
183     return isaccessible (file, F_OK);
184 }
185 
186 #ifdef SETXID_SUPPORT
187 int
188 ingroup(gid_t gid)
189 {
190     gid_t *gidp;
191     int i, ngroups;
192 
193     if (gid == getegid())
194 	return 1;
195 
196     ngroups = getgroups(0, NULL);
197     if (ngroups == -1)
198 	return 0;
199 
200     if ((gidp = malloc(sizeof(gid_t) * ngroups)) == NULL)
201 	return 0;
202 
203     if (getgroups(ngroups, gidp) == -1) {
204 	free(gidp);
205 	return 0;
206     }
207 
208     for (i = 0; i < ngroups; i++)
209 	if (gid == gidp[i])
210 	    break;
211 
212     free(gidp);
213     return i != ngroups;
214 }
215 #endif
216 
217 /*
218  * Returns non-zero if the argument file is readable.
219  */
220 bool
221 isreadable (const char *file)
222 {
223     return isaccessible (file, R_OK);
224 }
225 
226 
227 
228 /*
229  * Returns non-zero if the argument file is writable.
230  */
231 bool
232 iswritable (const char *file)
233 {
234     return isaccessible (file, W_OK);
235 }
236 
237 
238 
239 /*
240  * Returns true if the argument file is accessable according to
241  * mode.  If compiled with SETXID_SUPPORT also works if cvs has setxid
242  * bits set.
243  */
244 bool
245 isaccessible (const char *file, const int mode)
246 {
247 #ifdef SETXID_SUPPORT
248     struct stat sb;
249     int umask = 0;
250     int gmask = 0;
251     int omask = 0;
252     int uid, mask;
253 
254     if (stat (file, &sb)== -1)
255 	return false;
256     if (mode == F_OK)
257 	return true;
258 
259     uid = geteuid();
260     if (uid == 0)		/* superuser */
261     {
262 	if (!(mode & X_OK) || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
263 	    return true;
264 
265 	errno = EACCES;
266 	return false;
267     }
268 
269     if (mode & R_OK)
270     {
271 	umask |= S_IRUSR;
272 	gmask |= S_IRGRP;
273 	omask |= S_IROTH;
274     }
275     if (mode & W_OK)
276     {
277 	umask |= S_IWUSR;
278 	gmask |= S_IWGRP;
279 	omask |= S_IWOTH;
280     }
281     if (mode & X_OK)
282     {
283 	umask |= S_IXUSR;
284 	gmask |= S_IXGRP;
285 	omask |= S_IXOTH;
286     }
287 
288     mask = sb.st_uid == uid ? umask : ingroup(sb.st_gid) ? gmask : omask;
289     if ((sb.st_mode & mask) == mask)
290 	return true;
291     errno = EACCES;
292     return false;
293 #else /* !SETXID_SUPPORT */
294     return access (file, mode) == 0;
295 #endif /* SETXID_SUPPORT */
296 }
297 
298 
299 
300 /*
301  * Make a directory and die if it fails
302  */
303 void
304 make_directory (const char *name)
305 {
306     struct stat sb;
307 
308     if (stat (name, &sb) == 0 && (!S_ISDIR (sb.st_mode)))
309 	    error (0, 0, "%s already exists but is not a directory", name);
310     if (!noexec && mkdir (name, 0777) < 0)
311 	error (1, errno, "cannot make directory %s", name);
312 }
313 
314 /*
315  * Make a path to the argument directory, printing a message if something
316  * goes wrong.
317  */
318 void
319 make_directories (const char *name)
320 {
321     char *cp;
322 
323     if (noexec)
324 	return;
325 
326     if (mkdir (name, 0777) == 0 || errno == EEXIST)
327 	return;
328     if (! existence_error (errno))
329     {
330 	error (0, errno, "cannot make path to %s", name);
331 	return;
332     }
333     if ((cp = strrchr (name, '/')) == NULL)
334 	return;
335     *cp = '\0';
336     make_directories (name);
337     *cp++ = '/';
338     if (*cp == '\0')
339 	return;
340     (void) mkdir (name, 0777);
341 }
342 
343 /* Create directory NAME if it does not already exist; fatal error for
344    other errors.  Returns 0 if directory was created; 1 if it already
345    existed.  */
346 int
347 mkdir_if_needed (const char *name)
348 {
349     if (mkdir (name, 0777) < 0)
350     {
351 	int save_errno = errno;
352 	if (save_errno != EEXIST && !isdir (name))
353 	    error (1, save_errno, "cannot make directory %s", name);
354 	return 1;
355     }
356     return 0;
357 }
358 
359 /*
360  * Change the mode of a file, either adding write permissions, or removing
361  * all write permissions.  Either change honors the current umask setting.
362  *
363  * Don't do anything if PreservePermissions is set to `yes'.  This may
364  * have unexpected consequences for some uses of xchmod.
365  */
366 void
367 xchmod (const char *fname, int writable)
368 {
369     struct stat sb;
370     mode_t mode, oumask;
371 
372 #ifdef PRESERVE_PERMISSIONS_SUPPORT
373     if (config->preserve_perms)
374 	return;
375 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
376 
377     if (stat (fname, &sb) < 0)
378     {
379 	if (!noexec)
380 	    error (0, errno, "cannot stat %s", fname);
381 	return;
382     }
383     oumask = umask (0);
384     (void) umask (oumask);
385     if (writable)
386     {
387 	mode = sb.st_mode | (~oumask
388 			     & (((sb.st_mode & S_IRUSR) ? S_IWUSR : 0)
389 				| ((sb.st_mode & S_IRGRP) ? S_IWGRP : 0)
390 				| ((sb.st_mode & S_IROTH) ? S_IWOTH : 0)));
391     }
392     else
393     {
394 	mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask;
395     }
396 
397     TRACE (TRACE_FUNCTION, "chmod(%s,%o)", fname, (unsigned int) mode);
398 
399     if (noexec)
400 	return;
401 
402     if (chmod (fname, mode) < 0)
403 	error (0, errno, "cannot change mode of file %s", fname);
404 }
405 
406 /*
407  * Rename a file and die if it fails
408  */
409 void
410 rename_file (const char *from, const char *to)
411 {
412     TRACE (TRACE_FUNCTION, "rename(%s,%s)", from, to);
413 
414     if (noexec)
415 	return;
416 
417     if (rename (from, to) < 0)
418 	error (1, errno, "cannot rename file %s to %s", from, to);
419 }
420 
421 /*
422  * unlink a file, if possible.
423  */
424 int
425 unlink_file (const char *f)
426 {
427     TRACE (TRACE_FUNCTION, "unlink_file(%s)", f);
428 
429     if (noexec)
430 	return (0);
431 
432     return (CVS_UNLINK (f));
433 }
434 
435 
436 
437 /*
438  * Unlink a file or dir, if possible.  If it is a directory do a deep
439  * removal of all of the files in the directory.  Return -1 on error
440  * (in which case errno is set).
441  */
442 int
443 unlink_file_dir (const char *f)
444 {
445     struct stat sb;
446 
447     /* This is called by the server parent process in contexts where
448        it is not OK to send output (e.g. after we sent "ok" to the
449        client).  */
450     if (!server_active)
451 	TRACE (TRACE_FUNCTION, "unlink_file_dir(%s)", f);
452 
453     if (noexec)
454 	return 0;
455 
456     /* For at least some unices, if root tries to unlink() a directory,
457        instead of doing something rational like returning EISDIR,
458        the system will gleefully go ahead and corrupt the filesystem.
459        So we first call stat() to see if it is OK to call unlink().  This
460        doesn't quite work--if someone creates a directory between the
461        call to stat() and the call to unlink(), we'll still corrupt
462        the filesystem.  Where is the Unix Haters Handbook when you need
463        it?  */
464     if (stat (f, &sb) < 0)
465     {
466 	if (existence_error (errno))
467 	{
468 	    /* The file or directory doesn't exist anyhow.  */
469 	    return -1;
470 	}
471     }
472     else if (S_ISDIR (sb.st_mode))
473 	return deep_remove_dir (f);
474 
475     return CVS_UNLINK (f);
476 }
477 
478 
479 
480 /* Remove a directory and everything it contains.  Returns 0 for
481  * success, -1 for failure (in which case errno is set).
482  */
483 
484 static int
485 deep_remove_dir (const char *path)
486 {
487     DIR		  *dirp;
488     struct dirent *dp;
489 
490     if (rmdir (path) != 0)
491     {
492 	if (errno == ENOTEMPTY
493 	    || errno == EEXIST
494 	    /* Ugly workaround for ugly AIX 4.1 (and 3.2) header bug
495 	       (it defines ENOTEMPTY and EEXIST to 17 but actually
496 	       returns 87).  */
497 	    || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87))
498 	{
499 	    if ((dirp = CVS_OPENDIR (path)) == NULL)
500 		/* If unable to open the directory return
501 		 * an error
502 		 */
503 		return -1;
504 
505 	    errno = 0;
506 	    while ((dp = CVS_READDIR (dirp)) != NULL)
507 	    {
508 		char *buf;
509 
510 		if (strcmp (dp->d_name, ".") == 0 ||
511 			    strcmp (dp->d_name, "..") == 0)
512 		    continue;
513 
514 		buf = Xasprintf ("%s/%s", path, dp->d_name);
515 
516 		/* See comment in unlink_file_dir explanation of why we use
517 		   isdir instead of just calling unlink and checking the
518 		   status.  */
519 		if (isdir (buf))
520 		{
521 		    if (deep_remove_dir (buf))
522 		    {
523 			CVS_CLOSEDIR (dirp);
524 			free (buf);
525 			return -1;
526 		    }
527 		}
528 		else
529 		{
530 		    if (CVS_UNLINK (buf) != 0)
531 		    {
532 			CVS_CLOSEDIR (dirp);
533 			free (buf);
534 			return -1;
535 		    }
536 		}
537 		free (buf);
538 
539 		errno = 0;
540 	    }
541 	    if (errno != 0)
542 	    {
543 		int save_errno = errno;
544 		CVS_CLOSEDIR (dirp);
545 		errno = save_errno;
546 		return -1;
547 	    }
548 	    CVS_CLOSEDIR (dirp);
549 	    return rmdir (path);
550 	}
551 	else
552 	    return -1;
553     }
554 
555     /* Was able to remove the directory return 0 */
556     return 0;
557 }
558 
559 
560 
561 /* Read NCHARS bytes from descriptor FD into BUF.
562    Return the number of characters successfully read.
563    The number returned is always NCHARS unless end-of-file or error.  */
564 static size_t
565 block_read (int fd, char *buf, size_t nchars)
566 {
567     char *bp = buf;
568     size_t nread;
569 
570     do
571     {
572 	nread = read (fd, bp, nchars);
573 	if (nread == (size_t)-1)
574 	{
575 #ifdef EINTR
576 	    if (errno == EINTR)
577 		continue;
578 #endif
579 	    return (size_t)-1;
580 	}
581 
582 	if (nread == 0)
583 	    break;
584 
585 	bp += nread;
586 	nchars -= nread;
587     } while (nchars != 0);
588 
589     return bp - buf;
590 }
591 
592 
593 /*
594  * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
595  * If FILE1 and FILE2 are special files, compare their salient characteristics
596  * (i.e. major/minor device numbers, links, etc.
597  */
598 int
599 xcmp (const char *file1, const char *file2)
600 {
601     char *buf1, *buf2;
602     struct stat sb1, sb2;
603     int fd1, fd2;
604     int ret;
605 
606     if (lstat (file1, &sb1) < 0)
607 	error (1, errno, "cannot lstat %s", file1);
608     if (lstat (file2, &sb2) < 0)
609 	error (1, errno, "cannot lstat %s", file2);
610 
611     /* If FILE1 and FILE2 are not the same file type, they are unequal. */
612     if ((sb1.st_mode & S_IFMT) != (sb2.st_mode & S_IFMT))
613 	return 1;
614 
615     /* If FILE1 and FILE2 are symlinks, they are equal if they point to
616        the same thing. */
617 #ifdef S_ISLNK
618     if (S_ISLNK (sb1.st_mode) && S_ISLNK (sb2.st_mode))
619     {
620 	int result;
621 	buf1 = Xreadlink (file1, sb1.st_size);
622 	buf2 = Xreadlink (file2, sb2.st_size);
623 	result = (strcmp (buf1, buf2) == 0);
624 	free (buf1);
625 	free (buf2);
626 	return result;
627     }
628 #endif
629 
630     /* If FILE1 and FILE2 are devices, they are equal if their device
631        numbers match. */
632     if (S_ISBLK (sb1.st_mode) || S_ISCHR (sb1.st_mode))
633     {
634 #ifdef HAVE_STRUCT_STAT_ST_RDEV
635 	if (sb1.st_rdev == sb2.st_rdev)
636 	    return 0;
637 	else
638 	    return 1;
639 #else
640 	error (1, 0, "cannot compare device files on this system (%s and %s)",
641 	       file1, file2);
642 #endif
643     }
644 
645     if ((fd1 = open (file1, O_RDONLY)) < 0)
646 	error (1, errno, "cannot open file %s for comparing", file1);
647     if ((fd2 = open (file2, O_RDONLY)) < 0)
648 	error (1, errno, "cannot open file %s for comparing", file2);
649 
650     /* A generic file compare routine might compare st_dev & st_ino here
651        to see if the two files being compared are actually the same file.
652        But that won't happen in CVS, so we won't bother. */
653 
654     if (sb1.st_size != sb2.st_size)
655 	ret = 1;
656     else if (sb1.st_size == 0)
657 	ret = 0;
658     else
659     {
660 	/* FIXME: compute the optimal buffer size by computing the least
661 	   common multiple of the files st_blocks field */
662 	size_t buf_size = 8 * 1024;
663 	size_t read1;
664 	size_t read2;
665 
666 	buf1 = xmalloc (buf_size);
667 	buf2 = xmalloc (buf_size);
668 
669 	do
670 	{
671 	    read1 = block_read (fd1, buf1, buf_size);
672 	    if (read1 == (size_t)-1)
673 		error (1, errno, "cannot read file %s for comparing", file1);
674 
675 	    read2 = block_read (fd2, buf2, buf_size);
676 	    if (read2 == (size_t)-1)
677 		error (1, errno, "cannot read file %s for comparing", file2);
678 
679 	    /* assert (read1 == read2); */
680 
681 	    ret = memcmp(buf1, buf2, read1);
682 	} while (ret == 0 && read1 == buf_size);
683 
684 	free (buf1);
685 	free (buf2);
686     }
687 
688     (void) close (fd1);
689     (void) close (fd2);
690     return (ret);
691 }
692 
693 /* Generate a unique temporary filename.  Returns a pointer to a newly
694  * malloc'd string containing the name.  Returns successfully or not at
695  * all.
696  *
697  *     THIS FUNCTION IS DEPRECATED!!!  USE cvs_temp_file INSTEAD!!!
698  *
699  * and yes, I know about the way the rcs commands use temp files.  I think
700  * they should be converted too but I don't have time to look into it right
701  * now.
702  */
703 char *
704 cvs_temp_name (void)
705 {
706     char *fn;
707     FILE *fp;
708 
709     fp = cvs_temp_file (&fn);
710     if (fp == NULL)
711 	error (1, errno, "Failed to create temporary file");
712     if (fclose (fp) == EOF)
713 	error (0, errno, "Failed to close temporary file %s", fn);
714     return fn;
715 }
716 
717 /* Generate a unique temporary filename and return an open file stream
718  * to the truncated file by that name
719  *
720  *  INPUTS
721  *	filename	where to place the pointer to the newly allocated file
722  *   			name string
723  *
724  *  OUTPUTS
725  *	filename	dereferenced, will point to the newly allocated file
726  *			name string.  This value is undefined if the function
727  *			returns an error.
728  *
729  *  RETURNS
730  *	An open file pointer to a read/write mode empty temporary file with the
731  *	unique file name or NULL on failure.
732  *
733  *  ERRORS
734  *	On error, errno will be set to some value either by CVS_FOPEN or
735  *	whatever system function is called to generate the temporary file name.
736  *	The value of filename is undefined on error.
737  */
738 FILE *
739 cvs_temp_file (char **filename)
740 {
741     char *fn;
742     FILE *fp;
743     int fd;
744 
745     /* FIXME - I'd like to be returning NULL here in noexec mode, but I think
746      * some of the rcs & diff functions which rely on a temp file run in
747      * noexec mode too.
748      */
749 
750     assert (filename != NULL);
751 
752     fn = Xasprintf ("%s/%s", get_cvs_tmp_dir (), "cvsXXXXXX");
753     fd = mkstemp (fn);
754 
755     /* a NULL return will be interpreted by callers as an error and
756      * errno should still be set
757      */
758     if (fd == -1)
759 	fp = NULL;
760     else if ((fp = CVS_FDOPEN (fd, "w+")) == NULL)
761     {
762 	/* Attempt to close and unlink the file since mkstemp returned
763 	 * sucessfully and we believe it's been created and opened.
764 	 */
765  	int save_errno = errno;
766 	if (close (fd))
767 	    error (0, errno, "Failed to close temporary file %s", fn);
768 	if (CVS_UNLINK (fn))
769 	    error (0, errno, "Failed to unlink temporary file %s", fn);
770 	errno = save_errno;
771     }
772 
773     if (fp == NULL)
774 	free (fn);
775 
776     /* mkstemp is defined to open mode 0600 using glibc 2.0.7+.  There used
777      * to be a complicated #ifdef checking the library versions here and then
778      * a chmod 0600 on the temp file for versions of glibc less than 2.1.  This
779      * is rather a special case, leaves a race condition open regardless, and
780      * one could hope that sysadmins have read the relevant security
781      * announcements and upgraded by now to a version with a fix committed in
782      * January of 1999.
783      *
784      * If it is decided at some point that old, buggy versions of glibc should
785      * still be catered to, a umask of 0600 should be set before file creation
786      * instead then reset after file creation since this would avoid the race
787      * condition that the chmod left open to exploitation.
788      */
789 
790     *filename = fn;
791     return fp;
792 }
793 
794 
795 
796 /* Return a pointer into PATH's last component.  */
797 const char *
798 last_component (const char *path)
799 {
800     const char *last = strrchr (path, '/');
801 
802     if (last && (last != path))
803         return last + 1;
804     else
805         return path;
806 }
807 
808 
809 
810 /* Return the home directory.  Returns a pointer to storage
811    managed by this function or its callees (currently getenv).
812    This function will return the same thing every time it is
813    called.  Returns NULL if there is no home directory.
814 
815    Note that for a pserver server, this may return root's home
816    directory.  What typically happens is that upon being started from
817    inetd, before switching users, the code in cvsrc.c calls
818    get_homedir which remembers root's home directory in the static
819    variable.  Then the switch happens and get_homedir might return a
820    directory that we don't even have read or execute permissions for
821    (which is bad, when various parts of CVS try to read there).  One
822    fix would be to make the value returned by get_homedir only good
823    until the next call (which would free the old value).  Another fix
824    would be to just always malloc our answer, and let the caller free
825    it (that is best, because some day we may need to be reentrant).
826 
827    The workaround is to put -f in inetd.conf which means that
828    get_homedir won't get called until after the switch in user ID.
829 
830    The whole concept of a "home directory" on the server is pretty
831    iffy, although I suppose some people probably are relying on it for
832    .cvsrc and such, in the cases where it works.  */
833 char *
834 get_homedir (void)
835 {
836     static char *home = NULL;
837     char *env;
838     struct passwd *pw;
839 
840     if (home != NULL)
841 	return home;
842 
843     if (!server_active && (env = getenv ("HOME")) != NULL)
844 	home = env;
845     else if ((pw = (struct passwd *) getpwuid (getuid ()))
846 	     && pw->pw_dir)
847 	home = xstrdup (pw->pw_dir);
848     else
849 	return 0;
850 
851     return home;
852 }
853 
854 /* Compose a path to a file in the home directory.  This is necessary because
855  * of different behavior on UNIX and VMS.  See the notes in vms/filesubr.c.
856  *
857  * A more clean solution would be something more along the lines of a
858  * "join a directory to a filename" kind of thing which was not specific to
859  * the homedir.  This should aid portability between UNIX, Mac, Windows, VMS,
860  * and possibly others.  This is already handled by Perl - it might be
861  * interesting to see how much of the code was written in C since Perl is under
862  * the GPL and the Artistic license - we might be able to use it.
863  */
864 char *
865 strcat_filename_onto_homedir (const char *dir, const char *file)
866 {
867     char *path = Xasprintf ("%s/%s", dir, file);
868     return path;
869 }
870 
871 /* See cvs.h for description.  On unix this does nothing, because the
872    shell expands the wildcards.  */
873 void
874 expand_wild (int argc, char **argv, int *pargc, char ***pargv)
875 {
876     int i;
877     if (size_overflow_p (xtimes (argc, sizeof (char *)))) {
878 	*pargc = 0;
879 	*pargv = NULL;
880 	error (0, 0, "expand_wild: too many arguments");
881 	return;
882     }
883     *pargc = argc;
884     *pargv = xnmalloc (argc, sizeof (char *));
885     for (i = 0; i < argc; ++i)
886 	(*pargv)[i] = xstrdup (argv[i]);
887 }
888 
889 
890 
891 static char *tmpdir_env;
892 
893 /* Return path to temp directory.
894  */
895 const char *
896 get_system_temp_dir (void)
897 {
898     if (!tmpdir_env) tmpdir_env = getenv (TMPDIR_ENV);
899     return tmpdir_env;
900 }
901 
902 
903 
904 void
905 push_env_temp_dir (void)
906 {
907     const char *tmpdir = get_cvs_tmp_dir ();
908     if (tmpdir_env && strcmp (tmpdir_env, tmpdir))
909 	setenv (TMPDIR_ENV, tmpdir, 1);
910 }
911