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