17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 5*8d489c7aSmuffin 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 */ 11*8d489c7aSmuffin 12*8d489c7aSmuffin #pragma ident "%Z%%M% %I% %E% SMI" 13*8d489c7aSmuffin 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)) {\ 23*8d489c7aSmuffin (void) fprintf(stderr, "AERROR - (%s) ", #e); \ 24*8d489c7aSmuffin (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)) {\ 29*8d489c7aSmuffin (void) fprintf(stderr, "AERROR - (%s) ", "e"); \ 30*8d489c7aSmuffin (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> 51*8d489c7aSmuffin #include <stdlib.h> 52*8d489c7aSmuffin #include <time.h> 53*8d489c7aSmuffin #include <unistd.h> 54*8d489c7aSmuffin #include <fcntl.h> 55*8d489c7aSmuffin #include <signal.h> 56*8d489c7aSmuffin #include <utime.h> 577c478bd9Sstevel@tonic-gate 58*8d489c7aSmuffin static void stlock(char *); 59*8d489c7aSmuffin static int onelock(char *, char *, char *); 60*8d489c7aSmuffin static int checkLock(char *); 617c478bd9Sstevel@tonic-gate 62*8d489c7aSmuffin 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 */ 80*8d489c7aSmuffin /* ARGSUSED */ 81*8d489c7aSmuffin static int 82*8d489c7aSmuffin 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*8d489c7aSmuffin (void) sprintf(pid, "%*d\n", SIZEOFPID, (int)getpid()); 89*8d489c7aSmuffin (void) snprintf(tempfile, sizeof (tempfile), 90*8d489c7aSmuffin "%s/LTMP.%d", LOCKDIR, getpid()); 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate if (onelock(pid, tempfile, file) == -1) { 937c478bd9Sstevel@tonic-gate /* lock file exists */ 947c478bd9Sstevel@tonic-gate (void) unlink(tempfile); 957c478bd9Sstevel@tonic-gate if (checkLock(file)) 967c478bd9Sstevel@tonic-gate return (FAIL); 977c478bd9Sstevel@tonic-gate else { 987c478bd9Sstevel@tonic-gate if (onelock(pid, tempfile, file)) { 997c478bd9Sstevel@tonic-gate (void) unlink(tempfile); 1007c478bd9Sstevel@tonic-gate return (FAIL); 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate } 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate stlock(file); 1057c478bd9Sstevel@tonic-gate return (0); 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate /* 1097c478bd9Sstevel@tonic-gate * check to see if the lock file exists and is still active 1107c478bd9Sstevel@tonic-gate * - use kill(pid, 0) - (this only works on ATTSV and some hacked 1117c478bd9Sstevel@tonic-gate * BSD systems at this time) 1127c478bd9Sstevel@tonic-gate * return: 1137c478bd9Sstevel@tonic-gate * 0 -> success (lock file removed - no longer active) 1147c478bd9Sstevel@tonic-gate * FAIL -> lock file still active 1157c478bd9Sstevel@tonic-gate */ 1167c478bd9Sstevel@tonic-gate static int 117*8d489c7aSmuffin checkLock(char *file) 1187c478bd9Sstevel@tonic-gate { 119*8d489c7aSmuffin int ret; 1207c478bd9Sstevel@tonic-gate int lpid = -1; 1217c478bd9Sstevel@tonic-gate char alpid[SIZEOFPID+2]; /* +2 for '\n' and NULL */ 1227c478bd9Sstevel@tonic-gate int fd; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate fd = open(file, 0); 1257c478bd9Sstevel@tonic-gate if (fd == -1) { 1267c478bd9Sstevel@tonic-gate if (errno == ENOENT) /* file does not exist -- OK */ 1277c478bd9Sstevel@tonic-gate return (0); 1287c478bd9Sstevel@tonic-gate goto unlk; 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate ret = read(fd, (char *)alpid, SIZEOFPID+1); /* +1 for '\n' */ 1317c478bd9Sstevel@tonic-gate (void) close(fd); 1327c478bd9Sstevel@tonic-gate if (ret != (SIZEOFPID+1)) 1337c478bd9Sstevel@tonic-gate goto unlk; 1347c478bd9Sstevel@tonic-gate lpid = atoi(alpid); 1357c478bd9Sstevel@tonic-gate if ((ret = kill(lpid, 0)) == 0 || errno == EPERM) 1367c478bd9Sstevel@tonic-gate return (FAIL); 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate unlk: 1397c478bd9Sstevel@tonic-gate if (unlink(file) != 0) 1407c478bd9Sstevel@tonic-gate return (FAIL); 1417c478bd9Sstevel@tonic-gate return (0); 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate #define MAXLOCKS 10 /* maximum number of lock files */ 1457c478bd9Sstevel@tonic-gate char *Lockfile[MAXLOCKS]; 1467c478bd9Sstevel@tonic-gate int Nlocks = 0; 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /* 1497c478bd9Sstevel@tonic-gate * stlock(name) put name in list of lock files 1507c478bd9Sstevel@tonic-gate * char *name; 1517c478bd9Sstevel@tonic-gate * 1527c478bd9Sstevel@tonic-gate * return codes: none 1537c478bd9Sstevel@tonic-gate */ 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate static void 156*8d489c7aSmuffin stlock(char *name) 1577c478bd9Sstevel@tonic-gate { 1587c478bd9Sstevel@tonic-gate char *p; 1597c478bd9Sstevel@tonic-gate int i; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate for (i = 0; i < Nlocks; i++) { 1627c478bd9Sstevel@tonic-gate if (Lockfile[i] == NULL) 1637c478bd9Sstevel@tonic-gate break; 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate ASSERT(i < MAXLOCKS, "TOO MANY LOCKS %d", i); 1667c478bd9Sstevel@tonic-gate if (i >= Nlocks) 1677c478bd9Sstevel@tonic-gate i = Nlocks++; 1687c478bd9Sstevel@tonic-gate p = calloc(strlen(name) + 1, sizeof (char)); 1697c478bd9Sstevel@tonic-gate ASSERT(p != NULL, "CAN NOT ALLOCATE FOR %s", name); 170*8d489c7aSmuffin (void) strcpy(p, name); 1717c478bd9Sstevel@tonic-gate Lockfile[i] = p; 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate /* 1757c478bd9Sstevel@tonic-gate * rmlock(name) remove all lock files in list 1767c478bd9Sstevel@tonic-gate * char *name; or name 1777c478bd9Sstevel@tonic-gate * 1787c478bd9Sstevel@tonic-gate * return codes: none 1797c478bd9Sstevel@tonic-gate */ 1807c478bd9Sstevel@tonic-gate 181*8d489c7aSmuffin static void 182*8d489c7aSmuffin rmlock(char *name) 1837c478bd9Sstevel@tonic-gate { 1847c478bd9Sstevel@tonic-gate int i; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate for (i = 0; i < Nlocks; i++) { 1877c478bd9Sstevel@tonic-gate if (Lockfile[i] == NULL) 1887c478bd9Sstevel@tonic-gate continue; 1897c478bd9Sstevel@tonic-gate if (name == NULL || strcmp(name, Lockfile[i]) == SAME) { 190*8d489c7aSmuffin (void) unlink(Lockfile[i]); 1917c478bd9Sstevel@tonic-gate free(Lockfile[i]); 1927c478bd9Sstevel@tonic-gate Lockfile[i] = NULL; 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate 197*8d489c7aSmuffin static int 198*8d489c7aSmuffin onelock(char *pid, char *tempfile, char *name) 1997c478bd9Sstevel@tonic-gate { 2007c478bd9Sstevel@tonic-gate int fd; 2017c478bd9Sstevel@tonic-gate static int first = 1; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate fd = creat(tempfile, 0444); 2047c478bd9Sstevel@tonic-gate if (fd < 0) { 2057c478bd9Sstevel@tonic-gate if (first) { 2067c478bd9Sstevel@tonic-gate if (errno == EACCES) { 207*8d489c7aSmuffin (void) fprintf(stderr, 2087c478bd9Sstevel@tonic-gate "tip: can't create files in lock file directory %s\n", 2097c478bd9Sstevel@tonic-gate LOCKDIR); 2107c478bd9Sstevel@tonic-gate } else if (access(LOCKDIR, 0) < 0) { 211*8d489c7aSmuffin (void) fprintf(stderr, 212*8d489c7aSmuffin "tip: lock file directory %s: ", 2137c478bd9Sstevel@tonic-gate LOCKDIR); 2147c478bd9Sstevel@tonic-gate perror(""); 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate first = 0; 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate if (errno == EMFILE || errno == ENFILE) 2197c478bd9Sstevel@tonic-gate (void) unlink(tempfile); 2207c478bd9Sstevel@tonic-gate return (-1); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate /* +1 for '\n' */ 2237c478bd9Sstevel@tonic-gate if (write(fd, pid, SIZEOFPID+1) != (SIZEOFPID+1)) { 224*8d489c7aSmuffin (void) fprintf(stderr, 2257c478bd9Sstevel@tonic-gate "tip: can't write to files in lock file directory %s: %s\n", 2267c478bd9Sstevel@tonic-gate LOCKDIR, strerror(errno)); 2277c478bd9Sstevel@tonic-gate (void) unlink(tempfile); 2287c478bd9Sstevel@tonic-gate return (-1); 2297c478bd9Sstevel@tonic-gate } 230*8d489c7aSmuffin (void) fchmod(fd, 0444); 231*8d489c7aSmuffin (void) close(fd); 2327c478bd9Sstevel@tonic-gate if (link(tempfile, name) < 0) { 233*8d489c7aSmuffin (void) unlink(tempfile); 2347c478bd9Sstevel@tonic-gate return (-1); 2357c478bd9Sstevel@tonic-gate } 236*8d489c7aSmuffin (void) unlink(tempfile); 2377c478bd9Sstevel@tonic-gate return (0); 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* 2417c478bd9Sstevel@tonic-gate * delock(sys) remove a lock file 2427c478bd9Sstevel@tonic-gate * char *sys; 2437c478bd9Sstevel@tonic-gate */ 2447c478bd9Sstevel@tonic-gate 245*8d489c7aSmuffin void 246*8d489c7aSmuffin delock(char *sys) 2477c478bd9Sstevel@tonic-gate { 2487c478bd9Sstevel@tonic-gate struct stat sb; 2497c478bd9Sstevel@tonic-gate char lname[NAMESIZE]; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate if (stat(sys, &sb) < 0) 252*8d489c7aSmuffin return; 253*8d489c7aSmuffin (void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu", 254*8d489c7aSmuffin LOCKDIR, LOCKPRE, 2557c478bd9Sstevel@tonic-gate (unsigned long)major(sb.st_dev), 2567c478bd9Sstevel@tonic-gate (unsigned long)major(sb.st_rdev), 2577c478bd9Sstevel@tonic-gate (unsigned long)minor(sb.st_rdev)); 2587c478bd9Sstevel@tonic-gate rmlock(lname); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* 262*8d489c7aSmuffin * tip_mlock(sys) create system lock 2637c478bd9Sstevel@tonic-gate * char *sys; 2647c478bd9Sstevel@tonic-gate * 2657c478bd9Sstevel@tonic-gate * return codes: 0 | FAIL 2667c478bd9Sstevel@tonic-gate */ 2677c478bd9Sstevel@tonic-gate 268*8d489c7aSmuffin int 269*8d489c7aSmuffin tip_mlock(char *sys) 2707c478bd9Sstevel@tonic-gate { 2717c478bd9Sstevel@tonic-gate struct stat sb; 2727c478bd9Sstevel@tonic-gate char lname[NAMESIZE]; 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate if (stat(sys, &sb) < 0) 2757c478bd9Sstevel@tonic-gate return (FAIL); 276*8d489c7aSmuffin (void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu", 277*8d489c7aSmuffin LOCKDIR, LOCKPRE, 2787c478bd9Sstevel@tonic-gate (unsigned long)major(sb.st_dev), 2797c478bd9Sstevel@tonic-gate (unsigned long)major(sb.st_rdev), 2807c478bd9Sstevel@tonic-gate (unsigned long)minor(sb.st_rdev)); 2817c478bd9Sstevel@tonic-gate return (ulockf(lname, (time_t)SLCKTIME) < 0 ? FAIL : 0); 2827c478bd9Sstevel@tonic-gate } 283