change fd -> ttyfd, fd arg to various functions
[ppp.git] / pppd / sys-osf.c
1 /*
2  * sys-osf.c - System-dependent procedures for setting up
3  * PPP interfaces on OSF/1 systems which use the STREAMS ppp interface.
4  *
5  * Copyright (c) 1989 Carnegie Mellon University.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by Carnegie Mellon University.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20
21 #ifndef lint
22 static char rcsid[] = "$Id: sys-osf.c,v 1.6 1996/01/01 23:07:07 paulus Exp $";
23 #endif
24
25 /*
26  * TODO:
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <syslog.h>
33 #include <termios.h>
34 #include <fcntl.h>
35 #include <string.h>
36 #include <time.h>
37 #include <utmp.h>
38 #include <poll.h>
39 #include <signal.h>
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <sys/time.h>
43 #include <sys/stream.h>
44 #include <sys/stropts.h>
45
46 #include <net/if.h>
47 #include <net/ppp_defs.h>
48 #include <net/ppp_str.h>
49 #include <net/route.h>
50 #include <net/if_arp.h>
51 #include <netinet/in.h>
52
53 #include "pppd.h"
54
55 #ifndef ifr_mtu
56 #define ifr_mtu         ifr_metric
57 #endif
58
59 #define MAXMODULES      10      /* max number of module names to save */
60 static struct   modlist {
61     char        modname[FMNAMESZ+1];
62 } str_modules[MAXMODULES];
63 static int      str_module_count = 0;
64 static int      pushed_ppp;
65 static int      closed_stdio;
66
67 static int      restore_term;   /* 1 => we've munged the terminal */
68 static struct termios inittermios; /* Initial TTY termios */
69 static struct winsize wsinfo;      /* Initial window size info */
70 static int      initfdflags = -1; /* Initial file descriptor flags for fd */
71
72 static int sockfd;              /* socket for doing interface ioctls */
73
74 int orig_ttyfd = -1;   /*  Original ttyfd if we did a streamify()  */
75
76 static int      if_is_up;       /* Interface has been marked up */
77 static u_int32_t default_route_gateway; /* Gateway for default route added */
78 static u_int32_t proxy_arp_addr;        /* Addr for proxy arp entry added */
79
80 /* Prototypes for procedures local to this file. */
81 static int translate_speed __P((int));
82 static int baud_rate_of __P((int));
83 static int get_ether_addr __P((u_int32_t, struct sockaddr *));
84
85
86 /*
87  * sys_init - System-dependent initialization.
88  */
89 void
90 sys_init()
91 {
92     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
93     setlogmask(LOG_UPTO(LOG_INFO));
94     if (debug)
95         setlogmask(LOG_UPTO(LOG_DEBUG));
96
97     /* Get an internet socket for doing socket ioctl's on. */
98     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
99         syslog(LOG_ERR, "Couldn't create IP socket: %m");
100         die(1);
101     }
102 }
103
104 /*
105  * sys_cleanup - restore any system state we modified before exiting:
106  * mark the interface down, delete default route and/or proxy arp entry.
107  * This should call die() because it's called from die().
108  */
109 void
110 sys_cleanup()
111 {
112     struct ifreq ifr;
113
114     if (if_is_up) {
115         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
116         if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
117             && ((ifr.ifr_flags & IFF_UP) != 0)) {
118             ifr.ifr_flags &= ~IFF_UP;
119             ioctl(sockfd, SIOCSIFFLAGS, &ifr);
120         }
121     }
122
123     if (default_route_gateway)
124         cifdefaultroute(0, default_route_gateway);
125     if (proxy_arp_addr)
126         cifproxyarp(0, proxy_arp_addr);
127 }
128
129 /*
130  * note_debug_level - note a change in the debug level.
131  */
132 void
133 note_debug_level()
134 {
135     if (debug) {
136         syslog(LOG_INFO, "Debug turned ON, Level %d", debug);
137         setlogmask(LOG_UPTO(LOG_DEBUG));
138     } else {
139         setlogmask(LOG_UPTO(LOG_WARNING));
140     }
141 }
142
143 /*
144  * daemon - Detach us from the terminal session.
145  */
146 int
147 daemon(nochdir, noclose)
148     int nochdir, noclose;
149 {
150     int pid;
151
152     if ((pid = fork()) < 0)
153         return -1;
154     if (pid != 0)
155         exit(0);                /* parent dies */
156     setsid();
157     if (!nochdir)
158         chdir("/");
159     if (!noclose) {
160         fclose(stdin);          /* don't need stdin, stdout, stderr */
161         fclose(stdout);
162         fclose(stderr);
163     }
164     return 0;
165 }
166
167
168 char pipename[] = "/dev/streams/pipe";
169
170 /*
171  * ppp_available - check if this kernel supports PPP.
172  */
173 int
174 ppp_available()
175 {
176     int fd, ret;
177
178     fd = open(pipename, O_RDONLY, 0);
179     if (fd < 0)
180         return 0;               /* can't find out - assume we don't have ppp */
181     ret = ioctl(fd, I_FIND, "pppasync") >= 0;
182     close(fd);
183     return ret;
184 }
185
186
187 /*
188  *  streampipe -- Opens a STREAMS based pipe.  Used by streamify().
189  */
190
191 int 
192 streampipe(int fd[2])
193 {
194     if ((fd[0]=open(pipename, O_RDWR)) == -1)
195         return(-1);
196     else if ((fd[1]=open(pipename, O_RDWR)) == -1) {
197         close(fd[0]);
198         return(-1);
199     } else if (ioctl(fd[0], I_PIPE, fd[1]) != 0) {
200         close(fd[0]);
201         close(fd[1]);
202         return(-1);
203     } else {
204         return(ioctl(fd[0], I_PUSH, "pipemod"));
205     }
206 }
207
208 /*
209  *  streamify -- Needed for DEC OSF/1, since tty devices are not STREAMS
210  *               modules (but ptys are, and pipes can be).
211  */
212
213 #define BUFFSIZE 1000     /*  Size of buffer for streamify()  */
214
215 int 
216 streamify(int fd)
217 {
218     int fdes[2];
219     fd_set readfds;
220     int ret, fret, rret, maxfd;
221     static char buffer[BUFFSIZE];
222     struct sigaction sa;
223
224     if (streampipe(fdes) != 0)
225         syslog(LOG_ERR, "streampipe(): %m\n");
226     else if (isastream(fdes[0]) == 1) {
227         if ((fret=fork()) < 0) {
228             syslog(LOG_ERR, "fork(): %m\n");
229         } else if (fret == 0) {
230             /*  Process to forward things from pipe to tty  */
231             sigemptyset(&(sa.sa_mask));
232             sa.sa_handler = SIG_DFL;
233             sa.sa_flags = 0;
234             sigaction(SIGHUP, &sa, NULL);   /*  Go back to default actions */
235             sigaction(SIGINT, &sa, NULL);   /*  for changed signals.  */
236             sigaction(SIGTERM, &sa, NULL);
237             sigaction(SIGCHLD, &sa, NULL);
238             sigaction(SIGUSR1, &sa, NULL);
239             sigaction(SIGUSR2, &sa, NULL);
240             close(fdes[0]);
241
242             maxfd = (fdes[1]>fd)?fdes[1]:fd;
243             while (1) {
244                 FD_ZERO(&readfds);
245                 FD_SET(fdes[1], &readfds);
246                 FD_SET(fd, &readfds);
247                 ret = select(maxfd+1, &readfds, NULL, NULL, NULL);
248                 if (FD_ISSET(fd, &readfds)) {
249                     rret = read(fd, buffer, BUFFSIZE);
250                     if (rret == 0) {
251                         MAINDEBUG((LOG_DEBUG, "slave died:  EOF on tty."));
252                         exit(0);
253                     } else {
254                         write(fdes[1], buffer, rret);
255                     }
256                 }
257                 if (FD_ISSET(fdes[1], &readfds)) {
258                     rret = read(fdes[1], buffer, BUFFSIZE);
259                     if (rret == 0) {
260                         MAINDEBUG((LOG_DEBUG, "slave died:  EOF on pipe."));
261                         exit(0);
262                     } else {
263                         write(fd, buffer, rret);
264                     }
265                 }
266             }
267         } else {
268             close(fdes[1]);
269             orig_ttyfd = fd;
270             return(fdes[0]);
271         }
272     }
273
274     return(-1);
275 }
276
277
278 /*
279  * establish_ppp - Turn the serial port into a ppp interface.
280  */
281 void
282 establish_ppp(fd)
283     int fd;
284 {
285     int ret;
286
287     if (isastream(fd) != 1) {
288         if ((ttyfd = fd = streamify(fd)) < 0) {
289             syslog(LOG_ERR, "Couldn't get a STREAMS module!\n");
290             die(1);
291         }
292     }
293
294     /* go through and save the name of all the modules, then pop em */
295     for (;;) { 
296         if (ioctl(fd, I_LOOK, str_modules[str_module_count].modname) < 0 ||
297             ioctl(fd, I_POP, 0) < 0)
298             break;
299         MAINDEBUG((LOG_DEBUG, "popped stream module : %s",
300                    str_modules[str_module_count].modname));
301         str_module_count++;
302     }
303
304     /* now push the async/fcs module */
305     if (ioctl(fd, I_PUSH, "pppasync") < 0) {
306         syslog(LOG_ERR, "ioctl(I_PUSH, ppp_async): %m");
307         die(1);
308     }
309     /* push the compress module */
310     if (ioctl(fd, I_PUSH, "pppcomp") < 0) {
311         syslog(LOG_WARNING, "ioctl(I_PUSH, ppp_comp): %m");
312     }
313     /* finally, push the ppp_if module that actually handles the */
314     /* network interface */ 
315     if (ioctl(fd, I_PUSH, "pppif") < 0) {
316         syslog(LOG_ERR, "ioctl(I_PUSH, ppp_if): %m");
317         die(1);
318     }
319     pushed_ppp = 1;
320     /* read mode, message non-discard mode */
321     if (ioctl(fd, I_SRDOPT, RMSGN|RPROTNORM) < 0) {
322         syslog(LOG_ERR, "ioctl(I_SRDOPT, RMSGN): %m");
323         die(1);
324     }
325     /*
326      * Find out which interface we were given.
327      * (ppp_if handles this ioctl)
328      */
329     if (ioctl(fd, (int)SIOCGETU, &ifunit) < 0) {
330         syslog(LOG_ERR, "ioctl(SIOCGETU): %m");
331         die(1);
332     }
333
334     /* Set debug flags in driver */
335     if (ioctl(fd, (int)SIOCSIFDEBUG, &kdebugflag) < 0) {
336         syslog(LOG_ERR, "ioctl(SIOCSIFDEBUG): %m");
337     }
338
339     /* close stdin, stdout, stderr if they might refer to the device */
340     if (default_device && !closed_stdio) {
341         int i;
342
343         for (i = 0; i <= 2; ++i)
344             if (i != fd && i != sockfd) 
345                 close(i);
346         closed_stdio = 1;
347     }
348
349     /*
350      * Set device for non-blocking reads.
351      */
352     if ((initfdflags = fcntl(fd, F_GETFL)) == -1
353         || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
354         syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m");
355     }
356 }
357
358 /*  Debugging routine....  */
359
360 void prstrstack(int fd)
361 {
362     struct str_list sl;
363     struct str_mlist names[20];
364     int ret, i;
365
366     sl.sl_modlist = names;
367
368     ret = ioctl(fd, I_LIST, &sl);
369
370     if (ret >= 0) {
371         MAINDEBUG((LOG_DEBUG, "Current streams modules:\n"));
372         for (i=0; i<sl.sl_nmods; i++)
373             MAINDEBUG((LOG_DEBUG,"    %s\n", names[i].l_name));
374     } else {
375         MAINDEBUG((LOG_DEBUG,"I_LIST ioctl() failed.\n"));
376     }
377 }
378
379
380 /*
381  * disestablish_ppp - Restore the serial port to normal operation.
382  * It attempts to reconstruct the stream with the previously popped
383  * modules.  This shouldn't call die() because it's called from die().
384  */
385 void
386 disestablish_ppp(fd)
387     int fd;
388 {
389     int flags;
390     char *s;
391
392     /* Reset non-blocking mode on the file descriptor. */
393     if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
394         syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
395     initfdflags = -1;
396
397     if (hungup) {
398         /* we can't push or pop modules after the stream has hung up */
399         str_module_count = 0;
400         restore_term = 0;       /* nor can we fix up terminal settings */
401         return;
402     }
403
404     if (pushed_ppp) {
405         while (ioctl(fd, I_POP, 0) == 0) /* pop any we pushed */
406             ;
407         pushed_ppp = 0;
408
409         for (; str_module_count > 0; str_module_count--) {
410             if (ioctl(fd, I_PUSH, str_modules[str_module_count-1].modname)) {
411                 if (errno != ENXIO)
412                     syslog(LOG_WARNING, "str_restore: couldn't push module %s: %m",
413                            str_modules[str_module_count-1].modname);
414             } else {
415                 MAINDEBUG((LOG_INFO, "str_restore: pushed module %s",
416                            str_modules[str_module_count-1].modname));
417             }
418         }
419
420         if (orig_ttyfd >= 0) {
421             close(fd);
422             ttyfd = orig_ttyfd;
423             fd = -1;
424         }
425     }
426
427 }
428
429 /*
430  * clean_check - check whether the link seems to be 8-bit clean.
431  */
432 void
433 clean_check()
434 {
435     if (pushed_ppp) {
436         /*
437          * Check whether the link seems not to be 8-bit clean.
438          */
439         if (ioctl(ttyfd, (int)SIOCGIFDEBUG, (caddr_t) &flags) == 0) {
440             s = NULL;
441             switch (~flags & PAI_FLAGS_HIBITS) {
442               case PAI_FLAGS_B7_0:
443                 s = "bit 7 set to 1";
444                 break;
445               case PAI_FLAGS_B7_1:
446                 s = "bit 7 set to 0";
447                 break;
448               case PAI_FLAGS_PAR_EVEN:
449                 s = "odd parity";
450                 break;
451               case PAI_FLAGS_PAR_ODD:
452                 s = "even parity";
453                 break;
454             }
455             if (s != NULL) {
456                 syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
457                 syslog(LOG_WARNING, "All received characters had %s", s);
458             }
459         }
460     }
461 }
462
463 /*
464  * List of valid speeds.
465  */
466 struct speed {
467     int speed_int, speed_val;
468 } speeds[] = {
469 #ifdef B50
470     { 50, B50 },
471 #endif
472 #ifdef B75
473     { 75, B75 },
474 #endif
475 #ifdef B110
476     { 110, B110 },
477 #endif
478 #ifdef B134
479     { 134, B134 },
480 #endif
481 #ifdef B150
482     { 150, B150 },
483 #endif
484 #ifdef B200
485     { 200, B200 },
486 #endif
487 #ifdef B300
488     { 300, B300 },
489 #endif
490 #ifdef B600
491     { 600, B600 },
492 #endif
493 #ifdef B1200
494     { 1200, B1200 },
495 #endif
496 #ifdef B1800
497     { 1800, B1800 },
498 #endif
499 #ifdef B2000
500     { 2000, B2000 },
501 #endif
502 #ifdef B2400
503     { 2400, B2400 },
504 #endif
505 #ifdef B3600
506     { 3600, B3600 },
507 #endif
508 #ifdef B4800
509     { 4800, B4800 },
510 #endif
511 #ifdef B7200
512     { 7200, B7200 },
513 #endif
514 #ifdef B9600
515     { 9600, B9600 },
516 #endif
517 #ifdef B19200
518     { 19200, B19200 },
519 #endif
520 #ifdef B38400
521     { 38400, B38400 },
522 #endif
523 #ifdef EXTA
524     { 19200, EXTA },
525 #endif
526 #ifdef EXTB
527     { 38400, EXTB },
528 #endif
529 #ifdef B57600
530     { 57600, B57600 },
531 #endif
532 #ifdef B115200
533     { 115200, B115200 },
534 #endif
535     { 0, 0 }
536 };
537
538 /*
539  * Translate from bits/second to a speed_t.
540  */
541 static int
542 translate_speed(bps)
543     int bps;
544 {
545     struct speed *speedp;
546
547     if (bps == 0)
548         return 0;
549     for (speedp = speeds; speedp->speed_int; speedp++)
550         if (bps == speedp->speed_int)
551             return speedp->speed_val;
552     syslog(LOG_WARNING, "speed %d not supported", bps);
553     return 0;
554 }
555
556 /*
557  * Translate from a speed_t to bits/second.
558  */
559 static int
560 baud_rate_of(speed)
561     int speed;
562 {
563     struct speed *speedp;
564
565     if (speed == 0)
566         return 0;
567     for (speedp = speeds; speedp->speed_int; speedp++)
568         if (speed == speedp->speed_val)
569             return speedp->speed_int;
570     return 0;
571 }
572
573 /*
574  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
575  * at the requested speed, etc.  If `local' is true, set CLOCAL
576  * regardless of whether the modem option was specified.
577  */
578 void
579 set_up_tty(fd, local)
580     int fd, local;
581 {
582     int speed;
583     struct termios tios;
584
585     if (tcgetattr(fd, &tios) < 0) {
586         syslog(LOG_ERR, "tcgetattr: %m");
587         die(1);
588     }
589
590     if (!restore_term) {
591         inittermios = tios;
592         ioctl(fd, TIOCGWINSZ, &wsinfo);
593     }
594
595     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
596     if (crtscts > 0)
597         tios.c_cflag |= CRTSCTS;
598     else if (crtscts < 0)
599         tios.c_cflag &= ~CRTSCTS;
600
601     tios.c_cflag |= CS8 | CREAD | HUPCL;
602     if (local || !modem)
603         tios.c_cflag |= CLOCAL;
604     tios.c_iflag = IGNBRK | IGNPAR;
605     tios.c_oflag = 0;
606     tios.c_lflag = 0;
607     tios.c_cc[VMIN] = 1;
608     tios.c_cc[VTIME] = 0;
609
610     if (crtscts == -2) {
611         tios.c_iflag |= IXON | IXOFF;
612         tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
613         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
614     }
615
616     speed = translate_speed(inspeed);
617     if (speed) {
618         cfsetospeed(&tios, speed);
619         cfsetispeed(&tios, speed);
620     } else {
621         speed = cfgetospeed(&tios);
622         /*
623          * We can't proceed if the serial port speed is B0,
624          * since that implies that the serial port is disabled.
625          */
626         if (speed == B0) {
627             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
628                    devnam);
629             die(1);
630         }
631     }
632
633     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
634         syslog(LOG_ERR, "tcsetattr: %m");
635         die(1);
636     }
637
638     baud_rate = inspeed = baud_rate_of(speed);
639     restore_term = 1;
640 }
641
642 /*
643  * restore_tty - restore the terminal to the saved settings.
644  */
645 void
646 restore_tty(fd)
647     int fd;
648 {
649     if (restore_term) {
650         if (!default_device) {
651             /*
652              * Turn off echoing, because otherwise we can get into
653              * a loop with the tty and the modem echoing to each other.
654              * We presume we are the sole user of this tty device, so
655              * when we close it, it will revert to its defaults anyway.
656              */
657             inittermios.c_lflag &= ~(ECHO | ECHONL);
658         }
659         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
660             if (errno != ENXIO)
661                 syslog(LOG_WARNING, "tcsetattr: %m");
662         ioctl(fd, TIOCSWINSZ, &wsinfo);
663         restore_term = 0;
664     }
665 }
666
667 /*
668  * setdtr - control the DTR line on the serial port.
669  * This is called from die(), so it shouldn't call die().
670  */
671 void
672 setdtr(fd, on)
673 int fd, on;
674 {
675     int modembits = TIOCM_DTR;
676
677     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
678 }
679
680
681 /*
682  * output - Output PPP packet.
683  */
684 void
685 output(unit, p, len)
686     int unit;
687     u_char *p;
688     int len;
689 {
690     struct strbuf str;
691     int retries;
692     struct pollfd pfd;
693
694     if (debug)
695         log_packet(p, len, "sent ");
696
697     str.len = len;
698     str.buf = (caddr_t) p;
699     retries = 4;
700     while (putmsg(ttyfd, NULL, &str, 0) < 0) {
701         if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) {
702             if (errno != ENXIO)
703                 syslog(LOG_ERR, "Couldn't send packet: %m");
704             break;
705         }
706         pfd.fd = ttyfd;
707         pfd.events = POLLOUT;
708         poll(&pfd, 1, 250);     /* wait for up to 0.25 seconds */
709     }
710 }
711
712 /*
713  * wait_input - wait for input, for a length of time specified in *timo.
714  */
715 void
716 wait_input(timo)
717     struct timeval *timo;
718 {
719     int t;
720     struct pollfd pfd;
721
722     t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000;
723     pfd.fd = ttyfd;
724     pfd.events = POLLIN | POLLPRI | POLLHUP;
725     if (poll(&pfd, 1, t) < 0 && errno != EINTR) {
726         syslog(LOG_ERR, "poll: %m");
727         die(1);
728     }
729 }
730
731 /*
732  * read_packet - get a PPP packet from the serial device.
733  */
734 int
735 read_packet(buf)
736     u_char *buf;
737 {
738     struct strbuf str, ctl;
739     int len, i;
740     unsigned char ctlbuf[16];
741
742     str.maxlen = PPP_MTU + PPP_HDRLEN;
743     str.buf = (caddr_t) buf;
744     ctl.maxlen = sizeof(ctlbuf);
745     ctl.buf = (caddr_t) ctlbuf;
746     i = 0;
747     len = getmsg(ttyfd, &ctl, &str, &i);
748     if (len < 0) {
749         if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
750             return -1;
751         }
752         syslog(LOG_ERR, "getmsg %m");
753         die(1);
754     }
755     if (len) 
756         MAINDEBUG((LOG_DEBUG, "getmsg returned 0x%x",len));
757     if (ctl.len > 0)
758         syslog(LOG_NOTICE, "got ctrl msg len %d %x %x\n", ctl.len,
759                ctlbuf[0], ctlbuf[1]);
760
761     if (str.len < 0) {
762         MAINDEBUG((LOG_DEBUG, "getmsg short return length %d", str.len));
763         return -1;
764     }
765
766     return str.len;
767 }
768
769
770 /*
771  * ppp_send_config - configure the transmit characteristics of
772  * the ppp interface.
773  */
774 void
775 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
776     int unit, mtu;
777     u_int32_t asyncmap;
778     int pcomp, accomp;
779 {
780     char c;
781     struct ifreq ifr;
782
783     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
784     ifr.ifr_mtu = mtu;
785     if (ioctl(sockfd, (int)SIOCSIPMTU, (caddr_t) &ifr) < 0) {
786         syslog(LOG_ERR, "ioctl(SIOCSIPMTU): %m");
787         quit();
788     }
789
790     if(ioctl(ttyfd, (int)SIOCSIFASYNCMAP, (caddr_t) &asyncmap) < 0) {
791         syslog(LOG_ERR, "ioctl(SIOCSIFASYNCMAP): %m");
792         quit();
793     }
794
795     c = (pcomp? 1: 0);
796     if(ioctl(ttyfd, (int)SIOCSIFCOMPPROT, &c) < 0) {
797         syslog(LOG_ERR, "ioctl(SIOCSIFCOMPPROT): %m");
798         quit();
799     }
800
801     c = (accomp? 1: 0);
802     if(ioctl(ttyfd, (int)SIOCSIFCOMPAC, &c) < 0) {
803         syslog(LOG_ERR, "ioctl(SIOCSIFCOMPAC): %m");
804         quit();
805     }
806 }
807
808
809 /*
810  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
811  */
812 void
813 ppp_set_xaccm(unit, accm)
814     int unit;
815     ext_accm accm;
816 {
817     if (ioctl(ttyfd, (int)SIOCSIFXASYNCMAP, accm) < 0 && errno != ENOTTY)
818         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
819 }
820
821
822 /*
823  * ppp_recv_config - configure the receive-side characteristics of
824  * the ppp interface.
825  */
826 void
827 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
828     int unit, mru;
829     u_int32_t asyncmap;
830     int pcomp, accomp;
831 {
832     char c;
833
834     if (ioctl(ttyfd, (int)SIOCSIFMRU, &mru) < 0) {
835         syslog(LOG_ERR, "ioctl(SIOCSIFMRU): %m");
836     }
837
838     if (ioctl(ttyfd, (int)SIOCSIFRASYNCMAP, (caddr_t) &asyncmap) < 0) {
839         syslog(LOG_ERR, "ioctl(SIOCSIFRASYNCMAP): %m");
840     }
841
842     c = 2 + (pcomp? 1: 0);
843     if(ioctl(ttyfd, (int)SIOCSIFCOMPPROT, &c) < 0) {
844         syslog(LOG_ERR, "ioctl(SIOCSIFCOMPPROT): %m");
845     }
846
847     c = 2 + (accomp? 1: 0);
848     if (ioctl(ttyfd, (int)SIOCSIFCOMPAC, &c) < 0) {
849         syslog(LOG_ERR, "ioctl(SIOCSIFCOMPAC): %m");
850     }
851 }
852
853 /*
854  * ccp_test - ask kernel whether a given compression method
855  * is acceptable for use.
856  */
857 int
858 ccp_test(unit, opt_ptr, opt_len, for_transmit)
859     int unit, opt_len, for_transmit;
860     u_char *opt_ptr;
861 {
862     struct ppp_option_data data;
863
864     if ((unsigned) opt_len > MAX_PPP_OPTION)
865         opt_len = MAX_PPP_OPTION;
866     data.length = opt_len;
867     data.transmit = for_transmit;
868     BCOPY(opt_ptr, data.opt_data, opt_len);
869     if (ioctl(ttyfd, (int)SIOCSCOMPRESS, (caddr_t) &data) >= 0)
870         return 1;
871     return (errno == ENOSR)? 0: -1;
872 }
873
874 /*
875  * ccp_flags_set - inform kernel about the current state of CCP.
876  */
877 void
878 ccp_flags_set(unit, isopen, isup)
879     int unit, isopen, isup;
880 {
881     int x;
882
883     x = (isopen? 1: 0) + (isup? 2: 0);
884     if (ioctl(ttyfd, (int)SIOCSIFCOMP, (caddr_t) &x) < 0 && errno != ENOTTY)
885         syslog(LOG_ERR, "ioctl (SIOCSIFCOMP): %m");
886 }
887
888 /*
889  * ccp_fatal_error - returns 1 if decompression was disabled as a
890  * result of an error detected after decompression of a packet,
891  * 0 otherwise.  This is necessary because of patent nonsense.
892  */
893 int
894 ccp_fatal_error(unit)
895     int unit;
896 {
897     int x;
898
899     if (ioctl(ttyfd, (int)SIOCGIFCOMP, (caddr_t) &x) < 0) {
900         syslog(LOG_ERR, "ioctl(SIOCGIFCOMP): %m");
901         return 0;
902     }
903     return x & CCP_FATALERROR;
904 }
905
906 /*
907  * sifvjcomp - config tcp header compression
908  */
909 int
910 sifvjcomp(u, vjcomp, cidcomp, maxcid)
911     int u, vjcomp, cidcomp, maxcid;
912 {
913     char x;
914
915     x = (vjcomp? 1: 0) + (cidcomp? 0: 2) + (maxcid << 4);
916     if (ioctl(ttyfd, (int)SIOCSIFVJCOMP, (caddr_t) &x) < 0) {
917         syslog(LOG_ERR, "ioctl(SIOCSIFVJCOMP): %m");
918         return 0;
919     }
920     return 1;
921 }
922
923 /*
924  * sifup - Config the interface up and enable IP packets to pass.
925  */
926 int
927 sifup(u)
928     int u;
929 {
930     struct ifreq ifr;
931     struct npioctl npi;
932
933     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
934     if (ioctl(sockfd, (int)SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
935         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
936         return 0;
937     }
938     ifr.ifr_flags |= IFF_UP;
939     if (ioctl(sockfd, (int)SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
940         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
941         return 0;
942     }
943     if_is_up = 1;
944     npi.protocol = PPP_IP;
945     npi.mode = NPMODE_PASS;
946     if (ioctl(ttyfd, (int)SIOCSETNPMODE, &npi) < 0) {
947         if (errno != ENOTTY) {
948             syslog(LOG_ERR, "ioctl(SIOCSETNPMODE): %m");
949             return 0;
950         }
951     }
952     return 1;
953 }
954
955 /*
956  * sifdown - Config the interface down.
957  */
958 int
959 sifdown(u)
960     int u;
961 {
962     struct ifreq ifr;
963     int rv;
964     struct npioctl npi;
965
966     rv = 1;
967     npi.protocol = PPP_IP;
968     npi.mode = NPMODE_ERROR;
969     if (ioctl(ttyfd, (int)SIOCSETNPMODE, (caddr_t) &npi) < 0) {
970         if (errno != ENOTTY) {
971             syslog(LOG_ERR, "ioctl(SIOCSETNPMODE): %m");
972             rv = 0;
973         }
974     }
975
976     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
977     if (ioctl(sockfd, (int)SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
978         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
979         rv = 0;
980     } else {
981         ifr.ifr_flags &= ~IFF_UP;
982         if (ioctl(sockfd, (int)SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
983             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
984             rv = 0;
985         } else
986             if_is_up = 0;
987     }
988     return rv;
989 }
990
991 /*
992  * SET_SA_FAMILY - initialize a struct sockaddr, setting the sa_family field.
993  */
994 #define SET_SA_FAMILY(addr, family)             \
995     BZERO((char *) &(addr), sizeof(addr));      \
996     addr.sa_family = (family);
997
998 /*
999  * sifaddr - Config the interface IP addresses and netmask.
1000  */
1001 int
1002 sifaddr(u, o, h, m)
1003     int u;
1004     u_int32_t o, h, m;
1005 {
1006     int ret;
1007     struct ifreq ifr;
1008
1009     ret = 1;
1010     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1011     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
1012     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
1013     if (ioctl(sockfd, (int)SIOCSIFADDR, (caddr_t) &ifr) < 0) {
1014         syslog(LOG_ERR, "ioctl(SIOCSIFADDR): %m");
1015         ret = 0;
1016     }
1017     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = h;
1018     if (ioctl(sockfd, (int)SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
1019         syslog(LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m");
1020         ret = 0;
1021     }
1022     if (m != 0) {
1023         ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = m;
1024         syslog(LOG_INFO, "Setting interface mask to %s\n", ip_ntoa(m));
1025         if (ioctl(sockfd, (int)SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
1026             syslog(LOG_ERR, "ioctl(SIOCSIFNETMASK): %m");
1027             ret = 0;
1028         }
1029     }
1030
1031 /*  Reset if address --- This is stupid, but seems to be necessary...  */
1032
1033     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
1034     if (ioctl(sockfd, (int)SIOCSIFADDR, (caddr_t) &ifr) < 0) {
1035         syslog(LOG_ERR, "ioctl(SIOCSIFADDR): %m");
1036         ret = 0;
1037     }
1038
1039     return ret;
1040 }
1041
1042 /*
1043  * cifaddr - Clear the interface IP addresses, and delete routes
1044  * through the interface if possible.
1045  */
1046 int
1047 cifaddr(u, o, h)
1048     int u;
1049     u_int32_t o, h;
1050 {
1051     struct ortentry rt;
1052
1053     SET_SA_FAMILY(rt.rt_dst, AF_INET);
1054     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = h;
1055     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
1056     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = o;
1057     rt.rt_flags = RTF_HOST;
1058     if (ioctl(sockfd, (int)SIOCDELRT, (caddr_t) &rt) < 0) {
1059         syslog(LOG_ERR, "ioctl(SIOCDELRT): %m");
1060         return 0;
1061     }
1062     return 1;
1063 }
1064
1065 /*
1066  * sifdefaultroute - assign a default route through the address given.
1067  */
1068 int
1069 sifdefaultroute(u, g)
1070     int u;
1071     u_int32_t g;
1072 {
1073     struct ortentry rt;
1074
1075     SET_SA_FAMILY(rt.rt_dst, AF_INET);
1076     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
1077     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
1078     rt.rt_flags = RTF_GATEWAY;
1079     if (ioctl(sockfd, (int)SIOCADDRT, &rt) < 0) {
1080         syslog(LOG_ERR, "default route ioctl(SIOCADDRT): %m");
1081         return 0;
1082     }
1083     default_route_gateway = g;
1084     return 1;
1085 }
1086
1087 /*
1088  * cifdefaultroute - delete a default route through the address given.
1089  */
1090 int
1091 cifdefaultroute(u, g)
1092     int u;
1093     u_int32_t g;
1094 {
1095     struct ortentry rt;
1096
1097     SET_SA_FAMILY(rt.rt_dst, AF_INET);
1098     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
1099     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
1100     rt.rt_flags = RTF_GATEWAY;
1101     if (ioctl(sockfd, (int)SIOCDELRT, &rt) < 0) {
1102         syslog(LOG_ERR, "default route ioctl(SIOCDELRT): %m");
1103         return 0;
1104     }
1105     default_route_gateway = 0;
1106     return 1;
1107 }
1108
1109 /*
1110  * sifproxyarp - Make a proxy ARP entry for the peer.
1111  */
1112 int
1113 sifproxyarp(unit, hisaddr)
1114     int unit;
1115     u_int32_t hisaddr;
1116 {
1117     struct arpreq arpreq;
1118
1119     BZERO(&arpreq, sizeof(arpreq));
1120
1121     /*
1122      * Get the hardware address of an interface on the same subnet
1123      * as our local address.
1124      */
1125     if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
1126         syslog(LOG_WARNING, "Cannot determine ethernet address for proxy ARP");
1127         return 0;
1128     }
1129
1130     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1131     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1132     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1133     if (ioctl(sockfd, (int)SIOCSARP, (caddr_t)&arpreq) < 0) {
1134         syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
1135         return 0;
1136     }
1137
1138     proxy_arp_addr = hisaddr;
1139     return 1;
1140 }
1141
1142 /*
1143  * cifproxyarp - Delete the proxy ARP entry for the peer.
1144  */
1145 int
1146 cifproxyarp(unit, hisaddr)
1147     int unit;
1148     u_int32_t hisaddr;
1149 {
1150     struct arpreq arpreq;
1151
1152     BZERO(&arpreq, sizeof(arpreq));
1153     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1154     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1155     if (ioctl(sockfd, (int)SIOCDARP, (caddr_t)&arpreq) < 0) {
1156         syslog(LOG_ERR, "ioctl(SIOCDARP): %m");
1157         return 0;
1158     }
1159     proxy_arp_addr = 0;
1160     return 1;
1161 }
1162
1163 /*
1164  * get_ether_addr - get the hardware address of an interface on the
1165  * the same subnet as ipaddr.
1166  */
1167 #define MAX_IFS         32
1168
1169 int s;
1170
1171 static int
1172 get_ether_addr(ipaddr, hwaddr)
1173     u_int ipaddr;
1174     struct sockaddr *hwaddr;
1175 {
1176     struct ifreq *ifr, *ifend, *ifp;
1177     u_int ina, mask;
1178     struct sockaddr_dl *dla;
1179     struct ifreq ifreq;
1180     struct ifconf ifc;
1181     struct ifreq ifs[MAX_IFS];
1182     struct ifdevea ifdevreq;
1183
1184     ifc.ifc_len = sizeof(ifs);
1185     ifc.ifc_req = ifs;
1186     if (ioctl(sockfd, (int)SIOCGIFCONF, &ifc) < 0) {
1187         perror("ioctl(SIOCGIFCONF)");
1188         return 0;
1189     }
1190
1191     /*
1192      * Scan through looking for an interface with an Internet
1193      * address on the same subnet as `ipaddr'.
1194      */
1195     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1196     for (ifr = ifc.ifc_req; ifr < ifend; ) {
1197         if (ifr->ifr_addr.sa_family == AF_INET) {
1198             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1199             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1200             /*
1201              * Check that the interface is up, and not point-to-point
1202              * or loopback.
1203              */
1204             if (ioctl(sockfd, (int)SIOCGIFFLAGS, &ifreq) < 0)
1205                 continue;
1206             if ((ifreq.ifr_flags &
1207                  (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1208                  != (IFF_UP|IFF_BROADCAST))
1209                 continue;
1210             /*
1211              * Get its netmask and check that it's on the right subnet.
1212              */
1213             if (ioctl(sockfd, (int)SIOCGIFNETMASK, &ifreq) < 0)
1214                 continue;
1215             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1216             if ((ipaddr & mask) != (ina & mask))
1217                 continue;
1218
1219             break;
1220         }
1221         ifr++;
1222     }
1223
1224     if (ifr >= ifend)
1225         return 0;
1226     syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
1227
1228     strncpy(ifdevreq.ifr_name, ifr->ifr_name, sizeof(ifdevreq.ifr_name));
1229
1230     if (ioctl(sockfd, (int)SIOCRPHYSADDR, &ifdevreq) < 0) {
1231         perror("ioctl(SIOCRPHYSADDR)");
1232         return(0);
1233     }
1234
1235     hwaddr->sa_family = AF_UNSPEC;
1236     memcpy(hwaddr->sa_data, ifdevreq.current_pa, sizeof(ifdevreq.current_pa));
1237     return(1);
1238 }
1239
1240
1241 /*
1242  * Return user specified netmask, modified by any mask we might determine
1243  * for address `addr' (in network byte order).
1244  * Here we scan through the system's list of interfaces, looking for
1245  * any non-point-to-point interfaces which might appear to be on the same
1246  * network as `addr'.  If we find any, we OR in their netmask to the
1247  * user-specified netmask.
1248  */
1249 u_int32_t
1250 GetMask(addr)
1251     u_int32_t addr;
1252 {
1253     u_int32_t mask, nmask, ina;
1254     struct ifreq *ifr, *ifend, ifreq;
1255     struct ifconf ifc;
1256     struct ifreq ifs[MAX_IFS];
1257
1258     addr = ntohl(addr);
1259     if (IN_CLASSA(addr))        /* determine network mask for address class */
1260         nmask = IN_CLASSA_NET;
1261     else if (IN_CLASSB(addr))
1262         nmask = IN_CLASSB_NET;
1263     else
1264         nmask = IN_CLASSC_NET;
1265     /* class D nets are disallowed by bad_ip_adrs */
1266     mask = netmask | htonl(nmask);
1267
1268     /*
1269      * Scan through the system's network interfaces.
1270      */
1271     ifc.ifc_len = sizeof(ifs);
1272     ifc.ifc_req = ifs;
1273     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1274         syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1275         return mask;
1276     }
1277     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1278     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
1279         /*
1280          * Check the interface's internet address.
1281          */
1282         if (ifr->ifr_addr.sa_family != AF_INET)
1283             continue;
1284         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1285         if ((ntohl(ina) & nmask) != (addr & nmask))
1286             continue;
1287         /*
1288          * Check that the interface is up, and not point-to-point or loopback.
1289          */
1290         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1291         if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1292             continue;
1293         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1294             != IFF_UP)
1295             continue;
1296         /*
1297          * Get its netmask and OR it into our mask.
1298          */
1299         if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1300             continue;
1301         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1302     }
1303
1304     return mask;
1305 }
1306
1307
1308 #define WTMPFILE        "/usr/adm/wtmp"
1309 #include <sys/stat.h>
1310
1311 void
1312 logwtmp(line, name, host)
1313     char *line, *name, *host;
1314 {
1315     int fd;
1316     struct stat buf;
1317     struct utmp ut;
1318
1319     if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
1320         return;
1321     if (!fstat(fd, &buf)) {
1322         (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1323         (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1324         (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1325         (void)time(&ut.ut_time);
1326         if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp))
1327             (void)ftruncate(fd, buf.st_size);
1328     }
1329     close(fd);
1330 }
1331
1332 /*
1333  * Code for locking/unlocking the serial device.
1334  * This code is derived from chat.c.
1335  */
1336
1337 #ifndef LOCK_DIR
1338 #  ifdef HDB
1339 #   define      PIDSTRING
1340 #   define      LOCK_PREFIX     "/usr/spool/locks/LCK.."
1341 #  else /* HDB */
1342 #   define      LOCK_PREFIX     "/usr/spool/uucp/LCK.."
1343 #  endif /* HDB */
1344 #endif /* LOCK_DIR */
1345
1346 static char *lock_file;
1347
1348 /*
1349  * lock - create a lock file for the named device
1350  */
1351 int
1352 lock(dev)
1353     char *dev;
1354 {
1355     char hdb_lock_buffer[12];
1356     int fd, pid, n;
1357     char *p;
1358
1359     if ((p = strrchr(dev, '/')) != NULL)
1360         dev = p + 1;
1361     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1362     if (lock_file == NULL)
1363         novm("lock file name");
1364     strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1365
1366     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1367         if (errno == EEXIST
1368             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1369             /* Read the lock file to find out who has the device locked */
1370 #ifdef PIDSTRING
1371             n = read(fd, hdb_lock_buffer, 11);
1372             if (n > 0) {
1373                 hdb_lock_buffer[n] = 0;
1374                 pid = atoi(hdb_lock_buffer);
1375             }
1376 #else
1377             n = read(fd, &pid, sizeof(pid));
1378 #endif
1379             if (n <= 0) {
1380                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1381                 close(fd);
1382             } else {
1383                 if (kill(pid, 0) == -1 && errno == ESRCH) {
1384                     /* pid no longer exists - remove the lock file */
1385                     if (unlink(lock_file) == 0) {
1386                         close(fd);
1387                         syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1388                                dev, pid);
1389                         continue;
1390                     } else
1391                         syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1392                                dev);
1393                 } else
1394                     syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1395                            dev, pid);
1396             }
1397             close(fd);
1398         } else
1399             syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1400         free(lock_file);
1401         lock_file = NULL;
1402         return -1;
1403     }
1404
1405 # ifdef PIDSTRING
1406     sprintf(hdb_lock_buffer, "%10d\n", getpid());
1407     write(fd, hdb_lock_buffer, 11);
1408 # else
1409     pid = getpid();
1410     write(fd, &pid, sizeof pid);
1411 # endif
1412
1413     close(fd);
1414     return 0;
1415 }
1416
1417 /*
1418  * unlock - remove our lockfile
1419  */
1420 void
1421 unlock()
1422 {
1423     if (lock_file) {
1424         unlink(lock_file);
1425         free(lock_file);
1426         lock_file = NULL;
1427     }
1428 }
1429