Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
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 Sun Jul 17 2022 08:25:25 by 1.7.2