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