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