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
127c478bd9Sstevel@tonic-gate /*
137c478bd9Sstevel@tonic-gate * defs that come from uucp.h
147c478bd9Sstevel@tonic-gate */
157c478bd9Sstevel@tonic-gate #define NAMESIZE 40
167c478bd9Sstevel@tonic-gate #define FAIL -1
177c478bd9Sstevel@tonic-gate #define SAME 0
187c478bd9Sstevel@tonic-gate #define SLCKTIME (8*60*60) /* device timeout (LCK.. files) in seconds */
197c478bd9Sstevel@tonic-gate #ifdef __STDC__
207c478bd9Sstevel@tonic-gate #define ASSERT(e, f, v) if (!(e)) {\
218d489c7aSmuffin (void) fprintf(stderr, "AERROR - (%s) ", #e); \
228d489c7aSmuffin (void) fprintf(stderr, f, v); \
237c478bd9Sstevel@tonic-gate finish(FAIL); \
247c478bd9Sstevel@tonic-gate }
257c478bd9Sstevel@tonic-gate #else
267c478bd9Sstevel@tonic-gate #define ASSERT(e, f, v) if (!(e)) {\
278d489c7aSmuffin (void) fprintf(stderr, "AERROR - (%s) ", "e"); \
288d489c7aSmuffin (void) fprintf(stderr, f, v); \
297c478bd9Sstevel@tonic-gate finish(FAIL); \
307c478bd9Sstevel@tonic-gate }
317c478bd9Sstevel@tonic-gate #endif
327c478bd9Sstevel@tonic-gate #define SIZEOFPID 10 /* maximum number of digits in a pid */
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #define LOCKDIR "/var/spool/locks"
357c478bd9Sstevel@tonic-gate #define LOCKPRE "LK"
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate * This code is taken almost directly from uucp and follows the same
397c478bd9Sstevel@tonic-gate * conventions. This is important since uucp and tip should
407c478bd9Sstevel@tonic-gate * respect each others locks.
417c478bd9Sstevel@tonic-gate */
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate #include <sys/types.h>
447c478bd9Sstevel@tonic-gate #include <sys/stat.h>
457c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
467c478bd9Sstevel@tonic-gate #include <stdio.h>
477c478bd9Sstevel@tonic-gate #include <errno.h>
487c478bd9Sstevel@tonic-gate #include <string.h>
498d489c7aSmuffin #include <stdlib.h>
508d489c7aSmuffin #include <time.h>
518d489c7aSmuffin #include <unistd.h>
528d489c7aSmuffin #include <fcntl.h>
538d489c7aSmuffin #include <signal.h>
548d489c7aSmuffin #include <utime.h>
557c478bd9Sstevel@tonic-gate
568d489c7aSmuffin static void stlock(char *);
578d489c7aSmuffin static int onelock(char *, char *, char *);
588d489c7aSmuffin static int checkLock(char *);
597c478bd9Sstevel@tonic-gate
608d489c7aSmuffin extern void finish(int);
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate /*
637c478bd9Sstevel@tonic-gate * ulockf(file, atime)
647c478bd9Sstevel@tonic-gate * char *file;
657c478bd9Sstevel@tonic-gate * time_t atime;
667c478bd9Sstevel@tonic-gate *
677c478bd9Sstevel@tonic-gate * ulockf - this routine will create a lock file (file).
687c478bd9Sstevel@tonic-gate * If one already exists, send a signal 0 to the process--if
697c478bd9Sstevel@tonic-gate * it fails, then unlink it and make a new one.
707c478bd9Sstevel@tonic-gate *
717c478bd9Sstevel@tonic-gate * input:
727c478bd9Sstevel@tonic-gate * file - name of the lock file
737c478bd9Sstevel@tonic-gate * atime - is unused, but we keep it for lint compatibility
747c478bd9Sstevel@tonic-gate * with non-ATTSVKILL
757c478bd9Sstevel@tonic-gate *
767c478bd9Sstevel@tonic-gate * return codes: 0 | FAIL
777c478bd9Sstevel@tonic-gate */
788d489c7aSmuffin /* ARGSUSED */
798d489c7aSmuffin static int
ulockf(char * file,time_t atime)808d489c7aSmuffin ulockf(char *file, time_t atime)
817c478bd9Sstevel@tonic-gate {
827c478bd9Sstevel@tonic-gate static char pid[SIZEOFPID+2] = { '\0' }; /* +2 for '\n' and NULL */
837c478bd9Sstevel@tonic-gate static char tempfile[NAMESIZE];
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate if (pid[0] == '\0') {
86*94e1761eSsn199410 (void) snprintf(pid, sizeof (pid), "%*d\n", SIZEOFPID,
87*94e1761eSsn199410 (int)getpid());
888d489c7aSmuffin (void) snprintf(tempfile, sizeof (tempfile),
898d489c7aSmuffin "%s/LTMP.%d", LOCKDIR, getpid());
907c478bd9Sstevel@tonic-gate }
917c478bd9Sstevel@tonic-gate if (onelock(pid, tempfile, file) == -1) {
927c478bd9Sstevel@tonic-gate /* lock file exists */
937c478bd9Sstevel@tonic-gate (void) unlink(tempfile);
947c478bd9Sstevel@tonic-gate if (checkLock(file))
957c478bd9Sstevel@tonic-gate return (FAIL);
967c478bd9Sstevel@tonic-gate else {
977c478bd9Sstevel@tonic-gate if (onelock(pid, tempfile, file)) {
987c478bd9Sstevel@tonic-gate (void) unlink(tempfile);
997c478bd9Sstevel@tonic-gate return (FAIL);
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate stlock(file);
1047c478bd9Sstevel@tonic-gate return (0);
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate * check to see if the lock file exists and is still active
1097c478bd9Sstevel@tonic-gate * - use kill(pid, 0) - (this only works on ATTSV and some hacked
1107c478bd9Sstevel@tonic-gate * BSD systems at this time)
1117c478bd9Sstevel@tonic-gate * return:
1127c478bd9Sstevel@tonic-gate * 0 -> success (lock file removed - no longer active)
1137c478bd9Sstevel@tonic-gate * FAIL -> lock file still active
1147c478bd9Sstevel@tonic-gate */
1157c478bd9Sstevel@tonic-gate static int
checkLock(char * file)1168d489c7aSmuffin checkLock(char *file)
1177c478bd9Sstevel@tonic-gate {
1188d489c7aSmuffin int ret;
1197c478bd9Sstevel@tonic-gate int lpid = -1;
1207c478bd9Sstevel@tonic-gate char alpid[SIZEOFPID+2]; /* +2 for '\n' and NULL */
1217c478bd9Sstevel@tonic-gate int fd;
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate fd = open(file, 0);
1247c478bd9Sstevel@tonic-gate if (fd == -1) {
1257c478bd9Sstevel@tonic-gate if (errno == ENOENT) /* file does not exist -- OK */
1267c478bd9Sstevel@tonic-gate return (0);
1277c478bd9Sstevel@tonic-gate goto unlk;
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate ret = read(fd, (char *)alpid, SIZEOFPID+1); /* +1 for '\n' */
1307c478bd9Sstevel@tonic-gate (void) close(fd);
1317c478bd9Sstevel@tonic-gate if (ret != (SIZEOFPID+1))
1327c478bd9Sstevel@tonic-gate goto unlk;
1337c478bd9Sstevel@tonic-gate lpid = atoi(alpid);
1347c478bd9Sstevel@tonic-gate if ((ret = kill(lpid, 0)) == 0 || errno == EPERM)
1357c478bd9Sstevel@tonic-gate return (FAIL);
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate unlk:
1387c478bd9Sstevel@tonic-gate if (unlink(file) != 0)
1397c478bd9Sstevel@tonic-gate return (FAIL);
1407c478bd9Sstevel@tonic-gate return (0);
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate #define MAXLOCKS 10 /* maximum number of lock files */
1447c478bd9Sstevel@tonic-gate char *Lockfile[MAXLOCKS];
1457c478bd9Sstevel@tonic-gate int Nlocks = 0;
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate /*
1487c478bd9Sstevel@tonic-gate * stlock(name) put name in list of lock files
1497c478bd9Sstevel@tonic-gate * char *name;
1507c478bd9Sstevel@tonic-gate *
1517c478bd9Sstevel@tonic-gate * return codes: none
1527c478bd9Sstevel@tonic-gate */
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate static void
stlock(char * name)1558d489c7aSmuffin stlock(char *name)
1567c478bd9Sstevel@tonic-gate {
1577c478bd9Sstevel@tonic-gate char *p;
1587c478bd9Sstevel@tonic-gate int i;
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate for (i = 0; i < Nlocks; i++) {
1617c478bd9Sstevel@tonic-gate if (Lockfile[i] == NULL)
1627c478bd9Sstevel@tonic-gate break;
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate ASSERT(i < MAXLOCKS, "TOO MANY LOCKS %d", i);
1657c478bd9Sstevel@tonic-gate if (i >= Nlocks)
1667c478bd9Sstevel@tonic-gate i = Nlocks++;
1677c478bd9Sstevel@tonic-gate p = calloc(strlen(name) + 1, sizeof (char));
1687c478bd9Sstevel@tonic-gate ASSERT(p != NULL, "CAN NOT ALLOCATE FOR %s", name);
1698d489c7aSmuffin (void) strcpy(p, name);
1707c478bd9Sstevel@tonic-gate Lockfile[i] = p;
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate /*
1747c478bd9Sstevel@tonic-gate * rmlock(name) remove all lock files in list
1757c478bd9Sstevel@tonic-gate * char *name; or name
1767c478bd9Sstevel@tonic-gate *
1777c478bd9Sstevel@tonic-gate * return codes: none
1787c478bd9Sstevel@tonic-gate */
1797c478bd9Sstevel@tonic-gate
1808d489c7aSmuffin static void
rmlock(char * name)1818d489c7aSmuffin rmlock(char *name)
1827c478bd9Sstevel@tonic-gate {
1837c478bd9Sstevel@tonic-gate int i;
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate for (i = 0; i < Nlocks; i++) {
1867c478bd9Sstevel@tonic-gate if (Lockfile[i] == NULL)
1877c478bd9Sstevel@tonic-gate continue;
1887c478bd9Sstevel@tonic-gate if (name == NULL || strcmp(name, Lockfile[i]) == SAME) {
1898d489c7aSmuffin (void) unlink(Lockfile[i]);
1907c478bd9Sstevel@tonic-gate free(Lockfile[i]);
1917c478bd9Sstevel@tonic-gate Lockfile[i] = NULL;
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate }
1957c478bd9Sstevel@tonic-gate
1968d489c7aSmuffin static int
onelock(char * pid,char * tempfile,char * name)1978d489c7aSmuffin onelock(char *pid, char *tempfile, char *name)
1987c478bd9Sstevel@tonic-gate {
1997c478bd9Sstevel@tonic-gate int fd;
2007c478bd9Sstevel@tonic-gate static int first = 1;
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate fd = creat(tempfile, 0444);
2037c478bd9Sstevel@tonic-gate if (fd < 0) {
2047c478bd9Sstevel@tonic-gate if (first) {
2057c478bd9Sstevel@tonic-gate if (errno == EACCES) {
2068d489c7aSmuffin (void) fprintf(stderr,
2077c478bd9Sstevel@tonic-gate "tip: can't create files in lock file directory %s\n",
2087c478bd9Sstevel@tonic-gate LOCKDIR);
2097c478bd9Sstevel@tonic-gate } else if (access(LOCKDIR, 0) < 0) {
2108d489c7aSmuffin (void) fprintf(stderr,
2118d489c7aSmuffin "tip: lock file directory %s: ",
2127c478bd9Sstevel@tonic-gate LOCKDIR);
2137c478bd9Sstevel@tonic-gate perror("");
2147c478bd9Sstevel@tonic-gate }
2157c478bd9Sstevel@tonic-gate first = 0;
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate if (errno == EMFILE || errno == ENFILE)
2187c478bd9Sstevel@tonic-gate (void) unlink(tempfile);
2197c478bd9Sstevel@tonic-gate return (-1);
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate /* +1 for '\n' */
2227c478bd9Sstevel@tonic-gate if (write(fd, pid, SIZEOFPID+1) != (SIZEOFPID+1)) {
2238d489c7aSmuffin (void) fprintf(stderr,
2247c478bd9Sstevel@tonic-gate "tip: can't write to files in lock file directory %s: %s\n",
2257c478bd9Sstevel@tonic-gate LOCKDIR, strerror(errno));
2267c478bd9Sstevel@tonic-gate (void) unlink(tempfile);
2277c478bd9Sstevel@tonic-gate return (-1);
2287c478bd9Sstevel@tonic-gate }
2298d489c7aSmuffin (void) fchmod(fd, 0444);
2308d489c7aSmuffin (void) close(fd);
2317c478bd9Sstevel@tonic-gate if (link(tempfile, name) < 0) {
2328d489c7aSmuffin (void) unlink(tempfile);
2337c478bd9Sstevel@tonic-gate return (-1);
2347c478bd9Sstevel@tonic-gate }
2358d489c7aSmuffin (void) unlink(tempfile);
2367c478bd9Sstevel@tonic-gate return (0);
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate /*
2407c478bd9Sstevel@tonic-gate * delock(sys) remove a lock file
2417c478bd9Sstevel@tonic-gate * char *sys;
2427c478bd9Sstevel@tonic-gate */
2437c478bd9Sstevel@tonic-gate
2448d489c7aSmuffin void
delock(char * sys)2458d489c7aSmuffin delock(char *sys)
2467c478bd9Sstevel@tonic-gate {
2477c478bd9Sstevel@tonic-gate struct stat sb;
2487c478bd9Sstevel@tonic-gate char lname[NAMESIZE];
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate if (stat(sys, &sb) < 0)
2518d489c7aSmuffin return;
2528d489c7aSmuffin (void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu",
2538d489c7aSmuffin LOCKDIR, LOCKPRE,
2547c478bd9Sstevel@tonic-gate (unsigned long)major(sb.st_dev),
2557c478bd9Sstevel@tonic-gate (unsigned long)major(sb.st_rdev),
2567c478bd9Sstevel@tonic-gate (unsigned long)minor(sb.st_rdev));
2577c478bd9Sstevel@tonic-gate rmlock(lname);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate /*
2618d489c7aSmuffin * tip_mlock(sys) create system lock
2627c478bd9Sstevel@tonic-gate * char *sys;
2637c478bd9Sstevel@tonic-gate *
2647c478bd9Sstevel@tonic-gate * return codes: 0 | FAIL
2657c478bd9Sstevel@tonic-gate */
2667c478bd9Sstevel@tonic-gate
2678d489c7aSmuffin int
tip_mlock(char * sys)2688d489c7aSmuffin tip_mlock(char *sys)
2697c478bd9Sstevel@tonic-gate {
2707c478bd9Sstevel@tonic-gate struct stat sb;
2717c478bd9Sstevel@tonic-gate char lname[NAMESIZE];
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate if (stat(sys, &sb) < 0)
2747c478bd9Sstevel@tonic-gate return (FAIL);
2758d489c7aSmuffin (void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu",
2768d489c7aSmuffin LOCKDIR, LOCKPRE,
2777c478bd9Sstevel@tonic-gate (unsigned long)major(sb.st_dev),
2787c478bd9Sstevel@tonic-gate (unsigned long)major(sb.st_rdev),
2797c478bd9Sstevel@tonic-gate (unsigned long)minor(sb.st_rdev));
2807c478bd9Sstevel@tonic-gate return (ulockf(lname, (time_t)SLCKTIME) < 0 ? FAIL : 0);
2817c478bd9Sstevel@tonic-gate }
282