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: mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more
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 #if 0 /* unused (and wrong on LLP64 systems) */ 00251 case 'p': 00252 val = (unsigned long) va_arg(args, void *); 00253 base = 16; 00254 neg = 2; 00255 break; 00256 #endif /* unused (and wrong on LLP64 systems) */ 00257 case 's': 00258 str = va_arg(args, char *); 00259 break; 00260 case 'c': 00261 num[0] = va_arg(args, int); 00262 num[1] = 0; 00263 str = num; 00264 break; 00265 #if 0 /* do we always have strerror() in embedded ? */ 00266 case 'm': 00267 str = strerror(errno); 00268 break; 00269 #endif /* do we always have strerror() in embedded ? */ 00270 case 'I': 00271 ip = va_arg(args, u32_t); 00272 ip = lwip_ntohl(ip); 00273 ppp_slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff, 00274 (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); 00275 str = num; 00276 break; 00277 #if 0 /* need port */ 00278 case 't': 00279 time(&t); 00280 str = ctime(&t); 00281 str += 4; /* chop off the day name */ 00282 str[15] = 0; /* chop off year and newline */ 00283 break; 00284 #endif /* need port */ 00285 case 'v': /* "visible" string */ 00286 case 'q': /* quoted string */ 00287 quoted = c == 'q'; 00288 p = va_arg(args, unsigned char *); 00289 if (p == NULL) 00290 p = (const unsigned char *)"<NULL>"; 00291 if (fillch == '0' && prec >= 0) { 00292 n = prec; 00293 } else { 00294 n = strlen((const char *)p); 00295 if (prec >= 0 && n > prec) 00296 n = prec; 00297 } 00298 while (n > 0 && buflen > 0) { 00299 c = *p++; 00300 --n; 00301 if (!quoted && c >= 0x80) { 00302 OUTCHAR('M'); 00303 OUTCHAR('-'); 00304 c -= 0x80; 00305 } 00306 if (quoted && (c == '"' || c == '\\')) 00307 OUTCHAR('\\'); 00308 if (c < 0x20 || (0x7f <= c && c < 0xa0)) { 00309 if (quoted) { 00310 OUTCHAR('\\'); 00311 switch (c) { 00312 case '\t': OUTCHAR('t'); break; 00313 case '\n': OUTCHAR('n'); break; 00314 case '\b': OUTCHAR('b'); break; 00315 case '\f': OUTCHAR('f'); break; 00316 default: 00317 OUTCHAR('x'); 00318 OUTCHAR(hexchars[c >> 4]); 00319 OUTCHAR(hexchars[c & 0xf]); 00320 } 00321 } else { 00322 if (c == '\t') 00323 OUTCHAR(c); 00324 else { 00325 OUTCHAR('^'); 00326 OUTCHAR(c ^ 0x40); 00327 } 00328 } 00329 } else 00330 OUTCHAR(c); 00331 } 00332 continue; 00333 #if PRINTPKT_SUPPORT 00334 case 'P': /* print PPP packet */ 00335 bufinfo.ptr = buf; 00336 bufinfo.len = buflen + 1; 00337 p = va_arg(args, unsigned char *); 00338 n = va_arg(args, int); 00339 ppp_format_packet(p, n, ppp_vslp_printer, &bufinfo); 00340 buf = bufinfo.ptr; 00341 buflen = bufinfo.len - 1; 00342 continue; 00343 #endif /* PRINTPKT_SUPPORT */ 00344 case 'B': 00345 p = va_arg(args, unsigned char *); 00346 for (n = prec; n > 0; --n) { 00347 c = *p++; 00348 if (fillch == ' ') 00349 OUTCHAR(' '); 00350 OUTCHAR(hexchars[(c >> 4) & 0xf]); 00351 OUTCHAR(hexchars[c & 0xf]); 00352 } 00353 continue; 00354 default: 00355 *buf++ = '%'; 00356 if (c != '%') 00357 --fmt; /* so %z outputs %z etc. */ 00358 --buflen; 00359 continue; 00360 } 00361 if (base != 0) { 00362 str = num + sizeof(num); 00363 *--str = 0; 00364 while (str > num + neg) { 00365 *--str = hexchars[val % base]; 00366 val = val / base; 00367 if (--prec <= 0 && val == 0) 00368 break; 00369 } 00370 switch (neg) { 00371 case 1: 00372 *--str = '-'; 00373 break; 00374 case 2: 00375 *--str = 'x'; 00376 *--str = '0'; 00377 break; 00378 default: 00379 break; 00380 } 00381 len = num + sizeof(num) - 1 - str; 00382 } else { 00383 len = strlen(str); 00384 if (prec >= 0 && len > prec) 00385 len = prec; 00386 } 00387 if (width > 0) { 00388 if (width > buflen) 00389 width = buflen; 00390 if ((n = width - len) > 0) { 00391 buflen -= n; 00392 for (; n > 0; --n) 00393 *buf++ = fillch; 00394 } 00395 } 00396 if (len > buflen) 00397 len = buflen; 00398 memcpy(buf, str, len); 00399 buf += len; 00400 buflen -= len; 00401 } 00402 *buf = 0; 00403 return buf - buf0; 00404 } 00405 00406 #if PRINTPKT_SUPPORT 00407 /* 00408 * vslp_printer - used in processing a %P format 00409 */ 00410 static void ppp_vslp_printer(void *arg, const char *fmt, ...) { 00411 int n; 00412 va_list pvar; 00413 struct buffer_info *bi; 00414 00415 va_start(pvar, fmt); 00416 bi = (struct buffer_info *) arg; 00417 n = ppp_vslprintf(bi->ptr, bi->len, fmt, pvar); 00418 va_end(pvar); 00419 00420 bi->ptr += n; 00421 bi->len -= n; 00422 } 00423 #endif /* PRINTPKT_SUPPORT */ 00424 00425 #if 0 /* UNUSED */ 00426 /* 00427 * log_packet - format a packet and log it. 00428 */ 00429 00430 void 00431 log_packet(p, len, prefix, level) 00432 u_char *p; 00433 int len; 00434 char *prefix; 00435 int level; 00436 { 00437 init_pr_log(prefix, level); 00438 ppp_format_packet(p, len, pr_log, &level); 00439 end_pr_log(); 00440 } 00441 #endif /* UNUSED */ 00442 00443 #if PRINTPKT_SUPPORT 00444 /* 00445 * ppp_format_packet - make a readable representation of a packet, 00446 * calling `printer(arg, format, ...)' to output it. 00447 */ 00448 static void ppp_format_packet(const u_char *p, int len, 00449 void (*printer) (void *, const char *, ...), void *arg) { 00450 int i, n; 00451 u_short proto; 00452 const struct protent *protp; 00453 00454 if (len >= 2) { 00455 GETSHORT(proto, p); 00456 len -= 2; 00457 for (i = 0; (protp = protocols[i]) != NULL; ++i) 00458 if (proto == protp->protocol) 00459 break; 00460 if (protp != NULL) { 00461 printer(arg, "[%s", protp->name); 00462 n = (*protp->printpkt)(p, len, printer, arg); 00463 printer(arg, "]"); 00464 p += n; 00465 len -= n; 00466 } else { 00467 for (i = 0; (protp = protocols[i]) != NULL; ++i) 00468 if (proto == (protp->protocol & ~0x8000)) 00469 break; 00470 if (protp != 0 && protp->data_name != 0) { 00471 printer(arg, "[%s data]", protp->data_name); 00472 if (len > 8) 00473 printer(arg, "%.8B ...", p); 00474 else 00475 printer(arg, "%.*B", len, p); 00476 len = 0; 00477 } else 00478 printer(arg, "[proto=0x%x]", proto); 00479 } 00480 } 00481 00482 if (len > 32) 00483 printer(arg, "%.32B ...", p); 00484 else 00485 printer(arg, "%.*B", len, p); 00486 } 00487 #endif /* PRINTPKT_SUPPORT */ 00488 00489 #if 0 /* UNUSED */ 00490 /* 00491 * init_pr_log, end_pr_log - initialize and finish use of pr_log. 00492 */ 00493 00494 static char line[256]; /* line to be logged accumulated here */ 00495 static char *linep; /* current pointer within line */ 00496 static int llevel; /* level for logging */ 00497 00498 void 00499 init_pr_log(prefix, level) 00500 const char *prefix; 00501 int level; 00502 { 00503 linep = line; 00504 if (prefix != NULL) { 00505 ppp_strlcpy(line, prefix, sizeof(line)); 00506 linep = line + strlen(line); 00507 } 00508 llevel = level; 00509 } 00510 00511 void 00512 end_pr_log() 00513 { 00514 if (linep != line) { 00515 *linep = 0; 00516 ppp_log_write(llevel, line); 00517 } 00518 } 00519 00520 /* 00521 * pr_log - printer routine for outputting to log 00522 */ 00523 void 00524 pr_log (void *arg, const char *fmt, ...) 00525 { 00526 int l, n; 00527 va_list pvar; 00528 char *p, *eol; 00529 char buf[256]; 00530 00531 va_start(pvar, fmt); 00532 n = ppp_vslprintf(buf, sizeof(buf), fmt, pvar); 00533 va_end(pvar); 00534 00535 p = buf; 00536 eol = strchr(buf, '\n'); 00537 if (linep != line) { 00538 l = (eol == NULL)? n: eol - buf; 00539 if (linep + l < line + sizeof(line)) { 00540 if (l > 0) { 00541 memcpy(linep, buf, l); 00542 linep += l; 00543 } 00544 if (eol == NULL) 00545 return; 00546 p = eol + 1; 00547 eol = strchr(p, '\n'); 00548 } 00549 *linep = 0; 00550 ppp_log_write(llevel, line); 00551 linep = line; 00552 } 00553 00554 while (eol != NULL) { 00555 *eol = 0; 00556 ppp_log_write(llevel, p); 00557 p = eol + 1; 00558 eol = strchr(p, '\n'); 00559 } 00560 00561 /* assumes sizeof(buf) <= sizeof(line) */ 00562 l = buf + n - p; 00563 if (l > 0) { 00564 memcpy(line, p, n); 00565 linep = line + l; 00566 } 00567 } 00568 #endif /* UNUSED */ 00569 00570 /* 00571 * ppp_print_string - print a readable representation of a string using 00572 * printer. 00573 */ 00574 void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg) { 00575 int c; 00576 00577 printer(arg, "\""); 00578 for (; len > 0; --len) { 00579 c = *p++; 00580 if (' ' <= c && c <= '~') { 00581 if (c == '\\' || c == '"') 00582 printer(arg, "\\"); 00583 printer(arg, "%c", c); 00584 } else { 00585 switch (c) { 00586 case '\n': 00587 printer(arg, "\\n"); 00588 break; 00589 case '\r': 00590 printer(arg, "\\r"); 00591 break; 00592 case '\t': 00593 printer(arg, "\\t"); 00594 break; 00595 default: 00596 printer(arg, "\\%.3o", (u8_t)c); 00597 /* no break */ 00598 } 00599 } 00600 } 00601 printer(arg, "\""); 00602 } 00603 00604 /* 00605 * ppp_logit - does the hard work for fatal et al. 00606 */ 00607 static void ppp_logit(int level, const char *fmt, va_list args) { 00608 char buf[1024]; 00609 00610 ppp_vslprintf(buf, sizeof(buf), fmt, args); 00611 ppp_log_write(level, buf); 00612 } 00613 00614 static void ppp_log_write(int level, char *buf) { 00615 LWIP_UNUSED_ARG(level); /* necessary if PPPDEBUG is defined to an empty function */ 00616 LWIP_UNUSED_ARG(buf); 00617 PPPDEBUG(level, ("%s\n", buf) ); 00618 #if 0 00619 if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { 00620 int n = strlen(buf); 00621 00622 if (n > 0 && buf[n-1] == '\n') 00623 --n; 00624 if (write(log_to_fd, buf, n) != n 00625 || write(log_to_fd, "\n", 1) != 1) 00626 log_to_fd = -1; 00627 } 00628 #endif 00629 } 00630 00631 /* 00632 * ppp_fatal - log an error message and die horribly. 00633 */ 00634 void ppp_fatal(const char *fmt, ...) { 00635 va_list pvar; 00636 00637 va_start(pvar, fmt); 00638 ppp_logit(LOG_ERR, fmt, pvar); 00639 va_end(pvar); 00640 00641 LWIP_ASSERT("ppp_fatal", 0); /* as promised */ 00642 } 00643 00644 /* 00645 * ppp_error - log an error message. 00646 */ 00647 void ppp_error(const char *fmt, ...) { 00648 va_list pvar; 00649 00650 va_start(pvar, fmt); 00651 ppp_logit(LOG_ERR, fmt, pvar); 00652 va_end(pvar); 00653 #if 0 /* UNUSED */ 00654 ++error_count; 00655 #endif /* UNUSED */ 00656 } 00657 00658 /* 00659 * ppp_warn - log a warning message. 00660 */ 00661 void ppp_warn(const char *fmt, ...) { 00662 va_list pvar; 00663 00664 va_start(pvar, fmt); 00665 ppp_logit(LOG_WARNING, fmt, pvar); 00666 va_end(pvar); 00667 } 00668 00669 /* 00670 * ppp_notice - log a notice-level message. 00671 */ 00672 void ppp_notice(const char *fmt, ...) { 00673 va_list pvar; 00674 00675 va_start(pvar, fmt); 00676 ppp_logit(LOG_NOTICE, fmt, pvar); 00677 va_end(pvar); 00678 } 00679 00680 /* 00681 * ppp_info - log an informational message. 00682 */ 00683 void ppp_info(const char *fmt, ...) { 00684 va_list pvar; 00685 00686 va_start(pvar, fmt); 00687 ppp_logit(LOG_INFO, fmt, pvar); 00688 va_end(pvar); 00689 } 00690 00691 /* 00692 * ppp_dbglog - log a debug message. 00693 */ 00694 void ppp_dbglog(const char *fmt, ...) { 00695 va_list pvar; 00696 00697 va_start(pvar, fmt); 00698 ppp_logit(LOG_DEBUG, fmt, pvar); 00699 va_end(pvar); 00700 } 00701 00702 #if PRINTPKT_SUPPORT 00703 /* 00704 * ppp_dump_packet - print out a packet in readable form if it is interesting. 00705 * Assumes len >= PPP_HDRLEN. 00706 */ 00707 void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len) { 00708 int proto; 00709 00710 /* 00711 * don't print data packets, i.e. IPv4, IPv6, VJ, and compressed packets. 00712 */ 00713 proto = (p[0] << 8) + p[1]; 00714 if (proto < 0xC000 && (proto & ~0x8000) == proto) 00715 return; 00716 00717 /* 00718 * don't print valid LCP echo request/reply packets if the link is up. 00719 */ 00720 if (proto == PPP_LCP && pcb->phase == PPP_PHASE_RUNNING && len >= 2 + HEADERLEN) { 00721 unsigned char *lcp = p + 2; 00722 int l = (lcp[2] << 8) + lcp[3]; 00723 00724 if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP) 00725 && l >= HEADERLEN && l <= len - 2) 00726 return; 00727 } 00728 00729 ppp_dbglog("%s %P", tag, p, len); 00730 } 00731 #endif /* PRINTPKT_SUPPORT */ 00732 00733 #if 0 /* Unused */ 00734 00735 /* 00736 * complete_read - read a full `count' bytes from fd, 00737 * unless end-of-file or an error other than EINTR is encountered. 00738 */ 00739 ssize_t 00740 complete_read(int fd, void *buf, size_t count) 00741 { 00742 size_t done; 00743 ssize_t nb; 00744 char *ptr = buf; 00745 00746 for (done = 0; done < count; ) { 00747 nb = read(fd, ptr, count - done); 00748 if (nb < 0) { 00749 if (errno == EINTR) 00750 continue; 00751 return -1; 00752 } 00753 if (nb == 0) 00754 break; 00755 done += nb; 00756 ptr += nb; 00757 } 00758 return done; 00759 } 00760 00761 /* Procedures for locking the serial device using a lock file. */ 00762 #ifndef LOCK_DIR 00763 #ifdef __linux__ 00764 #define LOCK_DIR "/var/lock" 00765 #else 00766 #ifdef SVR4 00767 #define LOCK_DIR "/var/spool/locks" 00768 #else 00769 #define LOCK_DIR "/var/spool/lock" 00770 #endif 00771 #endif 00772 #endif /* LOCK_DIR */ 00773 00774 static char lock_file[MAXPATHLEN]; 00775 00776 /* 00777 * lock - create a lock file for the named device 00778 */ 00779 int 00780 lock(dev) 00781 char *dev; 00782 { 00783 #ifdef LOCKLIB 00784 int result; 00785 00786 result = mklock (dev, (void *) 0); 00787 if (result == 0) { 00788 ppp_strlcpy(lock_file, dev, sizeof(lock_file)); 00789 return 0; 00790 } 00791 00792 if (result > 0) 00793 ppp_notice("Device %s is locked by pid %d", dev, result); 00794 else 00795 ppp_error("Can't create lock file %s", lock_file); 00796 return -1; 00797 00798 #else /* LOCKLIB */ 00799 00800 char lock_buffer[12]; 00801 int fd, pid, n; 00802 00803 #ifdef SVR4 00804 struct stat sbuf; 00805 00806 if (stat(dev, &sbuf) < 0) { 00807 ppp_error("Can't get device number for %s: %m", dev); 00808 return -1; 00809 } 00810 if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { 00811 ppp_error("Can't lock %s: not a character device", dev); 00812 return -1; 00813 } 00814 ppp_slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", 00815 LOCK_DIR, major(sbuf.st_dev), 00816 major(sbuf.st_rdev), minor(sbuf.st_rdev)); 00817 #else 00818 char *p; 00819 char lockdev[MAXPATHLEN]; 00820 00821 if ((p = strstr(dev, "dev/")) != NULL) { 00822 dev = p + 4; 00823 strncpy(lockdev, dev, MAXPATHLEN-1); 00824 lockdev[MAXPATHLEN-1] = 0; 00825 while ((p = strrchr(lockdev, '/')) != NULL) { 00826 *p = '_'; 00827 } 00828 dev = lockdev; 00829 } else 00830 if ((p = strrchr(dev, '/')) != NULL) 00831 dev = p + 1; 00832 00833 ppp_slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); 00834 #endif 00835 00836 while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { 00837 if (errno != EEXIST) { 00838 ppp_error("Can't create lock file %s: %m", lock_file); 00839 break; 00840 } 00841 00842 /* Read the lock file to find out who has the device locked. */ 00843 fd = open(lock_file, O_RDONLY, 0); 00844 if (fd < 0) { 00845 if (errno == ENOENT) /* This is just a timing problem. */ 00846 continue; 00847 ppp_error("Can't open existing lock file %s: %m", lock_file); 00848 break; 00849 } 00850 #ifndef LOCK_BINARY 00851 n = read(fd, lock_buffer, 11); 00852 #else 00853 n = read(fd, &pid, sizeof(pid)); 00854 #endif /* LOCK_BINARY */ 00855 close(fd); 00856 fd = -1; 00857 if (n <= 0) { 00858 ppp_error("Can't read pid from lock file %s", lock_file); 00859 break; 00860 } 00861 00862 /* See if the process still exists. */ 00863 #ifndef LOCK_BINARY 00864 lock_buffer[n] = 0; 00865 pid = atoi(lock_buffer); 00866 #endif /* LOCK_BINARY */ 00867 if (pid == getpid()) 00868 return 1; /* somebody else locked it for us */ 00869 if (pid == 0 00870 || (kill(pid, 0) == -1 && errno == ESRCH)) { 00871 if (unlink (lock_file) == 0) { 00872 ppp_notice("Removed stale lock on %s (pid %d)", dev, pid); 00873 continue; 00874 } 00875 ppp_warn("Couldn't remove stale lock on %s", dev); 00876 } else 00877 ppp_notice("Device %s is locked by pid %d", dev, pid); 00878 break; 00879 } 00880 00881 if (fd < 0) { 00882 lock_file[0] = 0; 00883 return -1; 00884 } 00885 00886 pid = getpid(); 00887 #ifndef LOCK_BINARY 00888 ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); 00889 write (fd, lock_buffer, 11); 00890 #else 00891 write(fd, &pid, sizeof (pid)); 00892 #endif 00893 close(fd); 00894 return 0; 00895 00896 #endif 00897 } 00898 00899 /* 00900 * relock - called to update our lockfile when we are about to detach, 00901 * thus changing our pid (we fork, the child carries on, and the parent dies). 00902 * Note that this is called by the parent, with pid equal to the pid 00903 * of the child. This avoids a potential race which would exist if 00904 * we had the child rewrite the lockfile (the parent might die first, 00905 * and another process could think the lock was stale if it checked 00906 * between when the parent died and the child rewrote the lockfile). 00907 */ 00908 int 00909 relock(pid) 00910 int pid; 00911 { 00912 #ifdef LOCKLIB 00913 /* XXX is there a way to do this? */ 00914 return -1; 00915 #else /* LOCKLIB */ 00916 00917 int fd; 00918 char lock_buffer[12]; 00919 00920 if (lock_file[0] == 0) 00921 return -1; 00922 fd = open(lock_file, O_WRONLY, 0); 00923 if (fd < 0) { 00924 ppp_error("Couldn't reopen lock file %s: %m", lock_file); 00925 lock_file[0] = 0; 00926 return -1; 00927 } 00928 00929 #ifndef LOCK_BINARY 00930 ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); 00931 write (fd, lock_buffer, 11); 00932 #else 00933 write(fd, &pid, sizeof(pid)); 00934 #endif /* LOCK_BINARY */ 00935 close(fd); 00936 return 0; 00937 00938 #endif /* LOCKLIB */ 00939 } 00940 00941 /* 00942 * unlock - remove our lockfile 00943 */ 00944 void 00945 unlock() 00946 { 00947 if (lock_file[0]) { 00948 #ifdef LOCKLIB 00949 (void) rmlock(lock_file, (void *) 0); 00950 #else 00951 unlink(lock_file); 00952 #endif 00953 lock_file[0] = 0; 00954 } 00955 } 00956 00957 #endif /* Unused */ 00958 00959 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 11:02:28 by
1.7.2