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