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 OmniWheels 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 #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 00609 char buf[256]; 00610 00611 ppp_vslprintf(buf, sizeof(buf), fmt, args); 00612 ppp_log_write(level, buf); 00613 } 00614 00615 static void ppp_log_write(int level, char *buf) { 00616 LWIP_UNUSED_ARG(level); /* necessary if PPPDEBUG is defined to an empty function */ 00617 LWIP_UNUSED_ARG(buf); 00618 PPPDEBUG(level, ("%s\n", buf) ); 00619 #if 0 00620 if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { 00621 int n = strlen(buf); 00622 00623 if (n > 0 && buf[n-1] == '\n') 00624 --n; 00625 if (write(log_to_fd, buf, n) != n 00626 || write(log_to_fd, "\n", 1) != 1) 00627 log_to_fd = -1; 00628 } 00629 #endif 00630 } 00631 00632 /* 00633 * ppp_fatal - log an error message and die horribly. 00634 */ 00635 void ppp_fatal(const char *fmt, ...) { 00636 va_list pvar; 00637 00638 va_start(pvar, fmt); 00639 ppp_logit(LOG_ERR, fmt, pvar); 00640 va_end(pvar); 00641 00642 LWIP_ASSERT("ppp_fatal", 0); /* as promised */ 00643 } 00644 00645 /* 00646 * ppp_error - log an error message. 00647 */ 00648 void ppp_error(const char *fmt, ...) { 00649 va_list pvar; 00650 00651 va_start(pvar, fmt); 00652 ppp_logit(LOG_ERR, fmt, pvar); 00653 va_end(pvar); 00654 #if 0 /* UNUSED */ 00655 ++error_count; 00656 #endif /* UNUSED */ 00657 } 00658 00659 /* 00660 * ppp_warn - log a warning message. 00661 */ 00662 void ppp_warn(const char *fmt, ...) { 00663 va_list pvar; 00664 00665 va_start(pvar, fmt); 00666 ppp_logit(LOG_WARNING, fmt, pvar); 00667 va_end(pvar); 00668 } 00669 00670 /* 00671 * ppp_notice - log a notice-level message. 00672 */ 00673 void ppp_notice(const char *fmt, ...) { 00674 va_list pvar; 00675 00676 va_start(pvar, fmt); 00677 ppp_logit(LOG_NOTICE, fmt, pvar); 00678 va_end(pvar); 00679 } 00680 00681 /* 00682 * ppp_info - log an informational message. 00683 */ 00684 void ppp_info(const char *fmt, ...) { 00685 va_list pvar; 00686 00687 va_start(pvar, fmt); 00688 ppp_logit(LOG_INFO, fmt, pvar); 00689 va_end(pvar); 00690 } 00691 00692 /* 00693 * ppp_dbglog - log a debug message. 00694 */ 00695 void ppp_dbglog(const char *fmt, ...) { 00696 va_list pvar; 00697 00698 va_start(pvar, fmt); 00699 ppp_logit(LOG_DEBUG, fmt, pvar); 00700 va_end(pvar); 00701 } 00702 00703 #if PRINTPKT_SUPPORT 00704 /* 00705 * ppp_dump_packet - print out a packet in readable form if it is interesting. 00706 * Assumes len >= PPP_HDRLEN. 00707 */ 00708 void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len) { 00709 int proto; 00710 00711 /* 00712 * don't print data packets, i.e. IPv4, IPv6, VJ, and compressed packets. 00713 */ 00714 proto = (p[0] << 8) + p[1]; 00715 if (proto < 0xC000 && (proto & ~0x8000) == proto) 00716 return; 00717 00718 /* 00719 * don't print valid LCP echo request/reply packets if the link is up. 00720 */ 00721 if (proto == PPP_LCP && pcb->phase == PPP_PHASE_RUNNING && len >= 2 + HEADERLEN) { 00722 unsigned char *lcp = p + 2; 00723 int l = (lcp[2] << 8) + lcp[3]; 00724 00725 if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP) 00726 && l >= HEADERLEN && l <= len - 2) 00727 return; 00728 } 00729 00730 TRACE_TO_ASCII_HEX_DUMPF("PPP>", len, (char *) p); 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 Fri Jul 22 2022 04:53:53 by
 1.7.2
 1.7.2 
    