Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: blinky_max32630fthr
lwip_utils.c
00001 /* 00002 * utils.c - various utility functions used in pppd. 00003 * 00004 * Copyright (c) 1999-2002 Paul Mackerras. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * 2. The name(s) of the authors of this software must not be used to 00014 * endorse or promote products derived from this software without 00015 * prior written permission. 00016 * 00017 * 3. Redistributions of any form whatsoever must retain the following 00018 * acknowledgment: 00019 * "This product includes software developed by Paul Mackerras 00020 * <paulus@samba.org>". 00021 * 00022 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO 00023 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 00024 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY 00025 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00026 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 00027 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 00028 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00029 */ 00030 00031 #include "netif/ppp/ppp_opts.h" 00032 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00033 00034 #if 0 /* UNUSED */ 00035 #include <stdio.h> 00036 #include <ctype.h> 00037 #include <stdlib.h> 00038 #include <string.h> 00039 #include <unistd.h> 00040 #include <signal.h> 00041 #include <errno.h> 00042 #include <fcntl.h> 00043 #include <syslog.h> 00044 #include <netdb.h> 00045 #include <time.h> 00046 #include <utmp.h> 00047 #include <pwd.h> 00048 #include <sys/param.h> 00049 #include <sys/types.h> 00050 #include <sys/wait.h> 00051 #include <sys/time.h> 00052 #include <sys/resource.h> 00053 #include <sys/stat.h> 00054 #include <sys/socket.h> 00055 #include <netinet/in.h> 00056 #ifdef SVR4 00057 #include <sys/mkdev.h> 00058 #endif 00059 #endif /* UNUSED */ 00060 00061 #include <ctype.h> /* isdigit() */ 00062 00063 #include "netif/ppp/ppp_impl.h" 00064 00065 #include "netif/ppp/fsm.h" 00066 #include "netif/ppp/lcp.h" 00067 00068 #if defined(SUNOS4) 00069 extern char *strerror(); 00070 #endif 00071 00072 static void ppp_logit(int level, const char *fmt, va_list args); 00073 static void ppp_log_write(int level, char *buf); 00074 #if PRINTPKT_SUPPORT 00075 static void ppp_vslp_printer(void *arg, const char *fmt, ...); 00076 static void ppp_format_packet(const u_char *p, int len, 00077 void (*printer) (void *, const char *, ...), void *arg); 00078 00079 struct buffer_info { 00080 char *ptr; 00081 int len; 00082 }; 00083 #endif /* PRINTPKT_SUPPORT */ 00084 00085 /* 00086 * ppp_strlcpy - like strcpy/strncpy, doesn't overflow destination buffer, 00087 * always leaves destination null-terminated (for len > 0). 00088 */ 00089 size_t ppp_strlcpy(char *dest, const char *src, size_t len) { 00090 size_t ret = strlen(src); 00091 00092 if (len != 0) { 00093 if (ret < len) 00094 strcpy(dest, src); 00095 else { 00096 strncpy(dest, src, len - 1); 00097 dest[len-1] = 0; 00098 } 00099 } 00100 return ret; 00101 } 00102 00103 /* 00104 * ppp_strlcat - like strcat/strncat, doesn't overflow destination buffer, 00105 * always leaves destination null-terminated (for len > 0). 00106 */ 00107 size_t ppp_strlcat(char *dest, const char *src, size_t len) { 00108 size_t dlen = strlen(dest); 00109 00110 return dlen + ppp_strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0)); 00111 } 00112 00113 00114 /* 00115 * ppp_slprintf - format a message into a buffer. Like sprintf except we 00116 * also specify the length of the output buffer, and we handle 00117 * %m (error message), %v (visible string), 00118 * %q (quoted string), %t (current time) and %I (IP address) formats. 00119 * Doesn't do floating-point formats. 00120 * Returns the number of chars put into buf. 00121 */ 00122 int ppp_slprintf(char *buf, int buflen, const char *fmt, ...) { 00123 va_list args; 00124 int n; 00125 00126 va_start(args, fmt); 00127 n = ppp_vslprintf(buf, buflen, fmt, args); 00128 va_end(args); 00129 return n; 00130 } 00131 00132 /* 00133 * ppp_vslprintf - like ppp_slprintf, takes a va_list instead of a list of args. 00134 */ 00135 #define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) 00136 00137 int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args) { 00138 int c, i, n; 00139 int width, prec, fillch; 00140 int base, len, neg, quoted; 00141 unsigned long val = 0; 00142 const char *f; 00143 char *str, *buf0; 00144 const unsigned char *p; 00145 char num[32]; 00146 #if 0 /* need port */ 00147 time_t t; 00148 #endif /* need port */ 00149 u32_t ip; 00150 static char hexchars[] = "0123456789abcdef"; 00151 #if PRINTPKT_SUPPORT 00152 struct buffer_info bufinfo; 00153 #endif /* PRINTPKT_SUPPORT */ 00154 00155 buf0 = buf; 00156 --buflen; 00157 while (buflen > 0) { 00158 for (f = fmt; *f != '%' && *f != 0; ++f) 00159 ; 00160 if (f > fmt) { 00161 len = f - fmt; 00162 if (len > buflen) 00163 len = buflen; 00164 memcpy(buf, fmt, len); 00165 buf += len; 00166 buflen -= len; 00167 fmt = f; 00168 } 00169 if (*fmt == 0) 00170 break; 00171 c = *++fmt; 00172 width = 0; 00173 prec = -1; 00174 fillch = ' '; 00175 if (c == '0') { 00176 fillch = '0'; 00177 c = *++fmt; 00178 } 00179 if (c == '*') { 00180 width = va_arg(args, int); 00181 c = *++fmt; 00182 } else { 00183 while (isdigit(c)) { 00184 width = width * 10 + c - '0'; 00185 c = *++fmt; 00186 } 00187 } 00188 if (c == '.') { 00189 c = *++fmt; 00190 if (c == '*') { 00191 prec = va_arg(args, int); 00192 c = *++fmt; 00193 } else { 00194 prec = 0; 00195 while (isdigit(c)) { 00196 prec = prec * 10 + c - '0'; 00197 c = *++fmt; 00198 } 00199 } 00200 } 00201 str = 0; 00202 base = 0; 00203 neg = 0; 00204 ++fmt; 00205 switch (c) { 00206 case 'l': 00207 c = *fmt++; 00208 switch (c) { 00209 case 'd': 00210 val = va_arg(args, long); 00211 if ((long)val < 0) { 00212 neg = 1; 00213 val = (unsigned long)-(long)val; 00214 } 00215 base = 10; 00216 break; 00217 case 'u': 00218 val = va_arg(args, unsigned long); 00219 base = 10; 00220 break; 00221 default: 00222 OUTCHAR('%'); 00223 OUTCHAR('l'); 00224 --fmt; /* so %lz outputs %lz etc. */ 00225 continue; 00226 } 00227 break; 00228 case 'd': 00229 i = va_arg(args, int); 00230 if (i < 0) { 00231 neg = 1; 00232 val = -i; 00233 } else 00234 val = i; 00235 base = 10; 00236 break; 00237 case 'u': 00238 val = va_arg(args, unsigned int); 00239 base = 10; 00240 break; 00241 case 'o': 00242 val = va_arg(args, unsigned int); 00243 base = 8; 00244 break; 00245 case 'x': 00246 case 'X': 00247 val = va_arg(args, unsigned int); 00248 base = 16; 00249 break; 00250 case 'p': 00251 val = (unsigned long) va_arg(args, void *); 00252 base = 16; 00253 neg = 2; 00254 break; 00255 case 's': 00256 str = va_arg(args, char *); 00257 break; 00258 case 'c': 00259 num[0] = va_arg(args, int); 00260 num[1] = 0; 00261 str = num; 00262 break; 00263 #if 0 /* do we always have strerror() in embedded ? */ 00264 case 'm': 00265 str = strerror(errno); 00266 break; 00267 #endif /* do we always have strerror() in embedded ? */ 00268 case 'I': 00269 ip = va_arg(args, u32_t); 00270 ip = ntohl(ip); 00271 ppp_slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff, 00272 (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); 00273 str = num; 00274 break; 00275 #if 0 /* need port */ 00276 case 't': 00277 time(&t); 00278 str = ctime(&t); 00279 str += 4; /* chop off the day name */ 00280 str[15] = 0; /* chop off year and newline */ 00281 break; 00282 #endif /* need port */ 00283 case 'v': /* "visible" string */ 00284 case 'q': /* quoted string */ 00285 quoted = c == 'q'; 00286 p = va_arg(args, unsigned char *); 00287 if (p == NULL) 00288 p = (const unsigned char *)"<NULL>"; 00289 if (fillch == '0' && prec >= 0) { 00290 n = prec; 00291 } else { 00292 n = strlen((const char *)p); 00293 if (prec >= 0 && n > prec) 00294 n = prec; 00295 } 00296 while (n > 0 && buflen > 0) { 00297 c = *p++; 00298 --n; 00299 if (!quoted && c >= 0x80) { 00300 OUTCHAR('M'); 00301 OUTCHAR('-'); 00302 c -= 0x80; 00303 } 00304 if (quoted && (c == '"' || c == '\\')) 00305 OUTCHAR('\\'); 00306 if (c < 0x20 || (0x7f <= c && c < 0xa0)) { 00307 if (quoted) { 00308 OUTCHAR('\\'); 00309 switch (c) { 00310 case '\t': OUTCHAR('t'); break; 00311 case '\n': OUTCHAR('n'); break; 00312 case '\b': OUTCHAR('b'); break; 00313 case '\f': OUTCHAR('f'); break; 00314 default: 00315 OUTCHAR('x'); 00316 OUTCHAR(hexchars[c >> 4]); 00317 OUTCHAR(hexchars[c & 0xf]); 00318 } 00319 } else { 00320 if (c == '\t') 00321 OUTCHAR(c); 00322 else { 00323 OUTCHAR('^'); 00324 OUTCHAR(c ^ 0x40); 00325 } 00326 } 00327 } else 00328 OUTCHAR(c); 00329 } 00330 continue; 00331 #if PRINTPKT_SUPPORT 00332 case 'P': /* print PPP packet */ 00333 bufinfo.ptr = buf; 00334 bufinfo.len = buflen + 1; 00335 p = va_arg(args, unsigned char *); 00336 n = va_arg(args, int); 00337 ppp_format_packet(p, n, ppp_vslp_printer, &bufinfo); 00338 buf = bufinfo.ptr; 00339 buflen = bufinfo.len - 1; 00340 continue; 00341 #endif /* PRINTPKT_SUPPORT */ 00342 case 'B': 00343 p = va_arg(args, unsigned char *); 00344 for (n = prec; n > 0; --n) { 00345 c = *p++; 00346 if (fillch == ' ') 00347 OUTCHAR(' '); 00348 OUTCHAR(hexchars[(c >> 4) & 0xf]); 00349 OUTCHAR(hexchars[c & 0xf]); 00350 } 00351 continue; 00352 default: 00353 *buf++ = '%'; 00354 if (c != '%') 00355 --fmt; /* so %z outputs %z etc. */ 00356 --buflen; 00357 continue; 00358 } 00359 if (base != 0) { 00360 str = num + sizeof(num); 00361 *--str = 0; 00362 while (str > num + neg) { 00363 *--str = hexchars[val % base]; 00364 val = val / base; 00365 if (--prec <= 0 && val == 0) 00366 break; 00367 } 00368 switch (neg) { 00369 case 1: 00370 *--str = '-'; 00371 break; 00372 case 2: 00373 *--str = 'x'; 00374 *--str = '0'; 00375 break; 00376 default: 00377 break; 00378 } 00379 len = num + sizeof(num) - 1 - str; 00380 } else { 00381 len = strlen(str); 00382 if (prec >= 0 && len > prec) 00383 len = prec; 00384 } 00385 if (width > 0) { 00386 if (width > buflen) 00387 width = buflen; 00388 if ((n = width - len) > 0) { 00389 buflen -= n; 00390 for (; n > 0; --n) 00391 *buf++ = fillch; 00392 } 00393 } 00394 if (len > buflen) 00395 len = buflen; 00396 memcpy(buf, str, len); 00397 buf += len; 00398 buflen -= len; 00399 } 00400 *buf = 0; 00401 return buf - buf0; 00402 } 00403 00404 #if PRINTPKT_SUPPORT 00405 /* 00406 * vslp_printer - used in processing a %P format 00407 */ 00408 static void ppp_vslp_printer(void *arg, const char *fmt, ...) { 00409 int n; 00410 va_list pvar; 00411 struct buffer_info *bi; 00412 00413 va_start(pvar, fmt); 00414 bi = (struct buffer_info *) arg; 00415 n = ppp_vslprintf(bi->ptr, bi->len, fmt, pvar); 00416 va_end(pvar); 00417 00418 bi->ptr += n; 00419 bi->len -= n; 00420 } 00421 #endif /* PRINTPKT_SUPPORT */ 00422 00423 #if 0 /* UNUSED */ 00424 /* 00425 * log_packet - format a packet and log it. 00426 */ 00427 00428 void 00429 log_packet(p, len, prefix, level) 00430 u_char *p; 00431 int len; 00432 char *prefix; 00433 int level; 00434 { 00435 init_pr_log(prefix, level); 00436 ppp_format_packet(p, len, pr_log, &level); 00437 end_pr_log(); 00438 } 00439 #endif /* UNUSED */ 00440 00441 #if PRINTPKT_SUPPORT 00442 /* 00443 * ppp_format_packet - make a readable representation of a packet, 00444 * calling `printer(arg, format, ...)' to output it. 00445 */ 00446 static void ppp_format_packet(const u_char *p, int len, 00447 void (*printer) (void *, const char *, ...), void *arg) { 00448 int i, n; 00449 u_short proto; 00450 const struct protent *protp; 00451 00452 if (len >= 2) { 00453 GETSHORT(proto, p); 00454 len -= 2; 00455 for (i = 0; (protp = protocols[i]) != NULL; ++i) 00456 if (proto == protp->protocol) 00457 break; 00458 if (protp != NULL) { 00459 printer(arg, "[%s", protp->name); 00460 n = (*protp->printpkt)(p, len, printer, arg); 00461 printer(arg, "]"); 00462 p += n; 00463 len -= n; 00464 } else { 00465 for (i = 0; (protp = protocols[i]) != NULL; ++i) 00466 if (proto == (protp->protocol & ~0x8000)) 00467 break; 00468 if (protp != 0 && protp->data_name != 0) { 00469 printer(arg, "[%s data]", protp->data_name); 00470 if (len > 8) 00471 printer(arg, "%.8B ...", p); 00472 else 00473 printer(arg, "%.*B", len, p); 00474 len = 0; 00475 } else 00476 printer(arg, "[proto=0x%x]", proto); 00477 } 00478 } 00479 00480 if (len > 32) 00481 printer(arg, "%.32B ...", p); 00482 else 00483 printer(arg, "%.*B", len, p); 00484 } 00485 #endif /* PRINTPKT_SUPPORT */ 00486 00487 #if 0 /* UNUSED */ 00488 /* 00489 * init_pr_log, end_pr_log - initialize and finish use of pr_log. 00490 */ 00491 00492 static char line[256]; /* line to be logged accumulated here */ 00493 static char *linep; /* current pointer within line */ 00494 static int llevel; /* level for logging */ 00495 00496 void 00497 init_pr_log(prefix, level) 00498 const char *prefix; 00499 int level; 00500 { 00501 linep = line; 00502 if (prefix != NULL) { 00503 ppp_strlcpy(line, prefix, sizeof(line)); 00504 linep = line + strlen(line); 00505 } 00506 llevel = level; 00507 } 00508 00509 void 00510 end_pr_log() 00511 { 00512 if (linep != line) { 00513 *linep = 0; 00514 ppp_log_write(llevel, line); 00515 } 00516 } 00517 00518 /* 00519 * pr_log - printer routine for outputting to log 00520 */ 00521 void 00522 pr_log (void *arg, const char *fmt, ...) 00523 { 00524 int l, n; 00525 va_list pvar; 00526 char *p, *eol; 00527 char buf[256]; 00528 00529 va_start(pvar, fmt); 00530 n = ppp_vslprintf(buf, sizeof(buf), fmt, pvar); 00531 va_end(pvar); 00532 00533 p = buf; 00534 eol = strchr(buf, '\n'); 00535 if (linep != line) { 00536 l = (eol == NULL)? n: eol - buf; 00537 if (linep + l < line + sizeof(line)) { 00538 if (l > 0) { 00539 memcpy(linep, buf, l); 00540 linep += l; 00541 } 00542 if (eol == NULL) 00543 return; 00544 p = eol + 1; 00545 eol = strchr(p, '\n'); 00546 } 00547 *linep = 0; 00548 ppp_log_write(llevel, line); 00549 linep = line; 00550 } 00551 00552 while (eol != NULL) { 00553 *eol = 0; 00554 ppp_log_write(llevel, p); 00555 p = eol + 1; 00556 eol = strchr(p, '\n'); 00557 } 00558 00559 /* assumes sizeof(buf) <= sizeof(line) */ 00560 l = buf + n - p; 00561 if (l > 0) { 00562 memcpy(line, p, n); 00563 linep = line + l; 00564 } 00565 } 00566 #endif /* UNUSED */ 00567 00568 /* 00569 * ppp_print_string - print a readable representation of a string using 00570 * printer. 00571 */ 00572 void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg) { 00573 int c; 00574 00575 printer(arg, "\""); 00576 for (; len > 0; --len) { 00577 c = *p++; 00578 if (' ' <= c && c <= '~') { 00579 if (c == '\\' || c == '"') 00580 printer(arg, "\\"); 00581 printer(arg, "%c", c); 00582 } else { 00583 switch (c) { 00584 case '\n': 00585 printer(arg, "\\n"); 00586 break; 00587 case '\r': 00588 printer(arg, "\\r"); 00589 break; 00590 case '\t': 00591 printer(arg, "\\t"); 00592 break; 00593 default: 00594 printer(arg, "\\%.3o", (u8_t)c); 00595 /* no break */ 00596 } 00597 } 00598 } 00599 printer(arg, "\""); 00600 } 00601 00602 /* 00603 * ppp_logit - does the hard work for fatal et al. 00604 */ 00605 static void ppp_logit(int level, const char *fmt, va_list args) { 00606 char buf[1024]; 00607 00608 ppp_vslprintf(buf, sizeof(buf), fmt, args); 00609 ppp_log_write(level, buf); 00610 } 00611 00612 static void ppp_log_write(int level, char *buf) { 00613 LWIP_UNUSED_ARG(level); /* necessary if PPPDEBUG is defined to an empty function */ 00614 LWIP_UNUSED_ARG(buf); 00615 PPPDEBUG(level, ("%s\n", buf) ); 00616 #if 0 00617 if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { 00618 int n = strlen(buf); 00619 00620 if (n > 0 && buf[n-1] == '\n') 00621 --n; 00622 if (write(log_to_fd, buf, n) != n 00623 || write(log_to_fd, "\n", 1) != 1) 00624 log_to_fd = -1; 00625 } 00626 #endif 00627 } 00628 00629 /* 00630 * ppp_fatal - log an error message and die horribly. 00631 */ 00632 void ppp_fatal(const char *fmt, ...) { 00633 va_list pvar; 00634 00635 va_start(pvar, fmt); 00636 ppp_logit(LOG_ERR, fmt, pvar); 00637 va_end(pvar); 00638 00639 LWIP_ASSERT("ppp_fatal", 0); /* as promised */ 00640 } 00641 00642 /* 00643 * ppp_error - log an error message. 00644 */ 00645 void ppp_error(const char *fmt, ...) { 00646 va_list pvar; 00647 00648 va_start(pvar, fmt); 00649 ppp_logit(LOG_ERR, fmt, pvar); 00650 va_end(pvar); 00651 #if 0 /* UNUSED */ 00652 ++error_count; 00653 #endif /* UNUSED */ 00654 } 00655 00656 /* 00657 * ppp_warn - log a warning message. 00658 */ 00659 void ppp_warn(const char *fmt, ...) { 00660 va_list pvar; 00661 00662 va_start(pvar, fmt); 00663 ppp_logit(LOG_WARNING, fmt, pvar); 00664 va_end(pvar); 00665 } 00666 00667 /* 00668 * ppp_notice - log a notice-level message. 00669 */ 00670 void ppp_notice(const char *fmt, ...) { 00671 va_list pvar; 00672 00673 va_start(pvar, fmt); 00674 ppp_logit(LOG_NOTICE, fmt, pvar); 00675 va_end(pvar); 00676 } 00677 00678 /* 00679 * ppp_info - log an informational message. 00680 */ 00681 void ppp_info(const char *fmt, ...) { 00682 va_list pvar; 00683 00684 va_start(pvar, fmt); 00685 ppp_logit(LOG_INFO, fmt, pvar); 00686 va_end(pvar); 00687 } 00688 00689 /* 00690 * ppp_dbglog - log a debug message. 00691 */ 00692 void ppp_dbglog(const char *fmt, ...) { 00693 va_list pvar; 00694 00695 va_start(pvar, fmt); 00696 ppp_logit(LOG_DEBUG, fmt, pvar); 00697 va_end(pvar); 00698 } 00699 00700 #if PRINTPKT_SUPPORT 00701 /* 00702 * ppp_dump_packet - print out a packet in readable form if it is interesting. 00703 * Assumes len >= PPP_HDRLEN. 00704 */ 00705 void ppp_dump_packet(const char *tag, unsigned char *p, int len) { 00706 int proto; 00707 00708 /* 00709 * don't print IPv4 and IPv6 packets. 00710 */ 00711 proto = (p[0] << 8) + p[1]; 00712 if (proto == PPP_IP) 00713 return; 00714 #if PPP_IPV6_SUPPORT 00715 if (proto == PPP_IPV6) 00716 return; 00717 #endif 00718 00719 /* 00720 * don't print LCP echo request/reply packets if the link is up. 00721 */ 00722 if (proto == PPP_LCP && len >= 2 + HEADERLEN) { 00723 unsigned char *lcp = p + 2; 00724 int l = (lcp[2] << 8) + lcp[3]; 00725 00726 if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP) 00727 && l >= HEADERLEN && l <= len - 2) 00728 return; 00729 } 00730 00731 ppp_dbglog("%s %P", tag, p, len); 00732 } 00733 #endif /* PRINTPKT_SUPPORT */ 00734 00735 #if 0 /* Unused */ 00736 00737 /* 00738 * complete_read - read a full `count' bytes from fd, 00739 * unless end-of-file or an error other than EINTR is encountered. 00740 */ 00741 ssize_t 00742 complete_read(int fd, void *buf, size_t count) 00743 { 00744 size_t done; 00745 ssize_t nb; 00746 char *ptr = buf; 00747 00748 for (done = 0; done < count; ) { 00749 nb = read(fd, ptr, count - done); 00750 if (nb < 0) { 00751 if (errno == EINTR) 00752 continue; 00753 return -1; 00754 } 00755 if (nb == 0) 00756 break; 00757 done += nb; 00758 ptr += nb; 00759 } 00760 return done; 00761 } 00762 00763 /* Procedures for locking the serial device using a lock file. */ 00764 #ifndef LOCK_DIR 00765 #ifdef __linux__ 00766 #define LOCK_DIR "/var/lock" 00767 #else 00768 #ifdef SVR4 00769 #define LOCK_DIR "/var/spool/locks" 00770 #else 00771 #define LOCK_DIR "/var/spool/lock" 00772 #endif 00773 #endif 00774 #endif /* LOCK_DIR */ 00775 00776 static char lock_file[MAXPATHLEN]; 00777 00778 /* 00779 * lock - create a lock file for the named device 00780 */ 00781 int 00782 lock(dev) 00783 char *dev; 00784 { 00785 #ifdef LOCKLIB 00786 int result; 00787 00788 result = mklock (dev, (void *) 0); 00789 if (result == 0) { 00790 ppp_strlcpy(lock_file, dev, sizeof(lock_file)); 00791 return 0; 00792 } 00793 00794 if (result > 0) 00795 ppp_notice("Device %s is locked by pid %d", dev, result); 00796 else 00797 ppp_error("Can't create lock file %s", lock_file); 00798 return -1; 00799 00800 #else /* LOCKLIB */ 00801 00802 char lock_buffer[12]; 00803 int fd, pid, n; 00804 00805 #ifdef SVR4 00806 struct stat sbuf; 00807 00808 if (stat(dev, &sbuf) < 0) { 00809 ppp_error("Can't get device number for %s: %m", dev); 00810 return -1; 00811 } 00812 if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { 00813 ppp_error("Can't lock %s: not a character device", dev); 00814 return -1; 00815 } 00816 ppp_slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", 00817 LOCK_DIR, major(sbuf.st_dev), 00818 major(sbuf.st_rdev), minor(sbuf.st_rdev)); 00819 #else 00820 char *p; 00821 char lockdev[MAXPATHLEN]; 00822 00823 if ((p = strstr(dev, "dev/")) != NULL) { 00824 dev = p + 4; 00825 strncpy(lockdev, dev, MAXPATHLEN-1); 00826 lockdev[MAXPATHLEN-1] = 0; 00827 while ((p = strrchr(lockdev, '/')) != NULL) { 00828 *p = '_'; 00829 } 00830 dev = lockdev; 00831 } else 00832 if ((p = strrchr(dev, '/')) != NULL) 00833 dev = p + 1; 00834 00835 ppp_slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); 00836 #endif 00837 00838 while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { 00839 if (errno != EEXIST) { 00840 ppp_error("Can't create lock file %s: %m", lock_file); 00841 break; 00842 } 00843 00844 /* Read the lock file to find out who has the device locked. */ 00845 fd = open(lock_file, O_RDONLY, 0); 00846 if (fd < 0) { 00847 if (errno == ENOENT) /* This is just a timing problem. */ 00848 continue; 00849 ppp_error("Can't open existing lock file %s: %m", lock_file); 00850 break; 00851 } 00852 #ifndef LOCK_BINARY 00853 n = read(fd, lock_buffer, 11); 00854 #else 00855 n = read(fd, &pid, sizeof(pid)); 00856 #endif /* LOCK_BINARY */ 00857 close(fd); 00858 fd = -1; 00859 if (n <= 0) { 00860 ppp_error("Can't read pid from lock file %s", lock_file); 00861 break; 00862 } 00863 00864 /* See if the process still exists. */ 00865 #ifndef LOCK_BINARY 00866 lock_buffer[n] = 0; 00867 pid = atoi(lock_buffer); 00868 #endif /* LOCK_BINARY */ 00869 if (pid == getpid()) 00870 return 1; /* somebody else locked it for us */ 00871 if (pid == 0 00872 || (kill(pid, 0) == -1 && errno == ESRCH)) { 00873 if (unlink (lock_file) == 0) { 00874 ppp_notice("Removed stale lock on %s (pid %d)", dev, pid); 00875 continue; 00876 } 00877 ppp_warn("Couldn't remove stale lock on %s", dev); 00878 } else 00879 ppp_notice("Device %s is locked by pid %d", dev, pid); 00880 break; 00881 } 00882 00883 if (fd < 0) { 00884 lock_file[0] = 0; 00885 return -1; 00886 } 00887 00888 pid = getpid(); 00889 #ifndef LOCK_BINARY 00890 ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); 00891 write (fd, lock_buffer, 11); 00892 #else 00893 write(fd, &pid, sizeof (pid)); 00894 #endif 00895 close(fd); 00896 return 0; 00897 00898 #endif 00899 } 00900 00901 /* 00902 * relock - called to update our lockfile when we are about to detach, 00903 * thus changing our pid (we fork, the child carries on, and the parent dies). 00904 * Note that this is called by the parent, with pid equal to the pid 00905 * of the child. This avoids a potential race which would exist if 00906 * we had the child rewrite the lockfile (the parent might die first, 00907 * and another process could think the lock was stale if it checked 00908 * between when the parent died and the child rewrote the lockfile). 00909 */ 00910 int 00911 relock(pid) 00912 int pid; 00913 { 00914 #ifdef LOCKLIB 00915 /* XXX is there a way to do this? */ 00916 return -1; 00917 #else /* LOCKLIB */ 00918 00919 int fd; 00920 char lock_buffer[12]; 00921 00922 if (lock_file[0] == 0) 00923 return -1; 00924 fd = open(lock_file, O_WRONLY, 0); 00925 if (fd < 0) { 00926 ppp_error("Couldn't reopen lock file %s: %m", lock_file); 00927 lock_file[0] = 0; 00928 return -1; 00929 } 00930 00931 #ifndef LOCK_BINARY 00932 ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); 00933 write (fd, lock_buffer, 11); 00934 #else 00935 write(fd, &pid, sizeof(pid)); 00936 #endif /* LOCK_BINARY */ 00937 close(fd); 00938 return 0; 00939 00940 #endif /* LOCKLIB */ 00941 } 00942 00943 /* 00944 * unlock - remove our lockfile 00945 */ 00946 void 00947 unlock() 00948 { 00949 if (lock_file[0]) { 00950 #ifdef LOCKLIB 00951 (void) rmlock(lock_file, (void *) 0); 00952 #else 00953 unlink(lock_file); 00954 #endif 00955 lock_file[0] = 0; 00956 } 00957 } 00958 00959 #endif /* Unused */ 00960 00961 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 14:21:12 by
1.7.2