1 /*
2  * lckfiles.c   set_lock() and release_lock(), for maintaining
3  *		little file.lck style lockfiles.  this isn't what
4  *		we would call a standard mechanism.  but it's simple.
5  *
6  *		it's also not completely integrated with the editor --
7  *		for instance, one can probably bypass the locking mechanism
8  *		in various ways.  it is intended as an _aid_ to multiple
9  *		edits.  _not_ a cure-all.  it works well for the people
10  *		at Baan who contributed the code.  i make no other claims
11  *		for it.
12  *
13  *		operation:  if the global "usefilelock" is on, then when
14  *		"file" is edited, a "file.lck" is created, containing the
15  *		username of the user doing the editing.  when a file is
16  *		edited for which there already exists a .lck file, the buffer
17  *		mode "locked" is set to true and "locker" is set to the name
18  *		of the user that created the .lck.  this information will
19  *		appear on the status line, as "locked by pgf", and the
20  *		buffer will be marked readonly.  the .lck file will be
21  *		deleted at most of the appropriate times.
22  *
23  * $Id: lckfiles.c,v 1.13 2020/01/17 22:36:39 tom Exp $
24  *
25  */
26 
27 #include	"estruct.h"
28 #include	"edef.h"
29 
30 #if OPT_LCKFILES
31 
32 #ifndef HAVE_LONG_FILE_NAMES
33 You probably would not want this code:
34   there are no checks on filename length when adding.lck to the end.
35 #endif
36 
37 static void
get_lock_owner(char * lockfile,char * who,int n)38 get_lock_owner(char *lockfile, char *who, int n)
39 {
40     FILE *fp;
41     int l;
42     if ((fp = fopen(lockfile, FOPEN_READ)) != (FILE *) 0) {
43 	l = read(fileno(fp), who, (size_t) (n - 1));
44 	if (l < 0) {
45 	    (void) strcpy(who, "'Can't read .lck'");
46 	} else {
47 	    who[l - 1] = EOS;	/* Strip \n */
48 	}
49 	fclose(fp);
50     } else {
51 	(void) strcpy(who, "'Can't open .lck'");
52     }
53 }
54 
55 static char *
ourname(void)56 ourname(void)
57 {
58     char *np;
59     np = getenv("LOGNAME");
60     if (!np)
61 	np = getenv("USER");
62     if (!np)
63 	np = "unknown";
64     return np;
65 }
66 
67 int
set_lock(const char * fname,char * who,int n)68 set_lock(const char *fname, char *who, int n)
69 {
70     char lockfile[NFILEN];
71     FILE *fp;
72 
73     sprintf(lockfile, "%s.lck", fname);
74 
75     if (ffexists(lockfile)) {
76 	/* Lockfile exists */
77 	get_lock_owner(lockfile, who, n);
78 	mlwrite("[%s]", who);
79 	return FALSE;		/* Can't set lock */
80     } else {
81 	if ((fp = fopen(lockfile, FOPEN_WRITE)) != (FILE *) 0) {
82 	    (void) lsprintf(who, "%s\n", ourname());
83 	    write(fileno(fp), who, strlen(who));
84 	    fclose(fp);
85 	} else {
86 	    (void) strcpy(who, "'Can't write .lck'");
87 	    mlwrite("[%s]", who);
88 	    return (FALSE);	/* Can't set lock */
89 	}
90     }
91     return TRUE;		/* Lock ok */
92 }
93 
94 void
release_lock(const char * fname)95 release_lock(const char *fname)
96 {
97     char lockfile[NFILEN];
98     char who[100];
99 
100     if (fname && *fname) {
101 	(void) lsprintf(lockfile, "%s.lck", fname);
102 	get_lock_owner(lockfile, who, sizeof(who));
103 	/* is it ours? */
104 	if (strcmp(who, ourname()) == 0)
105 	    unlink(lockfile);
106     }
107 }
108 #endif
109