utils.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041
  1. /*
  2. * utils.c - various utility functions used in pppd.
  3. *
  4. * Copyright (c) 1999-2002 Paul Mackerras. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. *
  13. * 2. The name(s) of the authors of this software must not be used to
  14. * endorse or promote products derived from this software without
  15. * prior written permission.
  16. *
  17. * 3. Redistributions of any form whatsoever must retain the following
  18. * acknowledgment:
  19. * "This product includes software developed by Paul Mackerras
  20. * <paulus@samba.org>".
  21. *
  22. * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
  23. * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  24. * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
  25. * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  26. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  27. * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  28. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  29. */
  30. #define RCSID "$Id: utils.c,v 1.25 2008/06/03 12:06:37 paulus Exp $"
  31. #include <stdio.h>
  32. #include <ctype.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <unistd.h>
  36. #include <signal.h>
  37. #include <errno.h>
  38. #include <fcntl.h>
  39. #include <syslog.h>
  40. #include <netdb.h>
  41. #include <time.h>
  42. #include <utmp.h>
  43. #include <pwd.h>
  44. #include <sys/param.h>
  45. #include <sys/types.h>
  46. #include <sys/wait.h>
  47. #include <sys/time.h>
  48. #include <sys/resource.h>
  49. #include <sys/stat.h>
  50. #include <sys/socket.h>
  51. #include <netinet/in.h>
  52. #ifdef SVR4
  53. #include <sys/mkdev.h>
  54. #endif
  55. #include "pppd.h"
  56. #include "fsm.h"
  57. #include "lcp.h"
  58. static const char rcsid[] = RCSID;
  59. #if defined(SUNOS4)
  60. extern char *strerror();
  61. #endif
  62. static void logit __P((int, char *, va_list));
  63. static void log_write __P((int, char *));
  64. static void vslp_printer __P((void *, char *, ...));
  65. static void format_packet __P((u_char *, int, printer_func, void *));
  66. struct buffer_info {
  67. char *ptr;
  68. int len;
  69. };
  70. /*
  71. * strlcpy - like strcpy/strncpy, doesn't overflow destination buffer,
  72. * always leaves destination null-terminated (for len > 0).
  73. */
  74. size_t
  75. strlcpy(dest, src, len)
  76. char *dest;
  77. const char *src;
  78. size_t len;
  79. {
  80. size_t ret = strlen(src);
  81. if (len != 0) {
  82. if (ret < len)
  83. strcpy(dest, src);
  84. else {
  85. strncpy(dest, src, len - 1);
  86. dest[len-1] = 0;
  87. }
  88. }
  89. return ret;
  90. }
  91. /*
  92. * strlcat - like strcat/strncat, doesn't overflow destination buffer,
  93. * always leaves destination null-terminated (for len > 0).
  94. */
  95. size_t
  96. strlcat(dest, src, len)
  97. char *dest;
  98. const char *src;
  99. size_t len;
  100. {
  101. size_t dlen = strlen(dest);
  102. return dlen + strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0));
  103. }
  104. /*
  105. * slprintf - format a message into a buffer. Like sprintf except we
  106. * also specify the length of the output buffer, and we handle
  107. * %m (error message), %v (visible string),
  108. * %q (quoted string), %t (current time) and %I (IP address) formats.
  109. * Doesn't do floating-point formats.
  110. * Returns the number of chars put into buf.
  111. */
  112. int
  113. slprintf __V((char *buf, int buflen, char *fmt, ...))
  114. {
  115. va_list args;
  116. int n;
  117. #if defined(__STDC__)
  118. va_start(args, fmt);
  119. #else
  120. char *buf;
  121. int buflen;
  122. char *fmt;
  123. va_start(args);
  124. buf = va_arg(args, char *);
  125. buflen = va_arg(args, int);
  126. fmt = va_arg(args, char *);
  127. #endif
  128. n = vslprintf(buf, buflen, fmt, args);
  129. va_end(args);
  130. return n;
  131. }
  132. /*
  133. * vslprintf - like slprintf, takes a va_list instead of a list of args.
  134. */
  135. #define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
  136. int
  137. vslprintf(buf, buflen, fmt, args)
  138. char *buf;
  139. int buflen;
  140. char *fmt;
  141. va_list args;
  142. {
  143. int c, i, n;
  144. int width, prec, fillch;
  145. int base, len, neg, quoted;
  146. unsigned long val = 0;
  147. char *str, *f, *buf0;
  148. unsigned char *p;
  149. char num[32];
  150. time_t t;
  151. u_int32_t ip;
  152. static char hexchars[] = "0123456789abcdef";
  153. struct buffer_info bufinfo;
  154. buf0 = buf;
  155. --buflen;
  156. while (buflen > 0) {
  157. for (f = fmt; *f != '%' && *f != 0; ++f)
  158. ;
  159. if (f > fmt) {
  160. len = f - fmt;
  161. if (len > buflen)
  162. len = buflen;
  163. memcpy(buf, fmt, len);
  164. buf += len;
  165. buflen -= len;
  166. fmt = f;
  167. }
  168. if (*fmt == 0)
  169. break;
  170. c = *++fmt;
  171. width = 0;
  172. prec = -1;
  173. fillch = ' ';
  174. if (c == '0') {
  175. fillch = '0';
  176. c = *++fmt;
  177. }
  178. if (c == '*') {
  179. width = va_arg(args, int);
  180. c = *++fmt;
  181. } else {
  182. while (isdigit(c)) {
  183. width = width * 10 + c - '0';
  184. c = *++fmt;
  185. }
  186. }
  187. if (c == '.') {
  188. c = *++fmt;
  189. if (c == '*') {
  190. prec = va_arg(args, int);
  191. c = *++fmt;
  192. } else {
  193. prec = 0;
  194. while (isdigit(c)) {
  195. prec = prec * 10 + c - '0';
  196. c = *++fmt;
  197. }
  198. }
  199. }
  200. str = 0;
  201. base = 0;
  202. neg = 0;
  203. ++fmt;
  204. switch (c) {
  205. case 'l':
  206. c = *fmt++;
  207. switch (c) {
  208. case 'd':
  209. val = va_arg(args, long);
  210. if (val < 0) {
  211. neg = 1;
  212. val = -val;
  213. }
  214. base = 10;
  215. break;
  216. case 'u':
  217. val = va_arg(args, unsigned long);
  218. base = 10;
  219. break;
  220. default:
  221. OUTCHAR('%');
  222. OUTCHAR('l');
  223. --fmt; /* so %lz outputs %lz etc. */
  224. continue;
  225. }
  226. break;
  227. case 'd':
  228. i = va_arg(args, int);
  229. if (i < 0) {
  230. neg = 1;
  231. val = -i;
  232. } else
  233. val = i;
  234. base = 10;
  235. break;
  236. case 'u':
  237. val = va_arg(args, unsigned int);
  238. base = 10;
  239. break;
  240. case 'o':
  241. val = va_arg(args, unsigned int);
  242. base = 8;
  243. break;
  244. case 'x':
  245. case 'X':
  246. val = va_arg(args, unsigned int);
  247. base = 16;
  248. break;
  249. case 'p':
  250. val = (unsigned long) va_arg(args, void *);
  251. base = 16;
  252. neg = 2;
  253. break;
  254. case 's':
  255. str = va_arg(args, char *);
  256. break;
  257. case 'c':
  258. num[0] = va_arg(args, int);
  259. num[1] = 0;
  260. str = num;
  261. break;
  262. case 'm':
  263. str = strerror(errno);
  264. break;
  265. case 'I':
  266. ip = va_arg(args, u_int32_t);
  267. ip = ntohl(ip);
  268. slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff,
  269. (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
  270. str = num;
  271. break;
  272. case 't':
  273. time(&t);
  274. str = ctime(&t);
  275. str += 4; /* chop off the day name */
  276. str[15] = 0; /* chop off year and newline */
  277. break;
  278. case 'v': /* "visible" string */
  279. case 'q': /* quoted string */
  280. quoted = c == 'q';
  281. p = va_arg(args, unsigned char *);
  282. if (p == NULL)
  283. p = (unsigned char *)"<NULL>";
  284. if (fillch == '0' && prec >= 0) {
  285. n = prec;
  286. } else {
  287. n = strlen((char *)p);
  288. if (prec >= 0 && n > prec)
  289. n = prec;
  290. }
  291. while (n > 0 && buflen > 0) {
  292. c = *p++;
  293. --n;
  294. if (!quoted && c >= 0x80) {
  295. OUTCHAR('M');
  296. OUTCHAR('-');
  297. c -= 0x80;
  298. }
  299. if (quoted && (c == '"' || c == '\\'))
  300. OUTCHAR('\\');
  301. if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
  302. if (quoted) {
  303. OUTCHAR('\\');
  304. switch (c) {
  305. case '\t': OUTCHAR('t'); break;
  306. case '\n': OUTCHAR('n'); break;
  307. case '\b': OUTCHAR('b'); break;
  308. case '\f': OUTCHAR('f'); break;
  309. default:
  310. OUTCHAR('x');
  311. OUTCHAR(hexchars[c >> 4]);
  312. OUTCHAR(hexchars[c & 0xf]);
  313. }
  314. } else {
  315. if (c == '\t')
  316. OUTCHAR(c);
  317. else {
  318. OUTCHAR('^');
  319. OUTCHAR(c ^ 0x40);
  320. }
  321. }
  322. } else
  323. OUTCHAR(c);
  324. }
  325. continue;
  326. case 'P': /* print PPP packet */
  327. bufinfo.ptr = buf;
  328. bufinfo.len = buflen + 1;
  329. p = va_arg(args, unsigned char *);
  330. n = va_arg(args, int);
  331. format_packet(p, n, vslp_printer, &bufinfo);
  332. buf = bufinfo.ptr;
  333. buflen = bufinfo.len - 1;
  334. continue;
  335. case 'B':
  336. p = va_arg(args, unsigned char *);
  337. for (n = prec; n > 0; --n) {
  338. c = *p++;
  339. if (fillch == ' ')
  340. OUTCHAR(' ');
  341. OUTCHAR(hexchars[(c >> 4) & 0xf]);
  342. OUTCHAR(hexchars[c & 0xf]);
  343. }
  344. continue;
  345. default:
  346. *buf++ = '%';
  347. if (c != '%')
  348. --fmt; /* so %z outputs %z etc. */
  349. --buflen;
  350. continue;
  351. }
  352. if (base != 0) {
  353. str = num + sizeof(num);
  354. *--str = 0;
  355. while (str > num + neg) {
  356. *--str = hexchars[val % base];
  357. val = val / base;
  358. if (--prec <= 0 && val == 0)
  359. break;
  360. }
  361. switch (neg) {
  362. case 1:
  363. *--str = '-';
  364. break;
  365. case 2:
  366. *--str = 'x';
  367. *--str = '0';
  368. break;
  369. }
  370. len = num + sizeof(num) - 1 - str;
  371. } else {
  372. len = strlen(str);
  373. if (prec >= 0 && len > prec)
  374. len = prec;
  375. }
  376. if (width > 0) {
  377. if (width > buflen)
  378. width = buflen;
  379. if ((n = width - len) > 0) {
  380. buflen -= n;
  381. for (; n > 0; --n)
  382. *buf++ = fillch;
  383. }
  384. }
  385. if (len > buflen)
  386. len = buflen;
  387. memcpy(buf, str, len);
  388. buf += len;
  389. buflen -= len;
  390. }
  391. *buf = 0;
  392. return buf - buf0;
  393. }
  394. /*
  395. * vslp_printer - used in processing a %P format
  396. */
  397. static void
  398. vslp_printer __V((void *arg, char *fmt, ...))
  399. {
  400. int n;
  401. va_list pvar;
  402. struct buffer_info *bi;
  403. #if defined(__STDC__)
  404. va_start(pvar, fmt);
  405. #else
  406. void *arg;
  407. char *fmt;
  408. va_start(pvar);
  409. arg = va_arg(pvar, void *);
  410. fmt = va_arg(pvar, char *);
  411. #endif
  412. bi = (struct buffer_info *) arg;
  413. n = vslprintf(bi->ptr, bi->len, fmt, pvar);
  414. va_end(pvar);
  415. bi->ptr += n;
  416. bi->len -= n;
  417. }
  418. #ifdef unused
  419. /*
  420. * log_packet - format a packet and log it.
  421. */
  422. void
  423. log_packet(p, len, prefix, level)
  424. u_char *p;
  425. int len;
  426. char *prefix;
  427. int level;
  428. {
  429. init_pr_log(prefix, level);
  430. format_packet(p, len, pr_log, &level);
  431. end_pr_log();
  432. }
  433. #endif /* unused */
  434. /*
  435. * format_packet - make a readable representation of a packet,
  436. * calling `printer(arg, format, ...)' to output it.
  437. */
  438. static void
  439. format_packet(p, len, printer, arg)
  440. u_char *p;
  441. int len;
  442. printer_func printer;
  443. void *arg;
  444. {
  445. int i, n;
  446. u_short proto;
  447. struct protent *protp;
  448. if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
  449. p += 2;
  450. GETSHORT(proto, p);
  451. len -= PPP_HDRLEN;
  452. for (i = 0; (protp = protocols[i]) != NULL; ++i)
  453. if (proto == protp->protocol)
  454. break;
  455. if (protp != NULL) {
  456. printer(arg, "[%s", protp->name);
  457. n = (*protp->printpkt)(p, len, printer, arg);
  458. printer(arg, "]");
  459. p += n;
  460. len -= n;
  461. } else {
  462. for (i = 0; (protp = protocols[i]) != NULL; ++i)
  463. if (proto == (protp->protocol & ~0x8000))
  464. break;
  465. if (protp != 0 && protp->data_name != 0) {
  466. printer(arg, "[%s data]", protp->data_name);
  467. if (len > 8)
  468. printer(arg, "%.8B ...", p);
  469. else
  470. printer(arg, "%.*B", len, p);
  471. len = 0;
  472. } else
  473. printer(arg, "[proto=0x%x]", proto);
  474. }
  475. }
  476. if (len > 32)
  477. printer(arg, "%.32B ...", p);
  478. else
  479. printer(arg, "%.*B", len, p);
  480. }
  481. /*
  482. * init_pr_log, end_pr_log - initialize and finish use of pr_log.
  483. */
  484. static char line[256]; /* line to be logged accumulated here */
  485. static char *linep; /* current pointer within line */
  486. static int llevel; /* level for logging */
  487. void
  488. init_pr_log(prefix, level)
  489. const char *prefix;
  490. int level;
  491. {
  492. linep = line;
  493. if (prefix != NULL) {
  494. strlcpy(line, prefix, sizeof(line));
  495. linep = line + strlen(line);
  496. }
  497. llevel = level;
  498. }
  499. void
  500. end_pr_log()
  501. {
  502. if (linep != line) {
  503. *linep = 0;
  504. log_write(llevel, line);
  505. }
  506. }
  507. /*
  508. * pr_log - printer routine for outputting to syslog
  509. */
  510. void
  511. pr_log __V((void *arg, char *fmt, ...))
  512. {
  513. int l, n;
  514. va_list pvar;
  515. char *p, *eol;
  516. char buf[256];
  517. #if defined(__STDC__)
  518. va_start(pvar, fmt);
  519. #else
  520. void *arg;
  521. char *fmt;
  522. va_start(pvar);
  523. arg = va_arg(pvar, void *);
  524. fmt = va_arg(pvar, char *);
  525. #endif
  526. n = vslprintf(buf, sizeof(buf), fmt, pvar);
  527. va_end(pvar);
  528. p = buf;
  529. eol = strchr(buf, '\n');
  530. if (linep != line) {
  531. l = (eol == NULL)? n: eol - buf;
  532. if (linep + l < line + sizeof(line)) {
  533. if (l > 0) {
  534. memcpy(linep, buf, l);
  535. linep += l;
  536. }
  537. if (eol == NULL)
  538. return;
  539. p = eol + 1;
  540. eol = strchr(p, '\n');
  541. }
  542. *linep = 0;
  543. log_write(llevel, line);
  544. linep = line;
  545. }
  546. while (eol != NULL) {
  547. *eol = 0;
  548. log_write(llevel, p);
  549. p = eol + 1;
  550. eol = strchr(p, '\n');
  551. }
  552. /* assumes sizeof(buf) <= sizeof(line) */
  553. l = buf + n - p;
  554. if (l > 0) {
  555. memcpy(line, p, n);
  556. linep = line + l;
  557. }
  558. }
  559. /*
  560. * print_string - print a readable representation of a string using
  561. * printer.
  562. */
  563. void
  564. print_string(p, len, printer, arg)
  565. char *p;
  566. int len;
  567. printer_func printer;
  568. void *arg;
  569. {
  570. int c;
  571. printer(arg, "\"");
  572. for (; len > 0; --len) {
  573. c = *p++;
  574. if (' ' <= c && c <= '~') {
  575. if (c == '\\' || c == '"')
  576. printer(arg, "\\");
  577. printer(arg, "%c", c);
  578. } else {
  579. switch (c) {
  580. case '\n':
  581. printer(arg, "\\n");
  582. break;
  583. case '\r':
  584. printer(arg, "\\r");
  585. break;
  586. case '\t':
  587. printer(arg, "\\t");
  588. break;
  589. default:
  590. printer(arg, "\\%.3o", c);
  591. }
  592. }
  593. }
  594. printer(arg, "\"");
  595. }
  596. /*
  597. * logit - does the hard work for fatal et al.
  598. */
  599. static void
  600. logit(level, fmt, args)
  601. int level;
  602. char *fmt;
  603. va_list args;
  604. {
  605. char buf[1024];
  606. vslprintf(buf, sizeof(buf), fmt, args);
  607. log_write(level, buf);
  608. }
  609. static void
  610. log_write(level, buf)
  611. int level;
  612. char *buf;
  613. {
  614. syslog(level, "%s", buf);
  615. if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) {
  616. int n = strlen(buf);
  617. if (n > 0 && buf[n-1] == '\n')
  618. --n;
  619. if (write(log_to_fd, buf, n) != n
  620. || write(log_to_fd, "\n", 1) != 1)
  621. log_to_fd = -1;
  622. }
  623. }
  624. /*
  625. * fatal - log an error message and die horribly.
  626. */
  627. void
  628. fatal __V((char *fmt, ...))
  629. {
  630. va_list pvar;
  631. #if defined(__STDC__)
  632. va_start(pvar, fmt);
  633. #else
  634. char *fmt;
  635. va_start(pvar);
  636. fmt = va_arg(pvar, char *);
  637. #endif
  638. logit(LOG_ERR, fmt, pvar);
  639. va_end(pvar);
  640. die(1); /* as promised */
  641. }
  642. /*
  643. * error - log an error message.
  644. */
  645. void
  646. error __V((char *fmt, ...))
  647. {
  648. va_list pvar;
  649. #if defined(__STDC__)
  650. va_start(pvar, fmt);
  651. #else
  652. char *fmt;
  653. va_start(pvar);
  654. fmt = va_arg(pvar, char *);
  655. #endif
  656. logit(LOG_ERR, fmt, pvar);
  657. va_end(pvar);
  658. ++error_count;
  659. }
  660. /*
  661. * warn - log a warning message.
  662. */
  663. void
  664. warn __V((char *fmt, ...))
  665. {
  666. va_list pvar;
  667. #if defined(__STDC__)
  668. va_start(pvar, fmt);
  669. #else
  670. char *fmt;
  671. va_start(pvar);
  672. fmt = va_arg(pvar, char *);
  673. #endif
  674. logit(LOG_WARNING, fmt, pvar);
  675. va_end(pvar);
  676. }
  677. /*
  678. * notice - log a notice-level message.
  679. */
  680. void
  681. notice __V((char *fmt, ...))
  682. {
  683. va_list pvar;
  684. #if defined(__STDC__)
  685. va_start(pvar, fmt);
  686. #else
  687. char *fmt;
  688. va_start(pvar);
  689. fmt = va_arg(pvar, char *);
  690. #endif
  691. logit(LOG_NOTICE, fmt, pvar);
  692. va_end(pvar);
  693. }
  694. /*
  695. * info - log an informational message.
  696. */
  697. void
  698. info __V((char *fmt, ...))
  699. {
  700. va_list pvar;
  701. #if defined(__STDC__)
  702. va_start(pvar, fmt);
  703. #else
  704. char *fmt;
  705. va_start(pvar);
  706. fmt = va_arg(pvar, char *);
  707. #endif
  708. logit(LOG_INFO, fmt, pvar);
  709. va_end(pvar);
  710. }
  711. /*
  712. * dbglog - log a debug message.
  713. */
  714. void
  715. dbglog __V((char *fmt, ...))
  716. {
  717. va_list pvar;
  718. #if defined(__STDC__)
  719. va_start(pvar, fmt);
  720. #else
  721. char *fmt;
  722. va_start(pvar);
  723. fmt = va_arg(pvar, char *);
  724. #endif
  725. logit(LOG_DEBUG, fmt, pvar);
  726. va_end(pvar);
  727. }
  728. /*
  729. * dump_packet - print out a packet in readable form if it is interesting.
  730. * Assumes len >= PPP_HDRLEN.
  731. */
  732. void
  733. dump_packet(const char *tag, unsigned char *p, int len)
  734. {
  735. int proto;
  736. if (!debug)
  737. return;
  738. /*
  739. * don't print LCP echo request/reply packets if debug <= 1
  740. * and the link is up.
  741. */
  742. proto = (p[2] << 8) + p[3];
  743. if (debug <= 1 && unsuccess == 0 && proto == PPP_LCP
  744. && len >= PPP_HDRLEN + HEADERLEN) {
  745. unsigned char *lcp = p + PPP_HDRLEN;
  746. int l = (lcp[2] << 8) + lcp[3];
  747. if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP)
  748. && l >= HEADERLEN && l <= len - PPP_HDRLEN)
  749. return;
  750. }
  751. dbglog("%s %P", tag, p, len);
  752. }
  753. /*
  754. * complete_read - read a full `count' bytes from fd,
  755. * unless end-of-file or an error other than EINTR is encountered.
  756. */
  757. ssize_t
  758. complete_read(int fd, void *buf, size_t count)
  759. {
  760. size_t done;
  761. ssize_t nb;
  762. char *ptr = buf;
  763. for (done = 0; done < count; ) {
  764. nb = read(fd, ptr, count - done);
  765. if (nb < 0) {
  766. if (errno == EINTR)
  767. continue;
  768. return -1;
  769. }
  770. if (nb == 0)
  771. break;
  772. done += nb;
  773. ptr += nb;
  774. }
  775. return done;
  776. }
  777. /* Procedures for locking the serial device using a lock file. */
  778. #ifndef LOCK_DIR
  779. #ifdef __linux__
  780. #define LOCK_DIR "/var/lock"
  781. #else
  782. #ifdef SVR4
  783. #define LOCK_DIR "/var/spool/locks"
  784. #else
  785. #define LOCK_DIR "/var/spool/lock"
  786. #endif
  787. #endif
  788. #endif /* LOCK_DIR */
  789. static char lock_file[MAXPATHLEN];
  790. /*
  791. * lock - create a lock file for the named device
  792. */
  793. int
  794. lock(dev)
  795. char *dev;
  796. {
  797. #ifdef LOCKLIB
  798. int result;
  799. result = mklock (dev, (void *) 0);
  800. if (result == 0) {
  801. strlcpy(lock_file, dev, sizeof(lock_file));
  802. return 0;
  803. }
  804. if (result > 0)
  805. notice("Device %s is locked by pid %d", dev, result);
  806. else
  807. error("Can't create lock file %s", lock_file);
  808. return -1;
  809. #else /* LOCKLIB */
  810. char lock_buffer[12];
  811. int fd, pid, n;
  812. #ifdef SVR4
  813. struct stat sbuf;
  814. if (stat(dev, &sbuf) < 0) {
  815. error("Can't get device number for %s: %m", dev);
  816. return -1;
  817. }
  818. if ((sbuf.st_mode & S_IFMT) != S_IFCHR) {
  819. error("Can't lock %s: not a character device", dev);
  820. return -1;
  821. }
  822. slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d",
  823. LOCK_DIR, major(sbuf.st_dev),
  824. major(sbuf.st_rdev), minor(sbuf.st_rdev));
  825. #else
  826. char *p;
  827. char lockdev[MAXPATHLEN];
  828. if ((p = strstr(dev, "dev/")) != NULL) {
  829. dev = p + 4;
  830. strncpy(lockdev, dev, MAXPATHLEN-1);
  831. lockdev[MAXPATHLEN-1] = 0;
  832. while ((p = strrchr(lockdev, '/')) != NULL) {
  833. *p = '_';
  834. }
  835. dev = lockdev;
  836. } else
  837. if ((p = strrchr(dev, '/')) != NULL)
  838. dev = p + 1;
  839. slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev);
  840. #endif
  841. while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
  842. if (errno != EEXIST) {
  843. error("Can't create lock file %s: %m", lock_file);
  844. break;
  845. }
  846. /* Read the lock file to find out who has the device locked. */
  847. fd = open(lock_file, O_RDONLY, 0);
  848. if (fd < 0) {
  849. if (errno == ENOENT) /* This is just a timing problem. */
  850. continue;
  851. error("Can't open existing lock file %s: %m", lock_file);
  852. break;
  853. }
  854. #ifndef LOCK_BINARY
  855. n = read(fd, lock_buffer, 11);
  856. #else
  857. n = read(fd, &pid, sizeof(pid));
  858. #endif /* LOCK_BINARY */
  859. close(fd);
  860. fd = -1;
  861. if (n <= 0) {
  862. error("Can't read pid from lock file %s", lock_file);
  863. break;
  864. }
  865. /* See if the process still exists. */
  866. #ifndef LOCK_BINARY
  867. lock_buffer[n] = 0;
  868. pid = atoi(lock_buffer);
  869. #endif /* LOCK_BINARY */
  870. if (pid == getpid())
  871. return 1; /* somebody else locked it for us */
  872. if (pid == 0
  873. || (kill(pid, 0) == -1 && errno == ESRCH)) {
  874. if (unlink (lock_file) == 0) {
  875. notice("Removed stale lock on %s (pid %d)", dev, pid);
  876. continue;
  877. }
  878. warn("Couldn't remove stale lock on %s", dev);
  879. } else
  880. notice("Device %s is locked by pid %d", dev, pid);
  881. break;
  882. }
  883. if (fd < 0) {
  884. lock_file[0] = 0;
  885. return -1;
  886. }
  887. pid = getpid();
  888. #ifndef LOCK_BINARY
  889. slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid);
  890. write (fd, lock_buffer, 11);
  891. #else
  892. write(fd, &pid, sizeof (pid));
  893. #endif
  894. close(fd);
  895. return 0;
  896. #endif
  897. }
  898. /*
  899. * relock - called to update our lockfile when we are about to detach,
  900. * thus changing our pid (we fork, the child carries on, and the parent dies).
  901. * Note that this is called by the parent, with pid equal to the pid
  902. * of the child. This avoids a potential race which would exist if
  903. * we had the child rewrite the lockfile (the parent might die first,
  904. * and another process could think the lock was stale if it checked
  905. * between when the parent died and the child rewrote the lockfile).
  906. */
  907. int
  908. relock(pid)
  909. int pid;
  910. {
  911. #ifdef LOCKLIB
  912. /* XXX is there a way to do this? */
  913. return -1;
  914. #else /* LOCKLIB */
  915. int fd;
  916. char lock_buffer[12];
  917. if (lock_file[0] == 0)
  918. return -1;
  919. fd = open(lock_file, O_WRONLY, 0);
  920. if (fd < 0) {
  921. error("Couldn't reopen lock file %s: %m", lock_file);
  922. lock_file[0] = 0;
  923. return -1;
  924. }
  925. #ifndef LOCK_BINARY
  926. slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid);
  927. write (fd, lock_buffer, 11);
  928. #else
  929. write(fd, &pid, sizeof(pid));
  930. #endif /* LOCK_BINARY */
  931. close(fd);
  932. return 0;
  933. #endif /* LOCKLIB */
  934. }
  935. /*
  936. * unlock - remove our lockfile
  937. */
  938. void
  939. unlock()
  940. {
  941. if (lock_file[0]) {
  942. #ifdef LOCKLIB
  943. (void) rmlock(lock_file, (void *) 0);
  944. #else
  945. unlink(lock_file);
  946. #endif
  947. lock_file[0] = 0;
  948. }
  949. }