1 /* 2 * Copyright (c) 1992, Brian Berliner and Jeff Polk 3 * Copyright (c) 1989-1992, Brian Berliner 4 * 5 * You may distribute under the terms of the GNU General Public License as 6 * specified in the README file that comes with the CVS source distribution. 7 * 8 * Various useful functions for the CVS support code. 9 */ 10 11 #include "cvs.h" 12 #include "getline.h" 13 14 #ifdef HAVE_NANOSLEEP 15 # include "xtime.h" 16 #else /* HAVE_NANOSLEEP */ 17 # if !defined HAVE_USLEEP && defined HAVE_SELECT 18 /* use select as a workaround */ 19 # include "xselect.h" 20 # endif /* !defined HAVE_USLEEP && defined HAVE_SELECT */ 21 #endif /* !HAVE_NANOSLEEP */ 22 23 extern char *getlogin (); 24 25 /* 26 * malloc some data and die if it fails 27 */ 28 void * 29 xmalloc (bytes) 30 size_t bytes; 31 { 32 char *cp; 33 34 /* Parts of CVS try to xmalloc zero bytes and then free it. Some 35 systems have a malloc which returns NULL for zero byte 36 allocations but a free which can't handle NULL, so compensate. */ 37 if (bytes == 0) 38 bytes = 1; 39 40 cp = malloc (bytes); 41 if (cp == NULL) 42 { 43 char buf[80]; 44 snprintf (buf, sizeof buf, "out of memory; can not allocate %lu bytes", 45 (unsigned long) bytes); 46 error (1, 0, buf); 47 } 48 return (cp); 49 } 50 51 /* 52 * realloc data and die if it fails [I've always wanted to have "realloc" do 53 * a "malloc" if the argument is NULL, but you can't depend on it. Here, I 54 * can *force* it. 55 */ 56 void * 57 xrealloc (ptr, bytes) 58 void *ptr; 59 size_t bytes; 60 { 61 char *cp; 62 63 if (!ptr) 64 cp = malloc (bytes); 65 else 66 cp = realloc (ptr, bytes); 67 68 if (cp == NULL) 69 { 70 char buf[80]; 71 snprintf (buf, sizeof buf, "out of memory; can not reallocate %lu bytes", 72 (unsigned long) bytes); 73 error (1, 0, buf); 74 } 75 return (cp); 76 } 77 78 /* Two constants which tune expand_string. Having MIN_INCR as large 79 as 1024 might waste a bit of memory, but it shouldn't be too bad 80 (CVS used to allocate arrays of, say, 3000, PATH_MAX (8192, often), 81 or other such sizes). Probably anything which is going to allocate 82 memory which is likely to get as big as MAX_INCR shouldn't be doing 83 it in one block which must be contiguous, but since getrcskey does 84 so, we might as well limit the wasted memory to MAX_INCR or so 85 bytes. 86 87 MIN_INCR and MAX_INCR should both be powers of two and we generally 88 try to keep our allocations to powers of two for the most part. 89 Most malloc implementations these days tend to like that. */ 90 91 #define MIN_INCR 1024 92 #define MAX_INCR (2*1024*1024) 93 94 /* *STRPTR is a pointer returned from malloc (or NULL), pointing to *N 95 characters of space. Reallocate it so that points to at least 96 NEWSIZE bytes of space. Gives a fatal error if out of memory; 97 if it returns it was successful. */ 98 void 99 expand_string (strptr, n, newsize) 100 char **strptr; 101 size_t *n; 102 size_t newsize; 103 { 104 if (*n < newsize) 105 { 106 while (*n < newsize) 107 { 108 if (*n < MIN_INCR) 109 *n = MIN_INCR; 110 else if (*n >= MAX_INCR) 111 *n += MAX_INCR; 112 else 113 { 114 *n *= 2; 115 if (*n > MAX_INCR) 116 *n = MAX_INCR; 117 } 118 } 119 *strptr = xrealloc (*strptr, *n); 120 } 121 } 122 123 /* *STR is a pointer to a malloc'd string. *LENP is its allocated 124 length. Add SRC to the end of it, reallocating if necessary. */ 125 void 126 allocate_and_strcat (str, lenp, src) 127 char **str; 128 size_t *lenp; 129 const char *src; 130 { 131 132 expand_string (str, lenp, strlen (*str) + strlen (src) + 1); 133 strcat (*str, src); 134 } 135 136 /* 137 * Duplicate a string, calling xmalloc to allocate some dynamic space 138 */ 139 char * 140 xstrdup (str) 141 const char *str; 142 { 143 char *s; 144 145 if (str == NULL) 146 return ((char *) NULL); 147 s = xmalloc (strlen (str) + 1); 148 (void) strcpy (s, str); 149 return (s); 150 } 151 152 /* Remove trailing newlines from STRING, destructively. */ 153 void 154 strip_trailing_newlines (str) 155 char *str; 156 { 157 int len; 158 len = strlen (str) - 1; 159 160 while (str[len] == '\n') 161 str[len--] = '\0'; 162 } 163 164 /* Return the number of levels that path ascends above where it starts. 165 For example: 166 "../../foo" -> 2 167 "foo/../../bar" -> 1 168 */ 169 /* FIXME: Should be using ISDIRSEP, last_component, or some other 170 mechanism which is more general than just looking at slashes, 171 particularly for the client.c caller. The server.c caller might 172 want something different, so be careful. */ 173 int 174 pathname_levels (path) 175 char *path; 176 { 177 char *p; 178 char *q; 179 int level; 180 int max_level; 181 182 max_level = 0; 183 p = path; 184 level = 0; 185 do 186 { 187 q = strchr (p, '/'); 188 if (q != NULL) 189 ++q; 190 if (p[0] == '.' && p[1] == '.' && (p[2] == '\0' || p[2] == '/')) 191 { 192 --level; 193 if (-level > max_level) 194 max_level = -level; 195 } 196 else if (p[0] == '\0' || p[0] == '/' || 197 (p[0] == '.' && (p[1] == '\0' || p[1] == '/'))) 198 ; 199 else 200 ++level; 201 p = q; 202 } while (p != NULL); 203 return max_level; 204 } 205 206 207 /* Free a vector, where (*ARGV)[0], (*ARGV)[1], ... (*ARGV)[*PARGC - 1] 208 are malloc'd and so is *ARGV itself. Such a vector is allocated by 209 line2argv or expand_wild, for example. */ 210 void 211 free_names (pargc, argv) 212 int *pargc; 213 char **argv; 214 { 215 register int i; 216 217 for (i = 0; i < *pargc; i++) 218 { /* only do through *pargc */ 219 free (argv[i]); 220 } 221 free (argv); 222 *pargc = 0; /* and set it to zero when done */ 223 } 224 225 /* Convert LINE into arguments separated by SEPCHARS. Set *ARGC 226 to the number of arguments found, and (*ARGV)[0] to the first argument, 227 (*ARGV)[1] to the second, etc. *ARGV is malloc'd and so are each of 228 (*ARGV)[0], (*ARGV)[1], ... Use free_names() to return the memory 229 allocated here back to the free pool. */ 230 void 231 line2argv (pargc, argv, line, sepchars) 232 int *pargc; 233 char ***argv; 234 char *line; 235 char *sepchars; 236 { 237 char *cp; 238 /* Could make a case for size_t or some other unsigned type, but 239 we'll stick with int to avoid signed/unsigned warnings when 240 comparing with *pargc. */ 241 int argv_allocated; 242 243 /* Small for testing. */ 244 argv_allocated = 1; 245 *argv = (char **) xmalloc (argv_allocated * sizeof (**argv)); 246 247 *pargc = 0; 248 for (cp = strtok (line, sepchars); cp; cp = strtok ((char *) NULL, sepchars)) 249 { 250 if (*pargc == argv_allocated) 251 { 252 argv_allocated *= 2; 253 *argv = xrealloc (*argv, argv_allocated * sizeof (**argv)); 254 } 255 (*argv)[*pargc] = xstrdup (cp); 256 (*pargc)++; 257 } 258 } 259 260 /* 261 * Returns the number of dots ('.') found in an RCS revision number 262 */ 263 int 264 numdots (s) 265 const char *s; 266 { 267 int dots = 0; 268 269 for (; *s; s++) 270 { 271 if (*s == '.') 272 dots++; 273 } 274 return (dots); 275 } 276 277 /* Compare revision numbers REV1 and REV2 by consecutive fields. 278 Return negative, zero, or positive in the manner of strcmp. The 279 two revision numbers must have the same number of fields, or else 280 compare_revnums will return an inaccurate result. */ 281 int 282 compare_revnums (rev1, rev2) 283 const char *rev1; 284 const char *rev2; 285 { 286 const char *s, *sp; 287 const char *t, *tp; 288 char *snext, *tnext; 289 int result = 0; 290 291 sp = s = rev1; 292 tp = t = rev2; 293 while (result == 0) 294 { 295 result = strtoul (sp, &snext, 10) - strtoul (tp, &tnext, 10); 296 if (*snext == '\0' || *tnext == '\0') 297 break; 298 sp = snext + 1; 299 tp = tnext + 1; 300 } 301 302 return result; 303 } 304 305 char * 306 increment_revnum (rev) 307 const char *rev; 308 { 309 char *newrev, *p; 310 int lastfield; 311 size_t len = strlen (rev); 312 313 newrev = (char *) xmalloc (len + 2); 314 memcpy (newrev, rev, len + 1); 315 p = strrchr (newrev, '.'); 316 if (p == NULL) 317 { 318 free (newrev); 319 return NULL; 320 } 321 lastfield = atoi (++p); 322 sprintf (p, "%d", lastfield + 1); 323 324 return newrev; 325 } 326 327 /* Return the username by which the caller should be identified in 328 CVS, in contexts such as the author field of RCS files, various 329 logs, etc. */ 330 char * 331 getcaller () 332 { 333 #ifndef SYSTEM_GETCALLER 334 static char *cache; 335 struct passwd *pw; 336 uid_t uid; 337 #endif 338 339 /* If there is a CVS username, return it. */ 340 #ifdef AUTH_SERVER_SUPPORT 341 if (CVS_Username != NULL) 342 return CVS_Username; 343 #endif 344 345 #ifdef SYSTEM_GETCALLER 346 return SYSTEM_GETCALLER (); 347 #else 348 /* Get the caller's login from his uid. If the real uid is "root" 349 try LOGNAME USER or getlogin(). If getlogin() and getpwuid() 350 both fail, return the uid as a string. */ 351 352 if (cache != NULL) 353 return cache; 354 355 uid = getuid (); 356 if (uid == (uid_t) 0) 357 { 358 char *name; 359 360 /* super-user; try getlogin() to distinguish */ 361 if (((name = getlogin ()) || (name = getenv("LOGNAME")) || 362 (name = getenv("USER"))) && *name) 363 { 364 cache = xstrdup (name); 365 return cache; 366 } 367 } 368 if ((pw = (struct passwd *) getpwuid (uid)) == NULL) 369 { 370 char uidname[20]; 371 372 (void) snprintf (uidname, sizeof uidname, "uid%lu", (unsigned long) uid); 373 cache = xstrdup (uidname); 374 return cache; 375 } 376 cache = xstrdup (pw->pw_name); 377 return cache; 378 #endif 379 } 380 381 #ifdef lint 382 #ifndef __GNUC__ 383 /* ARGSUSED */ 384 time_t 385 get_date (date) 386 char *date; 387 { 388 time_t foo = 0; 389 390 return (foo); 391 } 392 #endif 393 #endif 394 395 /* Given two revisions, find their greatest common ancestor. If the 396 two input revisions exist, then rcs guarantees that the gca will 397 exist. */ 398 399 char * 400 gca (rev1, rev2) 401 const char *rev1; 402 const char *rev2; 403 { 404 int dots; 405 char *gca; 406 const char *p[2]; 407 int j[2]; 408 char *retval; 409 410 if (rev1 == NULL || rev2 == NULL) 411 { 412 error (0, 0, "sanity failure in gca"); 413 abort(); 414 } 415 416 /* The greatest common ancestor will have no more dots, and numbers 417 of digits for each component no greater than the arguments. Therefore 418 this string will be big enough. */ 419 gca = xmalloc (strlen (rev1) + strlen (rev2) + 100); 420 421 /* walk the strings, reading the common parts. */ 422 gca[0] = '\0'; 423 p[0] = rev1; 424 p[1] = rev2; 425 do 426 { 427 int i; 428 char c[2]; 429 char *s[2]; 430 431 for (i = 0; i < 2; ++i) 432 { 433 /* swap out the dot */ 434 s[i] = strchr (p[i], '.'); 435 if (s[i] != NULL) { 436 c[i] = *s[i]; 437 } 438 439 /* read an int */ 440 j[i] = atoi (p[i]); 441 442 /* swap back the dot... */ 443 if (s[i] != NULL) { 444 *s[i] = c[i]; 445 p[i] = s[i] + 1; 446 } 447 else 448 { 449 /* or mark us at the end */ 450 p[i] = NULL; 451 } 452 453 } 454 455 /* use the lowest. */ 456 (void) sprintf (gca + strlen (gca), "%d.", 457 j[0] < j[1] ? j[0] : j[1]); 458 459 } while (j[0] == j[1] 460 && p[0] != NULL 461 && p[1] != NULL); 462 463 /* back up over that last dot. */ 464 gca[strlen(gca) - 1] = '\0'; 465 466 /* numbers differ, or we ran out of strings. we're done with the 467 common parts. */ 468 469 dots = numdots (gca); 470 if (dots == 0) 471 { 472 /* revisions differ in trunk major number. */ 473 474 char *q; 475 const char *s; 476 477 s = (j[0] < j[1]) ? p[0] : p[1]; 478 479 if (s == NULL) 480 { 481 /* we only got one number. this is strange. */ 482 error (0, 0, "bad revisions %s or %s", rev1, rev2); 483 abort(); 484 } 485 else 486 { 487 /* we have a minor number. use it. */ 488 q = gca + strlen (gca); 489 490 *q++ = '.'; 491 for ( ; *s != '.' && *s != '\0'; ) 492 *q++ = *s++; 493 494 *q = '\0'; 495 } 496 } 497 else if ((dots & 1) == 0) 498 { 499 /* if we have an even number of dots, then we have a branch. 500 remove the last number in order to make it a revision. */ 501 502 char *s; 503 504 s = strrchr(gca, '.'); 505 *s = '\0'; 506 } 507 508 retval = xstrdup (gca); 509 free (gca); 510 return retval; 511 } 512 513 /* Give fatal error if REV is numeric and ARGC,ARGV imply we are 514 planning to operate on more than one file. The current directory 515 should be the working directory. Note that callers assume that we 516 will only be checking the first character of REV; it need not have 517 '\0' at the end of the tag name and other niceties. Right now this 518 is only called from admin.c, but if people like the concept it probably 519 should also be called from diff -r, update -r, get -r, and log -r. */ 520 521 void 522 check_numeric (rev, argc, argv) 523 const char *rev; 524 int argc; 525 char **argv; 526 { 527 if (rev == NULL || !isdigit ((unsigned char) *rev)) 528 return; 529 530 /* Note that the check for whether we are processing more than one 531 file is (basically) syntactic; that is, we don't behave differently 532 depending on whether a directory happens to contain only a single 533 file or whether it contains more than one. I strongly suspect this 534 is the least confusing behavior. */ 535 if (argc != 1 536 || (!wrap_name_has (argv[0], WRAP_TOCVS) && isdir (argv[0]))) 537 { 538 error (0, 0, "while processing more than one file:"); 539 error (1, 0, "attempt to specify a numeric revision"); 540 } 541 } 542 543 /* 544 * Sanity checks and any required fix-up on message passed to RCS via '-m'. 545 * RCS 5.7 requires that a non-total-whitespace, non-null message be provided 546 * with '-m'. Returns a newly allocated, non-empty buffer with whitespace 547 * stripped from end of lines and end of buffer. 548 * 549 * TODO: We no longer use RCS to manage repository files, so maybe this 550 * nonsense about non-empty log fields can be dropped. 551 */ 552 char * 553 make_message_rcslegal (message) 554 char *message; 555 { 556 char *dst, *dp, *mp; 557 558 if (message == NULL) message = ""; 559 560 /* Strip whitespace from end of lines and end of string. */ 561 dp = dst = (char *) xmalloc (strlen (message) + 1); 562 for (mp = message; *mp != '\0'; ++mp) 563 { 564 if (*mp == '\n') 565 { 566 /* At end-of-line; backtrack to last non-space. */ 567 while (dp > dst && (dp[-1] == ' ' || dp[-1] == '\t')) 568 --dp; 569 } 570 *dp++ = *mp; 571 } 572 573 /* Backtrack to last non-space at end of string, and truncate. */ 574 while (dp > dst && isspace ((unsigned char) dp[-1])) 575 --dp; 576 *dp = '\0'; 577 578 /* After all that, if there was no non-space in the string, 579 substitute a non-empty message. */ 580 if (*dst == '\0') 581 { 582 free (dst); 583 dst = xstrdup ("*** empty log message ***"); 584 } 585 586 return dst; 587 } 588 589 /* Does the file FINFO contain conflict markers? The whole concept 590 of looking at the contents of the file to figure out whether there are 591 unresolved conflicts is kind of bogus (people do want to manage files 592 which contain those patterns not as conflict markers), but for now it 593 is what we do. */ 594 int 595 file_has_markers (finfo) 596 const struct file_info *finfo; 597 { 598 FILE *fp; 599 char *line = NULL; 600 size_t line_allocated = 0; 601 int result; 602 603 result = 0; 604 fp = CVS_FOPEN (finfo->file, "r"); 605 if (fp == NULL) 606 error (1, errno, "cannot open %s", finfo->fullname); 607 while (get_line (&line, &line_allocated, fp) > 0) 608 { 609 if (strncmp (line, RCS_MERGE_PAT_1, sizeof RCS_MERGE_PAT_1 - 1) == 0 || 610 strncmp (line, RCS_MERGE_PAT_2, sizeof RCS_MERGE_PAT_2 - 1) == 0 || 611 strncmp (line, RCS_MERGE_PAT_3, sizeof RCS_MERGE_PAT_3 - 1) == 0) 612 { 613 result = 1; 614 goto out; 615 } 616 } 617 if (ferror (fp)) 618 error (0, errno, "cannot read %s", finfo->fullname); 619 out: 620 if (fclose (fp) < 0) 621 error (0, errno, "cannot close %s", finfo->fullname); 622 if (line != NULL) 623 free (line); 624 return result; 625 } 626 627 /* Read the entire contents of the file NAME into *BUF. 628 If NAME is NULL, read from stdin. *BUF 629 is a pointer returned from malloc (or NULL), pointing to *BUFSIZE 630 bytes of space. The actual size is returned in *LEN. On error, 631 give a fatal error. The name of the file to use in error messages 632 (typically will include a directory if we have changed directory) 633 is FULLNAME. MODE is "r" for text or "rb" for binary. */ 634 635 void 636 get_file (name, fullname, mode, buf, bufsize, len) 637 const char *name; 638 const char *fullname; 639 const char *mode; 640 char **buf; 641 size_t *bufsize; 642 size_t *len; 643 { 644 struct stat s; 645 size_t nread; 646 char *tobuf; 647 FILE *e; 648 size_t filesize; 649 650 if (name == NULL) 651 { 652 e = stdin; 653 filesize = 100; /* force allocation of minimum buffer */ 654 } 655 else 656 { 657 /* Although it would be cleaner in some ways to just read 658 until end of file, reallocating the buffer, this function 659 does get called on files in the working directory which can 660 be of arbitrary size, so I think we better do all that 661 extra allocation. */ 662 663 if (CVS_STAT (name, &s) < 0) 664 error (1, errno, "can't stat %s", fullname); 665 666 /* Convert from signed to unsigned. */ 667 filesize = s.st_size; 668 669 e = open_file (name, mode); 670 } 671 672 if (*buf == NULL || *bufsize <= filesize) 673 { 674 *bufsize = filesize + 1; 675 *buf = xrealloc (*buf, *bufsize); 676 } 677 678 tobuf = *buf; 679 nread = 0; 680 while (1) 681 { 682 size_t got; 683 684 got = fread (tobuf, 1, *bufsize - (tobuf - *buf), e); 685 if (ferror (e)) 686 error (1, errno, "can't read %s", fullname); 687 nread += got; 688 tobuf += got; 689 690 if (feof (e)) 691 break; 692 693 /* Allocate more space if needed. */ 694 if (tobuf == *buf + *bufsize) 695 { 696 int c; 697 long off; 698 699 c = getc (e); 700 if (c == EOF) 701 break; 702 off = tobuf - *buf; 703 expand_string (buf, bufsize, *bufsize + 100); 704 tobuf = *buf + off; 705 *tobuf++ = c; 706 ++nread; 707 } 708 } 709 710 if (e != stdin && fclose (e) < 0) 711 error (0, errno, "cannot close %s", fullname); 712 713 *len = nread; 714 715 /* Force *BUF to be large enough to hold a null terminator. */ 716 if (nread == *bufsize) 717 expand_string (buf, bufsize, *bufsize + 1); 718 (*buf)[nread] = '\0'; 719 } 720 721 722 /* Follow a chain of symbolic links to its destination. FILENAME 723 should be a handle to a malloc'd block of memory which contains the 724 beginning of the chain. This routine will replace the contents of 725 FILENAME with the destination (a real file). */ 726 727 void 728 resolve_symlink (filename) 729 char **filename; 730 { 731 if ((! filename) || (! *filename)) 732 return; 733 734 while (islink (*filename)) 735 { 736 char *newname; 737 #ifdef HAVE_READLINK 738 /* The clean thing to do is probably to have each filesubr.c 739 implement this (with an error if not supported by the 740 platform, in which case islink would presumably return 0). 741 But that would require editing each filesubr.c and so the 742 expedient hack seems to be looking at HAVE_READLINK. */ 743 newname = xreadlink (*filename); 744 #else 745 error (1, 0, "internal error: islink doesn't like readlink"); 746 #endif 747 748 if (isabsolute (newname)) 749 { 750 free (*filename); 751 *filename = newname; 752 } 753 else 754 { 755 char *oldname = last_component (*filename); 756 int dirlen = oldname - *filename; 757 char *fullnewname = xmalloc (dirlen + strlen (newname) + 1); 758 strncpy (fullnewname, *filename, dirlen); 759 strcpy (fullnewname + dirlen, newname); 760 free (newname); 761 free (*filename); 762 *filename = fullnewname; 763 } 764 } 765 } 766 767 /* 768 * Rename a file to an appropriate backup name based on BAKPREFIX. 769 * If suffix non-null, then ".<suffix>" is appended to the new name. 770 * 771 * Returns the new name, which caller may free() if desired. 772 */ 773 char * 774 backup_file (filename, suffix) 775 const char *filename; 776 const char *suffix; 777 { 778 char *backup_name; 779 780 if (suffix == NULL) 781 { 782 backup_name = xmalloc (sizeof (BAKPREFIX) + strlen (filename) + 1); 783 sprintf (backup_name, "%s%s", BAKPREFIX, filename); 784 } 785 else 786 { 787 backup_name = xmalloc (sizeof (BAKPREFIX) 788 + strlen (filename) 789 + strlen (suffix) 790 + 2); /* one for dot, one for trailing '\0' */ 791 sprintf (backup_name, "%s%s.%s", BAKPREFIX, filename, suffix); 792 } 793 794 if (isfile (filename)) 795 copy_file (filename, backup_name); 796 797 return backup_name; 798 } 799 800 /* 801 * Copy a string into a buffer escaping any shell metacharacters. The 802 * buffer should be at least twice as long as the string. 803 * 804 * Returns a pointer to the terminating NUL byte in buffer. 805 */ 806 807 char * 808 shell_escape(buf, str) 809 char *buf; 810 const char *str; 811 { 812 static const char meta[] = "$`\\\""; 813 const char *p; 814 815 for (;;) 816 { 817 p = strpbrk(str, meta); 818 if (!p) p = str + strlen(str); 819 if (p > str) 820 { 821 memcpy(buf, str, p - str); 822 buf += p - str; 823 } 824 if (!*p) break; 825 *buf++ = '\\'; 826 *buf++ = *p++; 827 str = p; 828 } 829 *buf = '\0'; 830 return buf; 831 } 832 833 /* 834 * We can only travel forwards in time, not backwards. :) 835 */ 836 void 837 sleep_past (desttime) 838 time_t desttime; 839 { 840 time_t t; 841 long s; 842 long us; 843 844 while (time (&t) <= desttime) 845 { 846 #ifdef HAVE_GETTIMEOFDAY 847 struct timeval tv; 848 gettimeofday (&tv, NULL); 849 if (tv.tv_sec > desttime) 850 break; 851 s = desttime - tv.tv_sec; 852 if (tv.tv_usec > 0) 853 us = 1000000 - tv.tv_usec; 854 else 855 { 856 s++; 857 us = 0; 858 } 859 #else 860 /* default to 20 ms increments */ 861 s = desttime - t; 862 us = 20000; 863 #endif 864 865 #if defined(HAVE_NANOSLEEP) 866 { 867 struct timespec ts; 868 ts.tv_sec = s; 869 ts.tv_nsec = us * 1000; 870 (void)nanosleep (&ts, NULL); 871 } 872 #elif defined(HAVE_USLEEP) 873 if (s > 0) 874 (void)sleep (s); 875 else 876 (void)usleep (us); 877 #elif defined(HAVE_SELECT) 878 { 879 /* use select instead of sleep since it is a fairly portable way of 880 * sleeping for ms. 881 */ 882 struct timeval tv; 883 tv.tv_sec = s; 884 tv.tv_usec = us; 885 (void)select (0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL, &tv); 886 } 887 #else 888 if (us > 0) s++; 889 (void)sleep(s); 890 #endif 891 } 892 } 893