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: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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 "ppp_opts.h" 00032 #if PPP_SUPPORT /* don't build if not configured for use in ppp_opts.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 "ppp_impl.h" 00062 00063 #include "fsm.h" 00064 #include "lcp.h" 00065 00066 #if defined(SUNOS4) 00067 extern char *strerror(); 00068 #endif 00069 00070 static void ppp_logit(int level, const char *fmt, va_list args); 00071 static void ppp_log_write(int level, char *buf); 00072 #if PRINTPKT_SUPPORT 00073 static void ppp_vslp_printer(void *arg, const char *fmt, ...); 00074 static void ppp_format_packet(const u_char *p, int len, 00075 void (*printer) (void *, const char *, ...), void *arg); 00076 00077 struct buffer_info { 00078 char *ptr; 00079 int len; 00080 }; 00081 #endif /* PRINTPKT_SUPPORT */ 00082 00083 /* 00084 * ppp_strlcpy - like strcpy/strncpy, doesn't overflow destination buffer, 00085 * always leaves destination null-terminated (for len > 0). 00086 */ 00087 size_t ppp_strlcpy(char *dest, const char *src, size_t len) { 00088 size_t ret = strlen(src); 00089 00090 if (len != 0) { 00091 if (ret < len) 00092 strcpy(dest, src); 00093 else { 00094 strncpy(dest, src, len - 1); 00095 dest[len-1] = 0; 00096 } 00097 } 00098 return ret; 00099 } 00100 00101 /* 00102 * ppp_strlcat - like strcat/strncat, doesn't overflow destination buffer, 00103 * always leaves destination null-terminated (for len > 0). 00104 */ 00105 size_t ppp_strlcat(char *dest, const char *src, size_t len) { 00106 size_t dlen = strlen(dest); 00107 00108 return dlen + ppp_strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0)); 00109 } 00110 00111 00112 /* 00113 * ppp_slprintf - format a message into a buffer. Like sprintf except we 00114 * also specify the length of the output buffer, and we handle 00115 * %m (error message), %v (visible string), 00116 * %q (quoted string), %t (current time) and %I (IP address) formats. 00117 * Doesn't do floating-point formats. 00118 * Returns the number of chars put into buf. 00119 */ 00120 int ppp_slprintf(char *buf, int buflen, const char *fmt, ...) { 00121 va_list args; 00122 int n; 00123 00124 va_start(args, fmt); 00125 n = ppp_vslprintf(buf, buflen, fmt, args); 00126 va_end(args); 00127 return n; 00128 } 00129 00130 /* 00131 * ppp_vslprintf - like ppp_slprintf, takes a va_list instead of a list of args. 00132 */ 00133 #define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) 00134 00135 int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args) { 00136 int c, i, n; 00137 int width, prec, fillch; 00138 int base, len, neg, quoted; 00139 unsigned long val = 0; 00140 const char *f; 00141 char *str, *buf0; 00142 const unsigned char *p; 00143 char num[32]; 00144 #if 0 /* need port */ 00145 time_t t; 00146 #endif /* need port */ 00147 u32_t ip; 00148 static char hexchars[] = "0123456789abcdef"; 00149 #if PRINTPKT_SUPPORT 00150 struct buffer_info bufinfo; 00151 #endif /* PRINTPKT_SUPPORT */ 00152 00153 buf0 = buf; 00154 --buflen; 00155 while (buflen > 0) { 00156 for (f = fmt; *f != '%' && *f != 0; ++f) 00157 ; 00158 if (f > fmt) { 00159 len = f - fmt; 00160 if (len > buflen) 00161 len = buflen; 00162 memcpy(buf, fmt, len); 00163 buf += len; 00164 buflen -= len; 00165 fmt = f; 00166 } 00167 if (*fmt == 0) 00168 break; 00169 c = *++fmt; 00170 width = 0; 00171 prec = -1; 00172 fillch = ' '; 00173 if (c == '0') { 00174 fillch = '0'; 00175 c = *++fmt; 00176 } 00177 if (c == '*') { 00178 width = va_arg(args, int); 00179 c = *++fmt; 00180 } else { 00181 while (ppp_isdigit(c)) { 00182 width = width * 10 + c - '0'; 00183 c = *++fmt; 00184 } 00185 } 00186 if (c == '.') { 00187 c = *++fmt; 00188 if (c == '*') { 00189 prec = va_arg(args, int); 00190 c = *++fmt; 00191 } else { 00192 prec = 0; 00193 while (ppp_isdigit(c)) { 00194 prec = prec * 10 + c - '0'; 00195 c = *++fmt; 00196 } 00197 } 00198 } 00199 str = 0; 00200 base = 0; 00201 neg = 0; 00202 ++fmt; 00203 switch (c) { 00204 case 'l': 00205 c = *fmt++; 00206 switch (c) { 00207 case 'd': 00208 val = va_arg(args, long); 00209 if ((long)val < 0) { 00210 neg = 1; 00211 val = (unsigned long)-(long)val; 00212 } 00213 base = 10; 00214 break; 00215 case 'u': 00216 val = va_arg(args, unsigned long); 00217 base = 10; 00218 break; 00219 default: 00220 OUTCHAR('%'); 00221 OUTCHAR('l'); 00222 --fmt; /* so %lz outputs %lz etc. */ 00223 continue; 00224 } 00225 break; 00226 case 'd': 00227 i = va_arg(args, int); 00228 if (i < 0) { 00229 neg = 1; 00230 val = -i; 00231 } else 00232 val = i; 00233 base = 10; 00234 break; 00235 case 'u': 00236 val = va_arg(args, unsigned int); 00237 base = 10; 00238 break; 00239 case 'o': 00240 val = va_arg(args, unsigned int); 00241 base = 8; 00242 break; 00243 case 'x': 00244 case 'X': 00245 val = va_arg(args, unsigned int); 00246 base = 16; 00247 break; 00248 #if 0 /* unused (and wrong on LLP64 systems) */ 00249 case 'p': 00250 val = (unsigned long) va_arg(args, void *); 00251 base = 16; 00252 neg = 2; 00253 break; 00254 #endif /* unused (and wrong on LLP64 systems) */ 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 = ppp_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[256]; 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 PPP_UNUSED_ARG(level); /* necessary if PPPDEBUG is defined to an empty function */ 00614 PPP_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 PPP_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(ppp_pcb *pcb, const char *tag, unsigned char *p, int len) { 00706 int proto; 00707 00708 /* 00709 * don't print data packets, i.e. IPv4, IPv6, VJ, and compressed packets. 00710 */ 00711 proto = (p[0] << 8) + p[1]; 00712 if (proto < 0xC000 && (proto & ~0x8000) == proto) 00713 return; 00714 00715 /* 00716 * don't print valid LCP echo request/reply packets if the link is up. 00717 */ 00718 if (proto == PPP_LCP && pcb->phase == PPP_PHASE_RUNNING && len >= 2 + HEADERLEN) { 00719 unsigned char *lcp = p + 2; 00720 int l = (lcp[2] << 8) + lcp[3]; 00721 00722 if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP) 00723 && l >= HEADERLEN && l <= len - 2) 00724 return; 00725 } 00726 00727 TRACE_TO_ASCII_HEX_DUMPF("PPP>", len, (char *) p); 00728 ppp_dbglog("%s %P", tag, p, len); 00729 } 00730 #endif /* PRINTPKT_SUPPORT */ 00731 00732 #if 0 /* Unused */ 00733 00734 /* 00735 * complete_read - read a full `count' bytes from fd, 00736 * unless end-of-file or an error other than EINTR is encountered. 00737 */ 00738 ssize_t 00739 complete_read(int fd, void *buf, size_t count) 00740 { 00741 size_t done; 00742 ssize_t nb; 00743 char *ptr = buf; 00744 00745 for (done = 0; done < count; ) { 00746 nb = read(fd, ptr, count - done); 00747 if (nb < 0) { 00748 if (errno == EINTR) 00749 continue; 00750 return -1; 00751 } 00752 if (nb == 0) 00753 break; 00754 done += nb; 00755 ptr += nb; 00756 } 00757 return done; 00758 } 00759 00760 /* Procedures for locking the serial device using a lock file. */ 00761 #ifndef LOCK_DIR 00762 #ifdef __linux__ 00763 #define LOCK_DIR "/var/lock" 00764 #else 00765 #ifdef SVR4 00766 #define LOCK_DIR "/var/spool/locks" 00767 #else 00768 #define LOCK_DIR "/var/spool/lock" 00769 #endif 00770 #endif 00771 #endif /* LOCK_DIR */ 00772 00773 static char lock_file[MAXPATHLEN]; 00774 00775 /* 00776 * lock - create a lock file for the named device 00777 */ 00778 int 00779 lock(dev) 00780 char *dev; 00781 { 00782 #ifdef LOCKLIB 00783 int result; 00784 00785 result = mklock (dev, (void *) 0); 00786 if (result == 0) { 00787 ppp_strlcpy(lock_file, dev, sizeof(lock_file)); 00788 return 0; 00789 } 00790 00791 if (result > 0) 00792 ppp_notice("Device %s is locked by pid %d", dev, result); 00793 else 00794 ppp_error("Can't create lock file %s", lock_file); 00795 return -1; 00796 00797 #else /* LOCKLIB */ 00798 00799 char lock_buffer[12]; 00800 int fd, pid, n; 00801 00802 #ifdef SVR4 00803 struct stat sbuf; 00804 00805 if (stat(dev, &sbuf) < 0) { 00806 ppp_error("Can't get device number for %s: %m", dev); 00807 return -1; 00808 } 00809 if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { 00810 ppp_error("Can't lock %s: not a character device", dev); 00811 return -1; 00812 } 00813 ppp_slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", 00814 LOCK_DIR, major(sbuf.st_dev), 00815 major(sbuf.st_rdev), minor(sbuf.st_rdev)); 00816 #else 00817 char *p; 00818 char lockdev[MAXPATHLEN]; 00819 00820 if ((p = strstr(dev, "dev/")) != NULL) { 00821 dev = p + 4; 00822 strncpy(lockdev, dev, MAXPATHLEN-1); 00823 lockdev[MAXPATHLEN-1] = 0; 00824 while ((p = strrchr(lockdev, '/')) != NULL) { 00825 *p = '_'; 00826 } 00827 dev = lockdev; 00828 } else 00829 if ((p = strrchr(dev, '/')) != NULL) 00830 dev = p + 1; 00831 00832 ppp_slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); 00833 #endif 00834 00835 while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { 00836 if (errno != EEXIST) { 00837 ppp_error("Can't create lock file %s: %m", lock_file); 00838 break; 00839 } 00840 00841 /* Read the lock file to find out who has the device locked. */ 00842 fd = open(lock_file, O_RDONLY, 0); 00843 if (fd < 0) { 00844 if (errno == ENOENT) /* This is just a timing problem. */ 00845 continue; 00846 ppp_error("Can't open existing lock file %s: %m", lock_file); 00847 break; 00848 } 00849 #ifndef LOCK_BINARY 00850 n = read(fd, lock_buffer, 11); 00851 #else 00852 n = read(fd, &pid, sizeof(pid)); 00853 #endif /* LOCK_BINARY */ 00854 close(fd); 00855 fd = -1; 00856 if (n <= 0) { 00857 ppp_error("Can't read pid from lock file %s", lock_file); 00858 break; 00859 } 00860 00861 /* See if the process still exists. */ 00862 #ifndef LOCK_BINARY 00863 lock_buffer[n] = 0; 00864 pid = atoi(lock_buffer); 00865 #endif /* LOCK_BINARY */ 00866 if (pid == getpid()) 00867 return 1; /* somebody else locked it for us */ 00868 if (pid == 0 00869 || (kill(pid, 0) == -1 && errno == ESRCH)) { 00870 if (unlink (lock_file) == 0) { 00871 ppp_notice("Removed stale lock on %s (pid %d)", dev, pid); 00872 continue; 00873 } 00874 ppp_warn("Couldn't remove stale lock on %s", dev); 00875 } else 00876 ppp_notice("Device %s is locked by pid %d", dev, pid); 00877 break; 00878 } 00879 00880 if (fd < 0) { 00881 lock_file[0] = 0; 00882 return -1; 00883 } 00884 00885 pid = getpid(); 00886 #ifndef LOCK_BINARY 00887 ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); 00888 write (fd, lock_buffer, 11); 00889 #else 00890 write(fd, &pid, sizeof (pid)); 00891 #endif 00892 close(fd); 00893 return 0; 00894 00895 #endif 00896 } 00897 00898 /* 00899 * relock - called to update our lockfile when we are about to detach, 00900 * thus changing our pid (we fork, the child carries on, and the parent dies). 00901 * Note that this is called by the parent, with pid equal to the pid 00902 * of the child. This avoids a potential race which would exist if 00903 * we had the child rewrite the lockfile (the parent might die first, 00904 * and another process could think the lock was stale if it checked 00905 * between when the parent died and the child rewrote the lockfile). 00906 */ 00907 int 00908 relock(pid) 00909 int pid; 00910 { 00911 #ifdef LOCKLIB 00912 /* XXX is there a way to do this? */ 00913 return -1; 00914 #else /* LOCKLIB */ 00915 00916 int fd; 00917 char lock_buffer[12]; 00918 00919 if (lock_file[0] == 0) 00920 return -1; 00921 fd = open(lock_file, O_WRONLY, 0); 00922 if (fd < 0) { 00923 ppp_error("Couldn't reopen lock file %s: %m", lock_file); 00924 lock_file[0] = 0; 00925 return -1; 00926 } 00927 00928 #ifndef LOCK_BINARY 00929 ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); 00930 write (fd, lock_buffer, 11); 00931 #else 00932 write(fd, &pid, sizeof(pid)); 00933 #endif /* LOCK_BINARY */ 00934 close(fd); 00935 return 0; 00936 00937 #endif /* LOCKLIB */ 00938 } 00939 00940 /* 00941 * unlock - remove our lockfile 00942 */ 00943 void 00944 unlock() 00945 { 00946 if (lock_file[0]) { 00947 #ifdef LOCKLIB 00948 (void) rmlock(lock_file, (void *) 0); 00949 #else 00950 unlink(lock_file); 00951 #endif 00952 lock_file[0] = 0; 00953 } 00954 } 00955 00956 #endif /* Unused */ 00957 00958 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 13:55:03 by
