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