Make unsafe_symlink() take const args so that we don't get any
[rsync/rsync.git] / util.c
1 /*  -*- c-file-style: "linux" -*-
2  * 
3  * Copyright (C) 1996-2000 by Andrew Tridgell 
4  * Copyright (C) Paul Mackerras 1996
5  * Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
6  * 
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  * 
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 /**
23  * @file
24  *
25  * Utilities used in rsync 
26  **/
27
28 #include "rsync.h"
29
30 extern int verbose;
31
32 int sanitize_paths = 0;
33
34
35
36 /**
37  * Set a fd into nonblocking mode
38  **/
39 void set_nonblocking(int fd)
40 {
41         int val;
42
43         if ((val = fcntl(fd, F_GETFL, 0)) == -1)
44                 return;
45         if (!(val & NONBLOCK_FLAG)) {
46                 val |= NONBLOCK_FLAG;
47                 fcntl(fd, F_SETFL, val);
48         }
49 }
50
51 /**
52  * Set a fd into blocking mode
53  **/
54 void set_blocking(int fd)
55 {
56         int val;
57
58         if ((val = fcntl(fd, F_GETFL, 0)) == -1)
59                 return;
60         if (val & NONBLOCK_FLAG) {
61                 val &= ~NONBLOCK_FLAG;
62                 fcntl(fd, F_SETFL, val);
63         }
64 }
65
66
67 /**
68  * Create a file descriptor pair - like pipe() but use socketpair if
69  * possible (because of blocking issues on pipes).
70  * 
71  * Always set non-blocking.
72  */
73 int fd_pair(int fd[2])
74 {
75         int ret;
76
77 #if HAVE_SOCKETPAIR
78         ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
79 #else
80         ret = pipe(fd);
81 #endif
82
83         if (ret == 0) {
84                 set_nonblocking(fd[0]);
85                 set_nonblocking(fd[1]);
86         }
87
88         return ret;
89 }
90
91
92 void print_child_argv(char **cmd)
93 {
94         rprintf(FINFO, "opening connection using ");
95         for (; *cmd; cmd++) {
96                 /* Look for characters that ought to be quoted.  This
97                 * is not a great quoting algorithm, but it's
98                 * sufficient for a log message. */
99                 if (strspn(*cmd, "abcdefghijklmnopqrstuvwxyz"
100                            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
101                            "0123456789"
102                            ",.-_=+@/") != strlen(*cmd)) {
103                         rprintf(FINFO, "\"%s\" ", *cmd);
104                 } else {
105                         rprintf(FINFO, "%s ", *cmd);
106                 }
107         }
108         rprintf(FINFO, "\n");
109 }
110
111
112 void out_of_memory(char *str)
113 {
114   rprintf(FERROR,"ERROR: out of memory in %s\n",str);
115   exit_cleanup(RERR_MALLOC);
116 }
117
118 void overflow(char *str)
119 {
120   rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
121   exit_cleanup(RERR_MALLOC);
122 }
123
124
125
126 int set_modtime(char *fname, time_t modtime)
127 {
128         extern int dry_run;
129         if (dry_run)
130                 return 0;
131
132         if (verbose > 2) {
133                 rprintf(FINFO, "set modtime of %s to (%ld) %s",
134                         fname, (long) modtime,
135                         asctime(localtime(&modtime)));
136         }
137         
138         {
139 #ifdef HAVE_UTIMBUF
140                 struct utimbuf tbuf;  
141                 tbuf.actime = time(NULL);
142                 tbuf.modtime = modtime;
143                 return utime(fname,&tbuf);
144 #elif defined(HAVE_UTIME)
145                 time_t t[2];
146                 t[0] = time(NULL);
147                 t[1] = modtime;
148                 return utime(fname,t);
149 #else
150                 struct timeval t[2];
151                 t[0].tv_sec = time(NULL);
152                 t[0].tv_usec = 0;
153                 t[1].tv_sec = modtime;
154                 t[1].tv_usec = 0;
155                 return utimes(fname,t);
156 #endif
157         }
158 }
159
160
161 /**
162    Create any necessary directories in fname. Unfortunately we don't know
163    what perms to give the directory when this is called so we need to rely
164    on the umask
165 **/
166 int create_directory_path(char *fname, int base_umask)
167 {
168         char *p;
169
170         while (*fname == '/') fname++;
171         while (strncmp(fname,"./",2)==0) fname += 2;
172
173         p = fname;
174         while ((p=strchr(p,'/'))) {
175                 *p = 0;
176                 do_mkdir(fname, 0777 & ~base_umask); 
177                 *p = '/';
178                 p++;
179         }
180         return 0;
181 }
182
183
184 /**
185  * Write @p len bytes at @p ptr to descriptor @p desc, retrying if
186  * interrupted.
187  *
188  * @retval len upon success
189  *
190  * @retval <0 write's (negative) error code
191  *
192  * Derived from GNU C's cccp.c.
193  */
194 static int full_write(int desc, char *ptr, size_t len)
195 {
196         int total_written;
197         
198         total_written = 0;
199         while (len > 0) {
200                 int written = write (desc, ptr, len);
201                 if (written < 0)  {
202 #ifdef EINTR
203                         if (errno == EINTR)
204                                 continue;
205 #endif
206                         return written;
207                 }
208                 total_written += written;
209                 ptr += written;
210                 len -= written;
211         }
212         return total_written;
213 }
214
215
216 /**
217  * Read @p len bytes at @p ptr from descriptor @p desc, retrying if
218  * interrupted.
219  *
220  * @retval >0 the actual number of bytes read
221  *
222  * @retval 0 for EOF
223  *
224  * @retval <0 for an error.
225  *
226  * Derived from GNU C's cccp.c. */
227 static int safe_read(int desc, char *ptr, size_t len)
228 {
229         int n_chars;
230  
231         if (len == 0)
232                 return len;
233  
234 #ifdef EINTR
235         do {
236                 n_chars = read(desc, ptr, len);
237         } while (n_chars < 0 && errno == EINTR);
238 #else
239         n_chars = read(desc, ptr, len);
240 #endif
241  
242         return n_chars;
243 }
244
245
246 /** Copy a file.
247  *
248  * This is used in conjunction with the --temp-dir option */
249 int copy_file(char *source, char *dest, mode_t mode)
250 {
251         int ifd;
252         int ofd;
253         char buf[1024 * 8];
254         int len;   /* Number of bytes read into `buf'. */
255
256         ifd = do_open(source, O_RDONLY, 0);
257         if (ifd == -1) {
258                 rprintf(FERROR,"open %s: %s\n",
259                         source,strerror(errno));
260                 return -1;
261         }
262
263         if (robust_unlink(dest) && errno != ENOENT) {
264                 rprintf(FERROR,"unlink %s: %s\n",
265                         dest,strerror(errno));
266                 return -1;
267         }
268
269         ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
270         if (ofd == -1) {
271                 rprintf(FERROR,"open %s: %s\n",
272                         dest,strerror(errno));
273                 close(ifd);
274                 return -1;
275         }
276
277         while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
278                 if (full_write(ofd, buf, len) < 0) {
279                         rprintf(FERROR,"write %s: %s\n",
280                                 dest,strerror(errno));
281                         close(ifd);
282                         close(ofd);
283                         return -1;
284                 }
285         }
286
287         close(ifd);
288         close(ofd);
289
290         if (len < 0) {
291                 rprintf(FERROR,"read %s: %s\n",
292                         source,strerror(errno));
293                 return -1;
294         }
295
296         return 0;
297 }
298
299 /* MAX_RENAMES should be 10**MAX_RENAMES_DIGITS */
300 #define MAX_RENAMES_DIGITS 3
301 #define MAX_RENAMES 1000
302
303 /**
304  * Robust unlink: some OS'es (HPUX) refuse to unlink busy files, so
305  * rename to <path>/.rsyncNNN instead.
306  *
307  * Note that successive rsync runs will shuffle the filenames around a
308  * bit as long as the file is still busy; this is because this function
309  * does not know if the unlink call is due to a new file coming in, or
310  * --delete trying to remove old .rsyncNNN files, hence it renames it
311  * each time.
312  **/
313 int robust_unlink(char *fname)
314 {
315 #ifndef ETXTBSY
316         return do_unlink(fname);
317 #else
318         static int counter = 1;
319         int rc, pos, start;
320         char path[MAXPATHLEN];
321
322         rc = do_unlink(fname);
323         if ((rc == 0) || (errno != ETXTBSY))
324                 return rc;
325
326         strlcpy(path, fname, MAXPATHLEN);
327
328         pos = strlen(path);
329         while((path[--pos] != '/') && (pos >= 0))
330                 ;
331         ++pos;
332         strlcpy(&path[pos], ".rsync", MAXPATHLEN-pos);
333         pos += sizeof(".rsync")-1;
334
335         if (pos > (MAXPATHLEN-MAX_RENAMES_DIGITS-1)) {
336                 errno = ETXTBSY;
337                 return -1;
338         }
339
340         /* start where the last one left off to reduce chance of clashes */
341         start = counter;
342         do {
343                 sprintf(&path[pos], "%03d", counter);
344                 if (++counter >= MAX_RENAMES)
345                         counter = 1;
346         } while (((rc = access(path, 0)) == 0) && (counter != start));
347
348         if (verbose > 0)
349                 rprintf(FINFO,"renaming %s to %s because of text busy\n",
350                                             fname, path);
351
352         /* maybe we should return rename()'s exit status? Nah. */
353         if (do_rename(fname, path) != 0) {
354                 errno = ETXTBSY;
355                 return -1;
356         }
357         return 0;
358 #endif
359 }
360
361 int robust_rename(char *from, char *to)
362 {
363 #ifndef ETXTBSY
364         return do_rename(from, to);
365 #else
366         int rc = do_rename(from, to);
367         if ((rc == 0) || (errno != ETXTBSY))
368                 return rc;
369         if (robust_unlink(to) != 0)
370                 return -1;
371         return do_rename(from, to);
372 #endif
373 }
374
375
376 static pid_t all_pids[10];
377 static int num_pids;
378
379 /** Fork and record the pid of the child. **/
380 pid_t do_fork(void)
381 {
382         pid_t newpid = fork();
383         
384         if (newpid != 0  &&  newpid != -1) {
385                 all_pids[num_pids++] = newpid;
386         }
387         return newpid;
388 }
389
390 /**
391  * Kill all children.
392  *
393  * @todo It would be kind of nice to make sure that they are actually
394  * all our children before we kill them, because their pids may have
395  * been recycled by some other process.  Perhaps when we wait for a
396  * child, we should remove it from this array.  Alternatively we could
397  * perhaps use process groups, but I think that would not work on
398  * ancient Unix versions that don't support them.
399  **/
400 void kill_all(int sig)
401 {
402         int i;
403
404         for (i = 0; i < num_pids; i++) {
405                 /* Let's just be a little careful where we
406                  * point that gun, hey?  See kill(2) for the
407                  * magic caused by negative values. */
408                 pid_t p = all_pids[i];
409
410                 if (p == getpid())
411                         continue;
412                 if (p <= 0)
413                         continue;
414
415                 kill(p, sig);
416         }
417 }
418
419
420 /** Turn a user name into a uid */
421 int name_to_uid(char *name, uid_t *uid)
422 {
423         struct passwd *pass;
424         if (!name || !*name) return 0;
425         pass = getpwnam(name);
426         if (pass) {
427                 *uid = pass->pw_uid;
428                 return 1;
429         }
430         return 0;
431 }
432
433 /** Turn a group name into a gid */
434 int name_to_gid(char *name, gid_t *gid)
435 {
436         struct group *grp;
437         if (!name || !*name) return 0;
438         grp = getgrnam(name);
439         if (grp) {
440                 *gid = grp->gr_gid;
441                 return 1;
442         }
443         return 0;
444 }
445
446
447 /** Lock a byte range in a open file */
448 int lock_range(int fd, int offset, int len)
449 {
450         struct flock lock;
451
452         lock.l_type = F_WRLCK;
453         lock.l_whence = SEEK_SET;
454         lock.l_start = offset;
455         lock.l_len = len;
456         lock.l_pid = 0;
457         
458         return fcntl(fd,F_SETLK,&lock) == 0;
459 }
460
461
462 static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
463 {
464 #if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
465         if (!*s) s = ".";
466         argv[*argc] = strdup(s);
467         (*argc)++;
468         return;
469 #else
470         extern int sanitize_paths;
471         glob_t globbuf;
472         int i;
473
474         if (!*s) s = ".";
475
476         argv[*argc] = strdup(s);
477         if (sanitize_paths) {
478                 sanitize_path(argv[*argc], NULL);
479         }
480
481         memset(&globbuf, 0, sizeof(globbuf));
482         glob(argv[*argc], 0, NULL, &globbuf);
483         if (globbuf.gl_pathc == 0) {
484                 (*argc)++;
485                 globfree(&globbuf);
486                 return;
487         }
488         for (i=0; i<(maxargs - (*argc)) && i < (int) globbuf.gl_pathc;i++) {
489                 if (i == 0) free(argv[*argc]);
490                 argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
491                 if (!argv[(*argc) + i]) out_of_memory("glob_expand");
492         }
493         globfree(&globbuf);
494         (*argc) += i;
495 #endif
496 }
497
498 void glob_expand(char *base1, char **argv, int *argc, int maxargs)
499 {
500         char *s = argv[*argc];
501         char *p, *q;
502         char *base = base1;
503
504         if (!s || !*s) return;
505
506         if (strncmp(s, base, strlen(base)) == 0) {
507                 s += strlen(base);
508         }
509
510         s = strdup(s);
511         if (!s) out_of_memory("glob_expand");
512
513         if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
514
515         q = s;
516         while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
517                 /* split it at this point */
518                 *p = 0;
519                 glob_expand_one(q, argv, argc, maxargs);
520                 q = p+strlen(base);
521         }
522
523         if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
524
525         free(s);
526         free(base);
527 }
528
529 /**
530  * Convert a string to lower case
531  **/
532 void strlower(char *s)
533 {
534         while (*s) {
535                 if (isupper(* (unsigned char *) s))
536                         *s = tolower(* (unsigned char *) s);
537                 s++;
538         }
539 }
540
541 void *Realloc(void *p, int size)
542 {
543         if (!p) return (void *)malloc(size);
544         return (void *)realloc(p, size);
545 }
546
547
548 void clean_fname(char *name)
549 {
550         char *p;
551         int l;
552         int modified = 1;
553
554         if (!name) return;
555
556         while (modified) {
557                 modified = 0;
558
559                 if ((p=strstr(name,"/./"))) {
560                         modified = 1;
561                         while (*p) {
562                                 p[0] = p[2];
563                                 p++;
564                         }
565                 }
566
567                 if ((p=strstr(name,"//"))) {
568                         modified = 1;
569                         while (*p) {
570                                 p[0] = p[1];
571                                 p++;
572                         }
573                 }
574
575                 if (strncmp(p=name,"./",2) == 0) {      
576                         modified = 1;
577                         do {
578                                 p[0] = p[2];
579                         } while (*p++);
580                 }
581
582                 l = strlen(p=name);
583                 if (l > 1 && p[l-1] == '/') {
584                         modified = 1;
585                         p[l-1] = 0;
586                 }
587         }
588 }
589
590 /**
591  * Make path appear as if a chroot had occurred:
592  *
593  * @li 1. remove leading "/" (or replace with "." if at end)
594  *
595  * @li 2. remove leading ".." components (except those allowed by @p reldir)
596  *
597  * @li 3. delete any other "<dir>/.." (recursively)
598  *
599  * Can only shrink paths, so sanitizes in place.
600  *
601  * While we're at it, remove double slashes and "." components like
602  *   clean_fname() does, but DON'T remove a trailing slash because that
603  *   is sometimes significant on command line arguments.
604  *
605  * If @p reldir is non-null, it is a sanitized directory that the path will be
606  *    relative to, so allow as many ".." at the beginning of the path as
607  *    there are components in reldir.  This is used for symbolic link targets.
608  *    If reldir is non-null and the path began with "/", to be completely like
609  *    a chroot we should add in depth levels of ".." at the beginning of the
610  *    path, but that would blow the assumption that the path doesn't grow and
611  *    it is not likely to end up being a valid symlink anyway, so just do
612  *    the normal removal of the leading "/" instead.
613  *
614  * Contributed by Dave Dykstra <dwd@bell-labs.com>
615  */
616 void sanitize_path(char *p, char *reldir)
617 {
618         char *start, *sanp;
619         int depth = 0;
620         int allowdotdot = 0;
621
622         if (reldir) {
623                 depth++;
624                 while (*reldir) {
625                         if (*reldir++ == '/') {
626                                 depth++;
627                         }
628                 }
629         }
630         start = p;
631         sanp = p;
632         while (*p == '/') {
633                 /* remove leading slashes */
634                 p++;
635         }
636         while (*p != '\0') {
637                 /* this loop iterates once per filename component in p.
638                  * both p (and sanp if the original had a slash) should
639                  * always be left pointing after a slash
640                  */
641                 if ((*p == '.') && ((*(p+1) == '/') || (*(p+1) == '\0'))) {
642                         /* skip "." component */
643                         while (*++p == '/') {
644                                 /* skip following slashes */
645                                 ;
646                         }
647                         continue;
648                 }
649                 allowdotdot = 0;
650                 if ((*p == '.') && (*(p+1) == '.') &&
651                             ((*(p+2) == '/') || (*(p+2) == '\0'))) {
652                         /* ".." component followed by slash or end */
653                         if ((depth > 0) && (sanp == start)) {
654                                 /* allow depth levels of .. at the beginning */
655                                 --depth;
656                                 allowdotdot = 1;
657                         } else {
658                                 p += 2;
659                                 if (*p == '/')
660                                         p++;
661                                 if (sanp != start) {
662                                         /* back up sanp one level */
663                                         --sanp; /* now pointing at slash */
664                                         while ((sanp > start) && (*(sanp - 1) != '/')) {
665                                                 /* skip back up to slash */
666                                                 sanp--;
667                                         }
668                                 }
669                                 continue;
670                         }
671                 }
672                 while (1) {
673                         /* copy one component through next slash */
674                         *sanp++ = *p++;
675                         if ((*p == '\0') || (*(p-1) == '/')) {
676                                 while (*p == '/') {
677                                         /* skip multiple slashes */
678                                         p++;
679                                 }
680                                 break;
681                         }
682                 }
683                 if (allowdotdot) {
684                         /* move the virtual beginning to leave the .. alone */
685                         start = sanp;
686                 }
687         }
688         if ((sanp == start) && !allowdotdot) {
689                 /* ended up with nothing, so put in "." component */
690                 /*
691                  * note that the !allowdotdot doesn't prevent this from
692                  *  happening in all allowed ".." situations, but I didn't
693                  *  think it was worth putting in an extra variable to ensure
694                  *  it since an extra "." won't hurt in those situations.
695                  */
696                 *sanp++ = '.';
697         }
698         *sanp = '\0';
699 }
700
701
702 static char curr_dir[MAXPATHLEN];
703
704 /**
705  * Like chdir() but can be reversed with pop_dir() if @p save is set.
706  * It is also much faster as it remembers where we have been.
707  **/
708 char *push_dir(char *dir, int save)
709 {
710         char *ret = curr_dir;
711         static int initialised;
712
713         if (!initialised) {
714                 initialised = 1;
715                 getcwd(curr_dir, sizeof(curr_dir)-1);
716         }
717
718         if (!dir) return NULL; /* this call was probably just to initialize */
719
720         if (chdir(dir)) return NULL;
721
722         if (save) {
723                 ret = strdup(curr_dir);
724         }
725
726         if (*dir == '/') {
727                 strlcpy(curr_dir, dir, sizeof(curr_dir));
728         } else {
729                 strlcat(curr_dir,"/", sizeof(curr_dir));
730                 strlcat(curr_dir,dir, sizeof(curr_dir));
731         }
732
733         clean_fname(curr_dir);
734
735         return ret;
736 }
737
738 /** Reverse a push_dir() call */
739 int pop_dir(char *dir)
740 {
741         int ret;
742
743         ret = chdir(dir);
744         if (ret) {
745                 free(dir);
746                 return ret;
747         }
748
749         strlcpy(curr_dir, dir, sizeof(curr_dir));
750
751         free(dir);
752
753         return 0;
754 }
755
756 /** We need to supply our own strcmp function for file list comparisons
757    to ensure that signed/unsigned usage is consistent between machines. */
758 int u_strcmp(const char *cs1, const char *cs2)
759 {
760         const uchar *s1 = (const uchar *)cs1;
761         const uchar *s2 = (const uchar *)cs2;
762
763         while (*s1 && *s2 && (*s1 == *s2)) {
764                 s1++; s2++;
765         }
766         
767         return (int)*s1 - (int)*s2;
768 }
769
770
771
772 /**
773  * Determine if a symlink points outside the current directory tree.
774  * This is considered "unsafe" because e.g. when mirroring somebody
775  * else's machine it might allow them to establish a symlink to
776  * /etc/passwd, and then read it through a web server.
777  *
778  * Null symlinks and absolute symlinks are always unsafe.
779  *
780  * Basically here we are concerned with symlinks whose target contains
781  * "..", because this might cause us to walk back up out of the
782  * transferred directory.  We are not allowed to go back up and
783  * reenter.
784  *
785  * @param dest Target of the symlink in question.
786  *
787  * @param src Top source directory currently applicable.  Basically this
788  * is the first parameter to rsync in a simple invocation, but it's
789  * modified by flist.c in slightly complex ways.
790  *
791  * @retval True if unsafe
792  * @retval False is unsafe
793  *
794  * @sa t_unsafe.c
795  **/
796 int unsafe_symlink(const char *dest_path, const char *src_path)
797 {
798         char *tok, *src, *dest;
799         int depth = 0;
800
801         /* all absolute and null symlinks are unsafe */
802         if (!dest_path || !*dest_path || *dest_path == '/') return 1;
803
804         src = strdup(src_path);
805         if (!src) out_of_memory("unsafe_symlink");
806
807         /* find out what our safety margin is */
808         for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) {
809                 if (strcmp(tok,"..") == 0) {
810                         depth=0;
811                 } else if (strcmp(tok,".") == 0) {
812                         /* nothing */
813                 } else {
814                         depth++;
815                 }
816         }
817         free(src);
818
819         /* drop by one to account for the filename portion */
820         depth--;
821
822         dest = strdup(dest_path);
823         if (!dest) out_of_memory("unsafe_symlink");
824
825         for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) {
826                 if (strcmp(tok,"..") == 0) {
827                         depth--;
828                 } else if (strcmp(tok,".") == 0) {
829                         /* nothing */
830                 } else {
831                         depth++;
832                 }
833                 /* if at any point we go outside the current directory then
834                    stop - it is unsafe */
835                 if (depth < 0) break;
836         }
837
838         free(dest);
839         return (depth < 0);
840 }
841
842
843 /**
844  * Return the date and time as a string
845  **/
846 char *timestring(time_t t)
847 {
848         static char TimeBuf[200];
849         struct tm *tm = localtime(&t);
850
851 #ifdef HAVE_STRFTIME
852         strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
853 #else
854         strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf));
855 #endif
856
857         if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
858                 TimeBuf[strlen(TimeBuf)-1] = 0;
859         }
860
861         return(TimeBuf);
862 }
863
864
865 /**
866  * Sleep for a specified number of milliseconds.
867  *
868  * Always returns TRUE.  (In the future it might return FALSE if
869  * interrupted.)
870  **/
871 int msleep(int t)
872 {
873         int tdiff=0;
874         struct timeval tval,t1,t2;  
875
876         gettimeofday(&t1, NULL);
877         gettimeofday(&t2, NULL);
878   
879         while (tdiff < t) {
880                 tval.tv_sec = (t-tdiff)/1000;
881                 tval.tv_usec = 1000*((t-tdiff)%1000);
882  
883                 errno = 0;
884                 select(0,NULL,NULL, NULL, &tval);
885
886                 gettimeofday(&t2, NULL);
887                 tdiff = (t2.tv_sec - t1.tv_sec)*1000 + 
888                         (t2.tv_usec - t1.tv_usec)/1000;
889         }
890
891         return True;
892 }
893
894
895 /**
896  * Determine if two file modification times are equivalent (either
897  * exact or in the modification timestamp window established by
898  * --modify-window).
899  *
900  * @retval 0 if the times should be treated as the same
901  *
902  * @retval +1 if the first is later
903  *
904  * @retval -1 if the 2nd is later
905  **/
906 int cmp_modtime(time_t file1, time_t file2)
907 {
908         extern int modify_window;
909
910         if (file2 > file1) {
911                 if (file2 - file1 <= modify_window) return 0;
912                 return -1;
913         }
914         if (file1 - file2 <= modify_window) return 0;
915         return 1;
916 }
917
918
919 #ifdef __INSURE__XX
920 #include <dlfcn.h>
921
922 /**
923    This routine is a trick to immediately catch errors when debugging
924    with insure. A xterm with a gdb is popped up when insure catches
925    a error. It is Linux specific.
926 **/
927 int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
928 {
929         static int (*fn)();
930         int ret;
931         char *cmd;
932
933         asprintf(&cmd, "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'", 
934                 getpid(), getpid(), getpid());
935
936         if (!fn) {
937                 static void *h;
938                 h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
939                 fn = dlsym(h, "_Insure_trap_error");
940         }
941
942         ret = fn(a1, a2, a3, a4, a5, a6);
943
944         system(cmd);
945
946         free(cmd);
947
948         return ret;
949 }
950 #endif