1 /* $NetBSD: utils.c,v 1.5 2021/01/09 16:39:28 christos Exp $ */ 2 3 /* 4 * utils.c - various utility functions used in pppd. 5 * 6 * Copyright (c) 1999-2002 Paul Mackerras. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. The name(s) of the authors of this software must not be used to 16 * endorse or promote products derived from this software without 17 * prior written permission. 18 * 19 * 3. Redistributions of any form whatsoever must retain the following 20 * acknowledgment: 21 * "This product includes software developed by Paul Mackerras 22 * <paulus@samba.org>". 23 * 24 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO 25 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 26 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY 27 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 28 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 29 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 30 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 31 */ 32 33 #include <sys/cdefs.h> 34 __RCSID("$NetBSD: utils.c,v 1.5 2021/01/09 16:39:28 christos Exp $"); 35 36 #include <stdarg.h> 37 #include <stdio.h> 38 #include <ctype.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 #include <signal.h> 43 #include <errno.h> 44 #include <fcntl.h> 45 #include <syslog.h> 46 #include <netdb.h> 47 #include <time.h> 48 #include <utmp.h> 49 #include <pwd.h> 50 #include <sys/param.h> 51 #include <sys/types.h> 52 #include <sys/wait.h> 53 #include <sys/time.h> 54 #include <sys/resource.h> 55 #include <sys/stat.h> 56 #include <sys/socket.h> 57 #include <netinet/in.h> 58 #ifdef SVR4 59 #include <sys/mkdev.h> 60 #endif 61 62 #include "pppd.h" 63 #include "fsm.h" 64 #include "lcp.h" 65 66 67 #if defined(SUNOS4) 68 extern char *strerror(); 69 #endif 70 71 static void logit(int, char *, va_list); 72 static void log_write(int, char *); 73 static void vslp_printer(void *, char *, ...); 74 static void format_packet(u_char *, int, printer_func, void *); 75 76 struct buffer_info { 77 char *ptr; 78 int len; 79 }; 80 81 /* 82 * slprintf - format a message into a buffer. Like sprintf except we 83 * also specify the length of the output buffer, and we handle 84 * %m (error message), %v (visible string), 85 * %q (quoted string), %t (current time) and %I (IP address) formats. 86 * Doesn't do floating-point formats. 87 * Returns the number of chars put into buf. 88 */ 89 int 90 slprintf(char *buf, int buflen, char *fmt, ...) 91 { 92 va_list args; 93 int n; 94 95 va_start(args, fmt); 96 n = vslprintf(buf, buflen, fmt, args); 97 va_end(args); 98 return n; 99 } 100 101 /* 102 * vslprintf - like slprintf, takes a va_list instead of a list of args. 103 */ 104 #define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) 105 106 int 107 vslprintf(char *buf, int buflen, char *fmt, va_list args) 108 { 109 int c, i, n; 110 int width, prec, fillch; 111 int base, len, neg, quoted; 112 unsigned long val = 0; 113 char *str, *f, *buf0; 114 unsigned char *p; 115 char num[32]; 116 time_t t; 117 u_int32_t ip; 118 static char hexchars[] = "0123456789abcdef"; 119 struct buffer_info bufinfo; 120 int termch; 121 122 buf0 = buf; 123 --buflen; 124 while (buflen > 0) { 125 for (f = fmt; *f != '%' && *f != 0; ++f) 126 ; 127 if (f > fmt) { 128 len = f - fmt; 129 if (len > buflen) 130 len = buflen; 131 memcpy(buf, fmt, len); 132 buf += len; 133 buflen -= len; 134 fmt = f; 135 } 136 if (*fmt == 0) 137 break; 138 c = *++fmt; 139 width = 0; 140 prec = -1; 141 fillch = ' '; 142 if (c == '0') { 143 fillch = '0'; 144 c = *++fmt; 145 } 146 if (c == '*') { 147 width = va_arg(args, int); 148 c = *++fmt; 149 } else { 150 while (isdigit(c)) { 151 width = width * 10 + c - '0'; 152 c = *++fmt; 153 } 154 } 155 if (c == '.') { 156 c = *++fmt; 157 if (c == '*') { 158 prec = va_arg(args, int); 159 c = *++fmt; 160 } else { 161 prec = 0; 162 while (isdigit(c)) { 163 prec = prec * 10 + c - '0'; 164 c = *++fmt; 165 } 166 } 167 } 168 str = 0; 169 base = 0; 170 neg = 0; 171 ++fmt; 172 switch (c) { 173 case 'l': 174 c = *fmt++; 175 switch (c) { 176 case 'd': 177 val = va_arg(args, long); 178 if (val < 0) { 179 neg = 1; 180 val = -val; 181 } 182 base = 10; 183 break; 184 case 'u': 185 val = va_arg(args, unsigned long); 186 base = 10; 187 break; 188 default: 189 OUTCHAR('%'); 190 OUTCHAR('l'); 191 --fmt; /* so %lz outputs %lz etc. */ 192 continue; 193 } 194 break; 195 case 'd': 196 i = va_arg(args, int); 197 if (i < 0) { 198 neg = 1; 199 val = -i; 200 } else 201 val = i; 202 base = 10; 203 break; 204 case 'u': 205 val = va_arg(args, unsigned int); 206 base = 10; 207 break; 208 case 'o': 209 val = va_arg(args, unsigned int); 210 base = 8; 211 break; 212 case 'x': 213 case 'X': 214 val = va_arg(args, unsigned int); 215 base = 16; 216 break; 217 case 'p': 218 val = (unsigned long) va_arg(args, void *); 219 base = 16; 220 neg = 2; 221 break; 222 case 's': 223 str = va_arg(args, char *); 224 break; 225 case 'c': 226 num[0] = va_arg(args, int); 227 num[1] = 0; 228 str = num; 229 break; 230 case 'm': 231 str = strerror(errno); 232 break; 233 case 'I': 234 ip = va_arg(args, u_int32_t); 235 ip = ntohl(ip); 236 slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff, 237 (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); 238 str = num; 239 break; 240 case 't': 241 time(&t); 242 str = ctime(&t); 243 if ((str = ctime(&t)) == NULL) 244 strlcpy(str = num, "?", sizeof(num)); 245 else { 246 str += 4; /* chop off the day name */ 247 str[15] = 0; /* chop off year and newline */ 248 } 249 break; 250 case 'v': /* "visible" string */ 251 case 'q': /* quoted string */ 252 quoted = c == 'q'; 253 p = va_arg(args, unsigned char *); 254 if (p == NULL) 255 p = (unsigned char *)"<NULL>"; 256 if (fillch == '0' && prec >= 0) { 257 n = prec; 258 termch = -1; /* matches no unsigned char value */ 259 } else { 260 n = buflen; 261 if (prec != -1 && n > prec) 262 n = prec; 263 termch = 0; /* stop on null byte */ 264 } 265 while (n > 0 && buflen > 0) { 266 c = *p++; 267 if (c == termch) 268 break; 269 --n; 270 if (!quoted && c >= 0x80) { 271 OUTCHAR('M'); 272 OUTCHAR('-'); 273 c -= 0x80; 274 } 275 if (quoted && (c == '"' || c == '\\')) 276 OUTCHAR('\\'); 277 if (c < 0x20 || (0x7f <= c && c < 0xa0)) { 278 if (quoted) { 279 OUTCHAR('\\'); 280 switch (c) { 281 case '\t': OUTCHAR('t'); break; 282 case '\n': OUTCHAR('n'); break; 283 case '\b': OUTCHAR('b'); break; 284 case '\f': OUTCHAR('f'); break; 285 default: 286 OUTCHAR('x'); 287 OUTCHAR(hexchars[c >> 4]); 288 OUTCHAR(hexchars[c & 0xf]); 289 } 290 } else { 291 if (c == '\t') 292 OUTCHAR(c); 293 else { 294 OUTCHAR('^'); 295 OUTCHAR(c ^ 0x40); 296 } 297 } 298 } else 299 OUTCHAR(c); 300 } 301 continue; 302 case 'P': /* print PPP packet */ 303 bufinfo.ptr = buf; 304 bufinfo.len = buflen + 1; 305 p = va_arg(args, unsigned char *); 306 n = va_arg(args, int); 307 format_packet(p, n, vslp_printer, &bufinfo); 308 buf = bufinfo.ptr; 309 buflen = bufinfo.len - 1; 310 continue; 311 case 'B': 312 p = va_arg(args, unsigned char *); 313 for (n = prec; n > 0; --n) { 314 c = *p++; 315 if (fillch == ' ') 316 OUTCHAR(' '); 317 OUTCHAR(hexchars[(c >> 4) & 0xf]); 318 OUTCHAR(hexchars[c & 0xf]); 319 } 320 continue; 321 default: 322 *buf++ = '%'; 323 if (c != '%') 324 --fmt; /* so %z outputs %z etc. */ 325 --buflen; 326 continue; 327 } 328 if (base != 0) { 329 str = num + sizeof(num); 330 *--str = 0; 331 while (str > num + neg) { 332 *--str = hexchars[val % base]; 333 val = val / base; 334 if (--prec <= 0 && val == 0) 335 break; 336 } 337 switch (neg) { 338 case 1: 339 *--str = '-'; 340 break; 341 case 2: 342 *--str = 'x'; 343 *--str = '0'; 344 break; 345 } 346 len = num + sizeof(num) - 1 - str; 347 } else { 348 for (len = 0; len < buflen && (prec == -1 || len < prec); ++len) 349 if (str[len] == 0) 350 break; 351 } 352 if (width > 0) { 353 if (width > buflen) 354 width = buflen; 355 if ((n = width - len) > 0) { 356 buflen -= n; 357 for (; n > 0; --n) 358 *buf++ = fillch; 359 } 360 } 361 if (len > buflen) 362 len = buflen; 363 memcpy(buf, str, len); 364 buf += len; 365 buflen -= len; 366 } 367 *buf = 0; 368 return buf - buf0; 369 } 370 371 /* 372 * vslp_printer - used in processing a %P format 373 */ 374 static void 375 vslp_printer(void *arg, char *fmt, ...) 376 { 377 int n; 378 va_list pvar; 379 struct buffer_info *bi; 380 381 va_start(pvar, fmt); 382 383 bi = (struct buffer_info *) arg; 384 n = vslprintf(bi->ptr, bi->len, fmt, pvar); 385 va_end(pvar); 386 387 bi->ptr += n; 388 bi->len -= n; 389 } 390 391 #ifdef unused 392 /* 393 * log_packet - format a packet and log it. 394 */ 395 396 void 397 log_packet(u_char *p, int len, char *prefix, int level) 398 { 399 init_pr_log(prefix, level); 400 format_packet(p, len, pr_log, &level); 401 end_pr_log(); 402 } 403 #endif /* unused */ 404 405 /* 406 * format_packet - make a readable representation of a packet, 407 * calling `printer(arg, format, ...)' to output it. 408 */ 409 static void 410 format_packet(u_char *p, int len, printer_func printer, void *arg) 411 { 412 int i, n; 413 u_short proto; 414 struct protent *protp; 415 416 if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) { 417 p += 2; 418 GETSHORT(proto, p); 419 len -= PPP_HDRLEN; 420 for (i = 0; (protp = protocols[i]) != NULL; ++i) 421 if (proto == protp->protocol) 422 break; 423 if (protp != NULL) { 424 printer(arg, "[%s", protp->name); 425 n = (*protp->printpkt)(p, len, printer, arg); 426 printer(arg, "]"); 427 p += n; 428 len -= n; 429 } else { 430 for (i = 0; (protp = protocols[i]) != NULL; ++i) 431 if (proto == (protp->protocol & ~0x8000)) 432 break; 433 if (protp != 0 && protp->data_name != 0) { 434 printer(arg, "[%s data]", protp->data_name); 435 if (len > 8) 436 printer(arg, "%.8B ...", p); 437 else 438 printer(arg, "%.*B", len, p); 439 len = 0; 440 } else 441 printer(arg, "[proto=0x%x]", proto); 442 } 443 } 444 445 if (len > 32) 446 printer(arg, "%.32B ...", p); 447 else 448 printer(arg, "%.*B", len, p); 449 } 450 451 /* 452 * init_pr_log, end_pr_log - initialize and finish use of pr_log. 453 */ 454 455 static char line[256]; /* line to be logged accumulated here */ 456 static char *linep; /* current pointer within line */ 457 static int llevel; /* level for logging */ 458 459 void 460 init_pr_log(const char *prefix, int level) 461 { 462 linep = line; 463 if (prefix != NULL) { 464 strlcpy(line, prefix, sizeof(line)); 465 linep = line + strlen(line); 466 } 467 llevel = level; 468 } 469 470 void 471 end_pr_log(void) 472 { 473 if (linep != line) { 474 *linep = 0; 475 log_write(llevel, line); 476 } 477 } 478 479 /* 480 * pr_log - printer routine for outputting to syslog 481 */ 482 void 483 pr_log(void *arg, char *fmt, ...) 484 { 485 int l, n; 486 va_list pvar; 487 char *p, *eol; 488 char buf[256]; 489 490 va_start(pvar, fmt); 491 492 n = vslprintf(buf, sizeof(buf), fmt, pvar); 493 va_end(pvar); 494 495 p = buf; 496 eol = strchr(buf, '\n'); 497 if (linep != line) { 498 l = (eol == NULL)? n: eol - buf; 499 if (linep + l < line + sizeof(line)) { 500 if (l > 0) { 501 memcpy(linep, buf, l); 502 linep += l; 503 } 504 if (eol == NULL) 505 return; 506 p = eol + 1; 507 eol = strchr(p, '\n'); 508 } 509 *linep = 0; 510 log_write(llevel, line); 511 linep = line; 512 } 513 514 while (eol != NULL) { 515 *eol = 0; 516 log_write(llevel, p); 517 p = eol + 1; 518 eol = strchr(p, '\n'); 519 } 520 521 /* assumes sizeof(buf) <= sizeof(line) */ 522 l = buf + n - p; 523 if (l > 0) { 524 memcpy(line, p, n); 525 linep = line + l; 526 } 527 } 528 529 /* 530 * print_string - print a readable representation of a string using 531 * printer. 532 */ 533 void 534 print_string(char *p, int len, printer_func printer, void *arg) 535 { 536 int c; 537 538 printer(arg, "\""); 539 for (; len > 0; --len) { 540 c = *p++; 541 if (' ' <= c && c <= '~') { 542 if (c == '\\' || c == '"') 543 printer(arg, "\\"); 544 printer(arg, "%c", c); 545 } else { 546 switch (c) { 547 case '\n': 548 printer(arg, "\\n"); 549 break; 550 case '\r': 551 printer(arg, "\\r"); 552 break; 553 case '\t': 554 printer(arg, "\\t"); 555 break; 556 default: 557 printer(arg, "\\%.3o", (unsigned char) c); 558 } 559 } 560 } 561 printer(arg, "\""); 562 } 563 564 /* 565 * logit - does the hard work for fatal et al. 566 */ 567 static void 568 logit(int level, char *fmt, va_list args) 569 { 570 char buf[1024]; 571 572 vslprintf(buf, sizeof(buf), fmt, args); 573 log_write(level, buf); 574 } 575 576 static void 577 log_write(int level, char *buf) 578 { 579 syslog(level, "%s", buf); 580 if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { 581 int n = strlen(buf); 582 583 if (n > 0 && buf[n-1] == '\n') 584 --n; 585 if (write(log_to_fd, buf, n) != n 586 || write(log_to_fd, "\n", 1) != 1) 587 log_to_fd = -1; 588 } 589 } 590 591 /* 592 * fatal - log an error message and die horribly. 593 */ 594 void 595 fatal(char *fmt, ...) 596 { 597 va_list pvar; 598 599 va_start(pvar, fmt); 600 601 logit(LOG_ERR, fmt, pvar); 602 va_end(pvar); 603 604 die(1); /* as promised */ 605 } 606 607 /* 608 * error - log an error message. 609 */ 610 void 611 error(char *fmt, ...) 612 { 613 va_list pvar; 614 615 va_start(pvar, fmt); 616 617 logit(LOG_ERR, fmt, pvar); 618 va_end(pvar); 619 ++error_count; 620 } 621 622 /* 623 * warn - log a warning message. 624 */ 625 void 626 warn(char *fmt, ...) 627 { 628 va_list pvar; 629 630 va_start(pvar, fmt); 631 632 logit(LOG_WARNING, fmt, pvar); 633 va_end(pvar); 634 } 635 636 /* 637 * notice - log a notice-level message. 638 */ 639 void 640 notice(char *fmt, ...) 641 { 642 va_list pvar; 643 644 va_start(pvar, fmt); 645 646 logit(LOG_NOTICE, fmt, pvar); 647 va_end(pvar); 648 } 649 650 /* 651 * info - log an informational message. 652 */ 653 void 654 info(char *fmt, ...) 655 { 656 va_list pvar; 657 658 va_start(pvar, fmt); 659 660 logit(LOG_INFO, fmt, pvar); 661 va_end(pvar); 662 } 663 664 /* 665 * dbglog - log a debug message. 666 */ 667 void 668 dbglog(char *fmt, ...) 669 { 670 va_list pvar; 671 672 va_start(pvar, fmt); 673 674 logit(LOG_DEBUG, fmt, pvar); 675 va_end(pvar); 676 } 677 678 /* 679 * dump_packet - print out a packet in readable form if it is interesting. 680 * Assumes len >= PPP_HDRLEN. 681 */ 682 void 683 dump_packet(const char *tag, unsigned char *p, int len) 684 { 685 int proto; 686 687 if (!debug) 688 return; 689 690 /* 691 * don't print LCP echo request/reply packets if debug <= 1 692 * and the link is up. 693 */ 694 proto = (p[2] << 8) + p[3]; 695 if (debug <= 1 && unsuccess == 0 && proto == PPP_LCP 696 && len >= PPP_HDRLEN + HEADERLEN) { 697 unsigned char *lcp = p + PPP_HDRLEN; 698 int l = (lcp[2] << 8) + lcp[3]; 699 700 if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP) 701 && l >= HEADERLEN && l <= len - PPP_HDRLEN) 702 return; 703 } 704 705 dbglog("%s %P", tag, p, len); 706 } 707 708 /* 709 * complete_read - read a full `count' bytes from fd, 710 * unless end-of-file or an error other than EINTR is encountered. 711 */ 712 ssize_t 713 complete_read(int fd, void *buf, size_t count) 714 { 715 size_t done; 716 ssize_t nb; 717 char *ptr = buf; 718 719 for (done = 0; done < count; ) { 720 nb = read(fd, ptr, count - done); 721 if (nb < 0) { 722 if (errno == EINTR && !got_sigterm) 723 continue; 724 return -1; 725 } 726 if (nb == 0) 727 break; 728 done += nb; 729 ptr += nb; 730 } 731 return done; 732 } 733 734 /* Procedures for locking the serial device using a lock file. */ 735 #ifndef LOCK_DIR 736 #ifdef __linux__ 737 #define LOCK_DIR "/var/lock" 738 #else 739 #ifdef SVR4 740 #define LOCK_DIR "/var/spool/locks" 741 #else 742 #define LOCK_DIR "/var/spool/lock" 743 #endif 744 #endif 745 #endif /* LOCK_DIR */ 746 747 static char lock_file[MAXPATHLEN]; 748 749 /* 750 * lock - create a lock file for the named device 751 */ 752 int 753 lock(char *dev) 754 { 755 #ifdef LOCKLIB 756 int result; 757 758 result = mklock (dev, (void *) 0); 759 if (result == 0) { 760 strlcpy(lock_file, dev, sizeof(lock_file)); 761 return 0; 762 } 763 764 if (result > 0) 765 notice("Device %s is locked by pid %d", dev, result); 766 else 767 error("Can't create lock file %s", lock_file); 768 return -1; 769 770 #else /* LOCKLIB */ 771 772 char lock_buffer[12]; 773 int fd, pid, n; 774 775 #ifdef SVR4 776 struct stat sbuf; 777 778 if (stat(dev, &sbuf) < 0) { 779 error("Can't get device number for %s: %m", dev); 780 return -1; 781 } 782 if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { 783 error("Can't lock %s: not a character device", dev); 784 return -1; 785 } 786 slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", 787 LOCK_DIR, major(sbuf.st_dev), 788 major(sbuf.st_rdev), minor(sbuf.st_rdev)); 789 #else 790 char *p; 791 char lockdev[MAXPATHLEN]; 792 793 if ((p = strstr(dev, "dev/")) != NULL) { 794 dev = p + 4; 795 strncpy(lockdev, dev, MAXPATHLEN-1); 796 lockdev[MAXPATHLEN-1] = 0; 797 while ((p = strrchr(lockdev, '/')) != NULL) { 798 *p = '_'; 799 } 800 dev = lockdev; 801 } else 802 if ((p = strrchr(dev, '/')) != NULL) 803 dev = p + 1; 804 805 slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); 806 #endif 807 808 while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { 809 if (errno != EEXIST) { 810 error("Can't create lock file %s: %m", lock_file); 811 break; 812 } 813 814 /* Read the lock file to find out who has the device locked. */ 815 fd = open(lock_file, O_RDONLY, 0); 816 if (fd < 0) { 817 if (errno == ENOENT) /* This is just a timing problem. */ 818 continue; 819 error("Can't open existing lock file %s: %m", lock_file); 820 break; 821 } 822 #ifndef LOCK_BINARY 823 n = read(fd, lock_buffer, 11); 824 #else 825 n = read(fd, &pid, sizeof(pid)); 826 #endif /* LOCK_BINARY */ 827 close(fd); 828 fd = -1; 829 if (n <= 0) { 830 error("Can't read pid from lock file %s", lock_file); 831 break; 832 } 833 834 /* See if the process still exists. */ 835 #ifndef LOCK_BINARY 836 lock_buffer[n] = 0; 837 pid = atoi(lock_buffer); 838 #endif /* LOCK_BINARY */ 839 if (pid == getpid()) 840 return 1; /* somebody else locked it for us */ 841 if (pid == 0 842 || (kill(pid, 0) == -1 && errno == ESRCH)) { 843 if (unlink (lock_file) == 0) { 844 notice("Removed stale lock on %s (pid %d)", dev, pid); 845 continue; 846 } 847 warn("Couldn't remove stale lock on %s", dev); 848 } else 849 notice("Device %s is locked by pid %d", dev, pid); 850 break; 851 } 852 853 if (fd < 0) { 854 lock_file[0] = 0; 855 return -1; 856 } 857 858 pid = getpid(); 859 #ifndef LOCK_BINARY 860 slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); 861 write (fd, lock_buffer, 11); 862 #else 863 write(fd, &pid, sizeof (pid)); 864 #endif 865 close(fd); 866 return 0; 867 868 #endif 869 } 870 871 /* 872 * relock - called to update our lockfile when we are about to detach, 873 * thus changing our pid (we fork, the child carries on, and the parent dies). 874 * Note that this is called by the parent, with pid equal to the pid 875 * of the child. This avoids a potential race which would exist if 876 * we had the child rewrite the lockfile (the parent might die first, 877 * and another process could think the lock was stale if it checked 878 * between when the parent died and the child rewrote the lockfile). 879 */ 880 int 881 relock(int pid) 882 { 883 #ifdef LOCKLIB 884 /* XXX is there a way to do this? */ 885 return -1; 886 #else /* LOCKLIB */ 887 888 int fd; 889 char lock_buffer[12]; 890 891 if (lock_file[0] == 0) 892 return -1; 893 fd = open(lock_file, O_WRONLY, 0); 894 if (fd < 0) { 895 error("Couldn't reopen lock file %s: %m", lock_file); 896 lock_file[0] = 0; 897 return -1; 898 } 899 900 #ifndef LOCK_BINARY 901 slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); 902 write (fd, lock_buffer, 11); 903 #else 904 write(fd, &pid, sizeof(pid)); 905 #endif /* LOCK_BINARY */ 906 close(fd); 907 return 0; 908 909 #endif /* LOCKLIB */ 910 } 911 912 /* 913 * unlock - remove our lockfile 914 */ 915 void 916 unlock(void) 917 { 918 if (lock_file[0]) { 919 #ifdef LOCKLIB 920 (void) rmlock(lock_file, (void *) 0); 921 #else 922 unlink(lock_file); 923 #endif 924 lock_file[0] = 0; 925 } 926 } 927 928