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, now) 386 char *date; 387 struct timeb *now; 388 { 389 time_t foo = 0; 390 391 return (foo); 392 } 393 #endif 394 #endif 395 396 /* Given two revisions, find their greatest common ancestor. If the 397 two input revisions exist, then rcs guarantees that the gca will 398 exist. */ 399 400 char * 401 gca (rev1, rev2) 402 const char *rev1; 403 const char *rev2; 404 { 405 int dots; 406 char *gca; 407 const char *p[2]; 408 int j[2]; 409 char *retval; 410 411 if (rev1 == NULL || rev2 == NULL) 412 { 413 error (0, 0, "sanity failure in gca"); 414 abort(); 415 } 416 417 /* The greatest common ancestor will have no more dots, and numbers 418 of digits for each component no greater than the arguments. Therefore 419 this string will be big enough. */ 420 gca = xmalloc (strlen (rev1) + strlen (rev2) + 100); 421 422 /* walk the strings, reading the common parts. */ 423 gca[0] = '\0'; 424 p[0] = rev1; 425 p[1] = rev2; 426 do 427 { 428 int i; 429 char c[2]; 430 char *s[2]; 431 432 for (i = 0; i < 2; ++i) 433 { 434 /* swap out the dot */ 435 s[i] = strchr (p[i], '.'); 436 if (s[i] != NULL) { 437 c[i] = *s[i]; 438 } 439 440 /* read an int */ 441 j[i] = atoi (p[i]); 442 443 /* swap back the dot... */ 444 if (s[i] != NULL) { 445 *s[i] = c[i]; 446 p[i] = s[i] + 1; 447 } 448 else 449 { 450 /* or mark us at the end */ 451 p[i] = NULL; 452 } 453 454 } 455 456 /* use the lowest. */ 457 (void) sprintf (gca + strlen (gca), "%d.", 458 j[0] < j[1] ? j[0] : j[1]); 459 460 } while (j[0] == j[1] 461 && p[0] != NULL 462 && p[1] != NULL); 463 464 /* back up over that last dot. */ 465 gca[strlen(gca) - 1] = '\0'; 466 467 /* numbers differ, or we ran out of strings. we're done with the 468 common parts. */ 469 470 dots = numdots (gca); 471 if (dots == 0) 472 { 473 /* revisions differ in trunk major number. */ 474 475 char *q; 476 const char *s; 477 478 s = (j[0] < j[1]) ? p[0] : p[1]; 479 480 if (s == NULL) 481 { 482 /* we only got one number. this is strange. */ 483 error (0, 0, "bad revisions %s or %s", rev1, rev2); 484 abort(); 485 } 486 else 487 { 488 /* we have a minor number. use it. */ 489 q = gca + strlen (gca); 490 491 *q++ = '.'; 492 for ( ; *s != '.' && *s != '\0'; ) 493 *q++ = *s++; 494 495 *q = '\0'; 496 } 497 } 498 else if ((dots & 1) == 0) 499 { 500 /* if we have an even number of dots, then we have a branch. 501 remove the last number in order to make it a revision. */ 502 503 char *s; 504 505 s = strrchr(gca, '.'); 506 *s = '\0'; 507 } 508 509 retval = xstrdup (gca); 510 free (gca); 511 return retval; 512 } 513 514 /* Give fatal error if REV is numeric and ARGC,ARGV imply we are 515 planning to operate on more than one file. The current directory 516 should be the working directory. Note that callers assume that we 517 will only be checking the first character of REV; it need not have 518 '\0' at the end of the tag name and other niceties. Right now this 519 is only called from admin.c, but if people like the concept it probably 520 should also be called from diff -r, update -r, get -r, and log -r. */ 521 522 void 523 check_numeric (rev, argc, argv) 524 const char *rev; 525 int argc; 526 char **argv; 527 { 528 if (rev == NULL || !isdigit ((unsigned char) *rev)) 529 return; 530 531 /* Note that the check for whether we are processing more than one 532 file is (basically) syntactic; that is, we don't behave differently 533 depending on whether a directory happens to contain only a single 534 file or whether it contains more than one. I strongly suspect this 535 is the least confusing behavior. */ 536 if (argc != 1 537 || (!wrap_name_has (argv[0], WRAP_TOCVS) && isdir (argv[0]))) 538 { 539 error (0, 0, "while processing more than one file:"); 540 error (1, 0, "attempt to specify a numeric revision"); 541 } 542 } 543 544 /* 545 * Sanity checks and any required fix-up on message passed to RCS via '-m'. 546 * RCS 5.7 requires that a non-total-whitespace, non-null message be provided 547 * with '-m'. Returns a newly allocated, non-empty buffer with whitespace 548 * stripped from end of lines and end of buffer. 549 * 550 * TODO: We no longer use RCS to manage repository files, so maybe this 551 * nonsense about non-empty log fields can be dropped. 552 */ 553 char * 554 make_message_rcslegal (message) 555 char *message; 556 { 557 char *dst, *dp, *mp; 558 559 if (message == NULL) message = ""; 560 561 /* Strip whitespace from end of lines and end of string. */ 562 dp = dst = (char *) xmalloc (strlen (message) + 1); 563 for (mp = message; *mp != '\0'; ++mp) 564 { 565 if (*mp == '\n') 566 { 567 /* At end-of-line; backtrack to last non-space. */ 568 while (dp > dst && (dp[-1] == ' ' || dp[-1] == '\t')) 569 --dp; 570 } 571 *dp++ = *mp; 572 } 573 574 /* Backtrack to last non-space at end of string, and truncate. */ 575 while (dp > dst && isspace ((unsigned char) dp[-1])) 576 --dp; 577 *dp = '\0'; 578 579 /* After all that, if there was no non-space in the string, 580 substitute a non-empty message. */ 581 if (*dst == '\0') 582 { 583 free (dst); 584 dst = xstrdup ("*** empty log message ***"); 585 } 586 587 return dst; 588 } 589 590 /* Does the file FINFO contain conflict markers? The whole concept 591 of looking at the contents of the file to figure out whether there are 592 unresolved conflicts is kind of bogus (people do want to manage files 593 which contain those patterns not as conflict markers), but for now it 594 is what we do. */ 595 int 596 file_has_markers (finfo) 597 const struct file_info *finfo; 598 { 599 FILE *fp; 600 char *line = NULL; 601 size_t line_allocated = 0; 602 int result; 603 604 result = 0; 605 fp = CVS_FOPEN (finfo->file, "r"); 606 if (fp == NULL) 607 error (1, errno, "cannot open %s", finfo->fullname); 608 while (get_line (&line, &line_allocated, fp) > 0) 609 { 610 if (strncmp (line, RCS_MERGE_PAT_1, sizeof RCS_MERGE_PAT_1 - 1) == 0 || 611 strncmp (line, RCS_MERGE_PAT_2, sizeof RCS_MERGE_PAT_2 - 1) == 0 || 612 strncmp (line, RCS_MERGE_PAT_3, sizeof RCS_MERGE_PAT_3 - 1) == 0) 613 { 614 result = 1; 615 goto out; 616 } 617 } 618 if (ferror (fp)) 619 error (0, errno, "cannot read %s", finfo->fullname); 620 out: 621 if (fclose (fp) < 0) 622 error (0, errno, "cannot close %s", finfo->fullname); 623 if (line != NULL) 624 free (line); 625 return result; 626 } 627 628 /* Read the entire contents of the file NAME into *BUF. 629 If NAME is NULL, read from stdin. *BUF 630 is a pointer returned from malloc (or NULL), pointing to *BUFSIZE 631 bytes of space. The actual size is returned in *LEN. On error, 632 give a fatal error. The name of the file to use in error messages 633 (typically will include a directory if we have changed directory) 634 is FULLNAME. MODE is "r" for text or "rb" for binary. */ 635 636 void 637 get_file (name, fullname, mode, buf, bufsize, len) 638 const char *name; 639 const char *fullname; 640 const char *mode; 641 char **buf; 642 size_t *bufsize; 643 size_t *len; 644 { 645 struct stat s; 646 size_t nread; 647 char *tobuf; 648 FILE *e; 649 size_t filesize; 650 651 if (name == NULL) 652 { 653 e = stdin; 654 filesize = 100; /* force allocation of minimum buffer */ 655 } 656 else 657 { 658 /* Although it would be cleaner in some ways to just read 659 until end of file, reallocating the buffer, this function 660 does get called on files in the working directory which can 661 be of arbitrary size, so I think we better do all that 662 extra allocation. */ 663 664 if (CVS_STAT (name, &s) < 0) 665 error (1, errno, "can't stat %s", fullname); 666 667 /* Convert from signed to unsigned. */ 668 filesize = s.st_size; 669 670 e = open_file (name, mode); 671 } 672 673 if (*buf == NULL || *bufsize <= filesize) 674 { 675 *bufsize = filesize + 1; 676 *buf = xrealloc (*buf, *bufsize); 677 } 678 679 tobuf = *buf; 680 nread = 0; 681 while (1) 682 { 683 size_t got; 684 685 got = fread (tobuf, 1, *bufsize - (tobuf - *buf), e); 686 if (ferror (e)) 687 error (1, errno, "can't read %s", fullname); 688 nread += got; 689 tobuf += got; 690 691 if (feof (e)) 692 break; 693 694 /* Allocate more space if needed. */ 695 if (tobuf == *buf + *bufsize) 696 { 697 int c; 698 long off; 699 700 c = getc (e); 701 if (c == EOF) 702 break; 703 off = tobuf - *buf; 704 expand_string (buf, bufsize, *bufsize + 100); 705 tobuf = *buf + off; 706 *tobuf++ = c; 707 ++nread; 708 } 709 } 710 711 if (e != stdin && fclose (e) < 0) 712 error (0, errno, "cannot close %s", fullname); 713 714 *len = nread; 715 716 /* Force *BUF to be large enough to hold a null terminator. */ 717 if (nread == *bufsize) 718 expand_string (buf, bufsize, *bufsize + 1); 719 (*buf)[nread] = '\0'; 720 } 721 722 723 /* Follow a chain of symbolic links to its destination. FILENAME 724 should be a handle to a malloc'd block of memory which contains the 725 beginning of the chain. This routine will replace the contents of 726 FILENAME with the destination (a real file). */ 727 728 void 729 resolve_symlink (filename) 730 char **filename; 731 { 732 if ((! filename) || (! *filename)) 733 return; 734 735 while (islink (*filename)) 736 { 737 char *newname; 738 #ifdef HAVE_READLINK 739 /* The clean thing to do is probably to have each filesubr.c 740 implement this (with an error if not supported by the 741 platform, in which case islink would presumably return 0). 742 But that would require editing each filesubr.c and so the 743 expedient hack seems to be looking at HAVE_READLINK. */ 744 newname = xreadlink (*filename); 745 #else 746 error (1, 0, "internal error: islink doesn't like readlink"); 747 #endif 748 749 if (isabsolute (newname)) 750 { 751 free (*filename); 752 *filename = newname; 753 } 754 else 755 { 756 char *oldname = last_component (*filename); 757 int dirlen = oldname - *filename; 758 char *fullnewname = xmalloc (dirlen + strlen (newname) + 1); 759 strncpy (fullnewname, *filename, dirlen); 760 strcpy (fullnewname + dirlen, newname); 761 free (newname); 762 free (*filename); 763 *filename = fullnewname; 764 } 765 } 766 } 767 768 /* 769 * Rename a file to an appropriate backup name based on BAKPREFIX. 770 * If suffix non-null, then ".<suffix>" is appended to the new name. 771 * 772 * Returns the new name, which caller may free() if desired. 773 */ 774 char * 775 backup_file (filename, suffix) 776 const char *filename; 777 const char *suffix; 778 { 779 char *backup_name; 780 781 if (suffix == NULL) 782 { 783 backup_name = xmalloc (sizeof (BAKPREFIX) + strlen (filename) + 1); 784 sprintf (backup_name, "%s%s", BAKPREFIX, filename); 785 } 786 else 787 { 788 backup_name = xmalloc (sizeof (BAKPREFIX) 789 + strlen (filename) 790 + strlen (suffix) 791 + 2); /* one for dot, one for trailing '\0' */ 792 sprintf (backup_name, "%s%s.%s", BAKPREFIX, filename, suffix); 793 } 794 795 if (isfile (filename)) 796 copy_file (filename, backup_name); 797 798 return backup_name; 799 } 800 801 /* 802 * Copy a string into a buffer escaping any shell metacharacters. The 803 * buffer should be at least twice as long as the string. 804 * 805 * Returns a pointer to the terminating NUL byte in buffer. 806 */ 807 808 char * 809 shell_escape(buf, str) 810 char *buf; 811 const char *str; 812 { 813 static const char meta[] = "$`\\\""; 814 const char *p; 815 816 for (;;) 817 { 818 p = strpbrk(str, meta); 819 if (!p) p = str + strlen(str); 820 if (p > str) 821 { 822 memcpy(buf, str, p - str); 823 buf += p - str; 824 } 825 if (!*p) break; 826 *buf++ = '\\'; 827 *buf++ = *p++; 828 str = p; 829 } 830 *buf = '\0'; 831 return buf; 832 } 833 834 /* 835 * We can only travel forwards in time, not backwards. :) 836 */ 837 void 838 sleep_past (desttime) 839 time_t desttime; 840 { 841 time_t t; 842 long s; 843 long us; 844 845 while (time (&t) <= desttime) 846 { 847 #ifdef HAVE_GETTIMEOFDAY 848 struct timeval tv; 849 gettimeofday (&tv, NULL); 850 if (tv.tv_sec > desttime) 851 break; 852 s = desttime - tv.tv_sec; 853 if (tv.tv_usec > 0) 854 us = 1000000 - tv.tv_usec; 855 else 856 { 857 s++; 858 us = 0; 859 } 860 #else 861 /* default to 20 ms increments */ 862 s = desttime - t; 863 us = 20000; 864 #endif 865 866 #if defined(HAVE_NANOSLEEP) 867 { 868 struct timespec ts; 869 ts.tv_sec = s; 870 ts.tv_nsec = us * 1000; 871 (void)nanosleep (&ts, NULL); 872 } 873 #elif defined(HAVE_USLEEP) 874 if (s > 0) 875 (void)sleep (s); 876 else 877 (void)usleep (us); 878 #elif defined(HAVE_SELECT) 879 { 880 /* use select instead of sleep since it is a fairly portable way of 881 * sleeping for ms. 882 */ 883 struct timeval tv; 884 tv.tv_sec = s; 885 tv.tv_usec = us; 886 (void)select (0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL, &tv); 887 } 888 #else 889 if (us > 0) s++; 890 (void)sleep(s); 891 #endif 892 } 893 } 894