17c478bd9Sstevel@tonic-gate /* 2*94e1761eSsn199410 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 58d489c7aSmuffin 67c478bd9Sstevel@tonic-gate /* 77c478bd9Sstevel@tonic-gate * Copyright (c) 1983 Regents of the University of California. 87c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 97c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 107c478bd9Sstevel@tonic-gate */ 118d489c7aSmuffin 128d489c7aSmuffin #pragma ident "%Z%%M% %I% %E% SMI" 138d489c7aSmuffin 147c478bd9Sstevel@tonic-gate /* 157c478bd9Sstevel@tonic-gate * defs that come from uucp.h 167c478bd9Sstevel@tonic-gate */ 177c478bd9Sstevel@tonic-gate #define NAMESIZE 40 187c478bd9Sstevel@tonic-gate #define FAIL -1 197c478bd9Sstevel@tonic-gate #define SAME 0 207c478bd9Sstevel@tonic-gate #define SLCKTIME (8*60*60) /* device timeout (LCK.. files) in seconds */ 217c478bd9Sstevel@tonic-gate #ifdef __STDC__ 227c478bd9Sstevel@tonic-gate #define ASSERT(e, f, v) if (!(e)) {\ 238d489c7aSmuffin (void) fprintf(stderr, "AERROR - (%s) ", #e); \ 248d489c7aSmuffin (void) fprintf(stderr, f, v); \ 257c478bd9Sstevel@tonic-gate finish(FAIL); \ 267c478bd9Sstevel@tonic-gate } 277c478bd9Sstevel@tonic-gate #else 287c478bd9Sstevel@tonic-gate #define ASSERT(e, f, v) if (!(e)) {\ 298d489c7aSmuffin (void) fprintf(stderr, "AERROR - (%s) ", "e"); \ 308d489c7aSmuffin (void) fprintf(stderr, f, v); \ 317c478bd9Sstevel@tonic-gate finish(FAIL); \ 327c478bd9Sstevel@tonic-gate } 337c478bd9Sstevel@tonic-gate #endif 347c478bd9Sstevel@tonic-gate #define SIZEOFPID 10 /* maximum number of digits in a pid */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #define LOCKDIR "/var/spool/locks" 377c478bd9Sstevel@tonic-gate #define LOCKPRE "LK" 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate /* 407c478bd9Sstevel@tonic-gate * This code is taken almost directly from uucp and follows the same 417c478bd9Sstevel@tonic-gate * conventions. This is important since uucp and tip should 427c478bd9Sstevel@tonic-gate * respect each others locks. 437c478bd9Sstevel@tonic-gate */ 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #include <sys/types.h> 467c478bd9Sstevel@tonic-gate #include <sys/stat.h> 477c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 487c478bd9Sstevel@tonic-gate #include <stdio.h> 497c478bd9Sstevel@tonic-gate #include <errno.h> 507c478bd9Sstevel@tonic-gate #include <string.h> 518d489c7aSmuffin #include <stdlib.h> 528d489c7aSmuffin #include <time.h> 538d489c7aSmuffin #include <unistd.h> 548d489c7aSmuffin #include <fcntl.h> 558d489c7aSmuffin #include <signal.h> 568d489c7aSmuffin #include <utime.h> 577c478bd9Sstevel@tonic-gate 588d489c7aSmuffin static void stlock(char *); 598d489c7aSmuffin static int onelock(char *, char *, char *); 608d489c7aSmuffin static int checkLock(char *); 617c478bd9Sstevel@tonic-gate 628d489c7aSmuffin extern void finish(int); 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate /* 657c478bd9Sstevel@tonic-gate * ulockf(file, atime) 667c478bd9Sstevel@tonic-gate * char *file; 677c478bd9Sstevel@tonic-gate * time_t atime; 687c478bd9Sstevel@tonic-gate * 697c478bd9Sstevel@tonic-gate * ulockf - this routine will create a lock file (file). 707c478bd9Sstevel@tonic-gate * If one already exists, send a signal 0 to the process--if 717c478bd9Sstevel@tonic-gate * it fails, then unlink it and make a new one. 727c478bd9Sstevel@tonic-gate * 737c478bd9Sstevel@tonic-gate * input: 747c478bd9Sstevel@tonic-gate * file - name of the lock file 757c478bd9Sstevel@tonic-gate * atime - is unused, but we keep it for lint compatibility 767c478bd9Sstevel@tonic-gate * with non-ATTSVKILL 777c478bd9Sstevel@tonic-gate * 787c478bd9Sstevel@tonic-gate * return codes: 0 | FAIL 797c478bd9Sstevel@tonic-gate */ 808d489c7aSmuffin /* ARGSUSED */ 818d489c7aSmuffin static int 828d489c7aSmuffin ulockf(char *file, time_t atime) 837c478bd9Sstevel@tonic-gate { 847c478bd9Sstevel@tonic-gate static char pid[SIZEOFPID+2] = { '\0' }; /* +2 for '\n' and NULL */ 857c478bd9Sstevel@tonic-gate static char tempfile[NAMESIZE]; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate if (pid[0] == '\0') { 88*94e1761eSsn199410 (void) snprintf(pid, sizeof (pid), "%*d\n", SIZEOFPID, 89*94e1761eSsn199410 (int)getpid()); 908d489c7aSmuffin (void) snprintf(tempfile, sizeof (tempfile), 918d489c7aSmuffin "%s/LTMP.%d", LOCKDIR, getpid()); 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate if (onelock(pid, tempfile, file) == -1) { 947c478bd9Sstevel@tonic-gate /* lock file exists */ 957c478bd9Sstevel@tonic-gate (void) unlink(tempfile); 967c478bd9Sstevel@tonic-gate if (checkLock(file)) 977c478bd9Sstevel@tonic-gate return (FAIL); 987c478bd9Sstevel@tonic-gate else { 997c478bd9Sstevel@tonic-gate if (onelock(pid, tempfile, file)) { 1007c478bd9Sstevel@tonic-gate (void) unlink(tempfile); 1017c478bd9Sstevel@tonic-gate return (FAIL); 1027c478bd9Sstevel@tonic-gate } 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate } 1057c478bd9Sstevel@tonic-gate stlock(file); 1067c478bd9Sstevel@tonic-gate return (0); 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate /* 1107c478bd9Sstevel@tonic-gate * check to see if the lock file exists and is still active 1117c478bd9Sstevel@tonic-gate * - use kill(pid, 0) - (this only works on ATTSV and some hacked 1127c478bd9Sstevel@tonic-gate * BSD systems at this time) 1137c478bd9Sstevel@tonic-gate * return: 1147c478bd9Sstevel@tonic-gate * 0 -> success (lock file removed - no longer active) 1157c478bd9Sstevel@tonic-gate * FAIL -> lock file still active 1167c478bd9Sstevel@tonic-gate */ 1177c478bd9Sstevel@tonic-gate static int 1188d489c7aSmuffin checkLock(char *file) 1197c478bd9Sstevel@tonic-gate { 1208d489c7aSmuffin int ret; 1217c478bd9Sstevel@tonic-gate int lpid = -1; 1227c478bd9Sstevel@tonic-gate char alpid[SIZEOFPID+2]; /* +2 for '\n' and NULL */ 1237c478bd9Sstevel@tonic-gate int fd; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate fd = open(file, 0); 1267c478bd9Sstevel@tonic-gate if (fd == -1) { 1277c478bd9Sstevel@tonic-gate if (errno == ENOENT) /* file does not exist -- OK */ 1287c478bd9Sstevel@tonic-gate return (0); 1297c478bd9Sstevel@tonic-gate goto unlk; 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate ret = read(fd, (char *)alpid, SIZEOFPID+1); /* +1 for '\n' */ 1327c478bd9Sstevel@tonic-gate (void) close(fd); 1337c478bd9Sstevel@tonic-gate if (ret != (SIZEOFPID+1)) 1347c478bd9Sstevel@tonic-gate goto unlk; 1357c478bd9Sstevel@tonic-gate lpid = atoi(alpid); 1367c478bd9Sstevel@tonic-gate if ((ret = kill(lpid, 0)) == 0 || errno == EPERM) 1377c478bd9Sstevel@tonic-gate return (FAIL); 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate unlk: 1407c478bd9Sstevel@tonic-gate if (unlink(file) != 0) 1417c478bd9Sstevel@tonic-gate return (FAIL); 1427c478bd9Sstevel@tonic-gate return (0); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate #define MAXLOCKS 10 /* maximum number of lock files */ 1467c478bd9Sstevel@tonic-gate char *Lockfile[MAXLOCKS]; 1477c478bd9Sstevel@tonic-gate int Nlocks = 0; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* 1507c478bd9Sstevel@tonic-gate * stlock(name) put name in list of lock files 1517c478bd9Sstevel@tonic-gate * char *name; 1527c478bd9Sstevel@tonic-gate * 1537c478bd9Sstevel@tonic-gate * return codes: none 1547c478bd9Sstevel@tonic-gate */ 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate static void 1578d489c7aSmuffin stlock(char *name) 1587c478bd9Sstevel@tonic-gate { 1597c478bd9Sstevel@tonic-gate char *p; 1607c478bd9Sstevel@tonic-gate int i; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate for (i = 0; i < Nlocks; i++) { 1637c478bd9Sstevel@tonic-gate if (Lockfile[i] == NULL) 1647c478bd9Sstevel@tonic-gate break; 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate ASSERT(i < MAXLOCKS, "TOO MANY LOCKS %d", i); 1677c478bd9Sstevel@tonic-gate if (i >= Nlocks) 1687c478bd9Sstevel@tonic-gate i = Nlocks++; 1697c478bd9Sstevel@tonic-gate p = calloc(strlen(name) + 1, sizeof (char)); 1707c478bd9Sstevel@tonic-gate ASSERT(p != NULL, "CAN NOT ALLOCATE FOR %s", name); 1718d489c7aSmuffin (void) strcpy(p, name); 1727c478bd9Sstevel@tonic-gate Lockfile[i] = p; 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * rmlock(name) remove all lock files in list 1777c478bd9Sstevel@tonic-gate * char *name; or name 1787c478bd9Sstevel@tonic-gate * 1797c478bd9Sstevel@tonic-gate * return codes: none 1807c478bd9Sstevel@tonic-gate */ 1817c478bd9Sstevel@tonic-gate 1828d489c7aSmuffin static void 1838d489c7aSmuffin rmlock(char *name) 1847c478bd9Sstevel@tonic-gate { 1857c478bd9Sstevel@tonic-gate int i; 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate for (i = 0; i < Nlocks; i++) { 1887c478bd9Sstevel@tonic-gate if (Lockfile[i] == NULL) 1897c478bd9Sstevel@tonic-gate continue; 1907c478bd9Sstevel@tonic-gate if (name == NULL || strcmp(name, Lockfile[i]) == SAME) { 1918d489c7aSmuffin (void) unlink(Lockfile[i]); 1927c478bd9Sstevel@tonic-gate free(Lockfile[i]); 1937c478bd9Sstevel@tonic-gate Lockfile[i] = NULL; 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1988d489c7aSmuffin static int 1998d489c7aSmuffin onelock(char *pid, char *tempfile, char *name) 2007c478bd9Sstevel@tonic-gate { 2017c478bd9Sstevel@tonic-gate int fd; 2027c478bd9Sstevel@tonic-gate static int first = 1; 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate fd = creat(tempfile, 0444); 2057c478bd9Sstevel@tonic-gate if (fd < 0) { 2067c478bd9Sstevel@tonic-gate if (first) { 2077c478bd9Sstevel@tonic-gate if (errno == EACCES) { 2088d489c7aSmuffin (void) fprintf(stderr, 2097c478bd9Sstevel@tonic-gate "tip: can't create files in lock file directory %s\n", 2107c478bd9Sstevel@tonic-gate LOCKDIR); 2117c478bd9Sstevel@tonic-gate } else if (access(LOCKDIR, 0) < 0) { 2128d489c7aSmuffin (void) fprintf(stderr, 2138d489c7aSmuffin "tip: lock file directory %s: ", 2147c478bd9Sstevel@tonic-gate LOCKDIR); 2157c478bd9Sstevel@tonic-gate perror(""); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate first = 0; 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate if (errno == EMFILE || errno == ENFILE) 2207c478bd9Sstevel@tonic-gate (void) unlink(tempfile); 2217c478bd9Sstevel@tonic-gate return (-1); 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate /* +1 for '\n' */ 2247c478bd9Sstevel@tonic-gate if (write(fd, pid, SIZEOFPID+1) != (SIZEOFPID+1)) { 2258d489c7aSmuffin (void) fprintf(stderr, 2267c478bd9Sstevel@tonic-gate "tip: can't write to files in lock file directory %s: %s\n", 2277c478bd9Sstevel@tonic-gate LOCKDIR, strerror(errno)); 2287c478bd9Sstevel@tonic-gate (void) unlink(tempfile); 2297c478bd9Sstevel@tonic-gate return (-1); 2307c478bd9Sstevel@tonic-gate } 2318d489c7aSmuffin (void) fchmod(fd, 0444); 2328d489c7aSmuffin (void) close(fd); 2337c478bd9Sstevel@tonic-gate if (link(tempfile, name) < 0) { 2348d489c7aSmuffin (void) unlink(tempfile); 2357c478bd9Sstevel@tonic-gate return (-1); 2367c478bd9Sstevel@tonic-gate } 2378d489c7aSmuffin (void) unlink(tempfile); 2387c478bd9Sstevel@tonic-gate return (0); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* 2427c478bd9Sstevel@tonic-gate * delock(sys) remove a lock file 2437c478bd9Sstevel@tonic-gate * char *sys; 2447c478bd9Sstevel@tonic-gate */ 2457c478bd9Sstevel@tonic-gate 2468d489c7aSmuffin void 2478d489c7aSmuffin delock(char *sys) 2487c478bd9Sstevel@tonic-gate { 2497c478bd9Sstevel@tonic-gate struct stat sb; 2507c478bd9Sstevel@tonic-gate char lname[NAMESIZE]; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate if (stat(sys, &sb) < 0) 2538d489c7aSmuffin return; 2548d489c7aSmuffin (void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu", 2558d489c7aSmuffin LOCKDIR, LOCKPRE, 2567c478bd9Sstevel@tonic-gate (unsigned long)major(sb.st_dev), 2577c478bd9Sstevel@tonic-gate (unsigned long)major(sb.st_rdev), 2587c478bd9Sstevel@tonic-gate (unsigned long)minor(sb.st_rdev)); 2597c478bd9Sstevel@tonic-gate rmlock(lname); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* 2638d489c7aSmuffin * tip_mlock(sys) create system lock 2647c478bd9Sstevel@tonic-gate * char *sys; 2657c478bd9Sstevel@tonic-gate * 2667c478bd9Sstevel@tonic-gate * return codes: 0 | FAIL 2677c478bd9Sstevel@tonic-gate */ 2687c478bd9Sstevel@tonic-gate 2698d489c7aSmuffin int 2708d489c7aSmuffin tip_mlock(char *sys) 2717c478bd9Sstevel@tonic-gate { 2727c478bd9Sstevel@tonic-gate struct stat sb; 2737c478bd9Sstevel@tonic-gate char lname[NAMESIZE]; 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate if (stat(sys, &sb) < 0) 2767c478bd9Sstevel@tonic-gate return (FAIL); 2778d489c7aSmuffin (void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu", 2788d489c7aSmuffin LOCKDIR, LOCKPRE, 2797c478bd9Sstevel@tonic-gate (unsigned long)major(sb.st_dev), 2807c478bd9Sstevel@tonic-gate (unsigned long)major(sb.st_rdev), 2817c478bd9Sstevel@tonic-gate (unsigned long)minor(sb.st_rdev)); 2827c478bd9Sstevel@tonic-gate return (ulockf(lname, (time_t)SLCKTIME) < 0 ? FAIL : 0); 2837c478bd9Sstevel@tonic-gate } 284