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.
Fork of mbed-os by
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 13:15:55 by
1.7.2
