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