1 /*	DOLOCK.C:	Machine specific code for File Locking
2 			for MicroEMACS
3 			(C)Copyright 1995 by Daniel M Lawrence
4 */
5 
6 #include	<stdio.h>
7 #include	"estruct.h"
8 #include	"eproto.h"
9 #include	"elang.h"
10 
11 #if	WMCS
12 /*	file locking for WMCS */
13 
14 #include "sys$disk/sysincl.sys/sysequ.h"
15 #include <stdio.h>
16 #include <ctype.h>
17 
18 char msg[] = TEXT35;
19 /*           "another user" */
20 
dolock(fname)21 char *dolock(fname)
22 char *fname;
23 {
24 	int lun,status;
25 	status = _open(fname,OPREADACC|OPWRITEACC|OPWRITELOCK,-1,&lun);
26 	if(status == 133 || status == 0 ) return(NULL);
27 	return(msg);
28 }
29 
undolock(fname)30 char *undolock(fname)
31 char *fname;
32 {
33 	int i,j,k,lun,status;
34 	char xname[95],c;
35 
36 	for(lun=4; _getfnam(lun,xname) == 0; lun++) {
37 		for(i=0;i<strlen(xname);i++)	{
38 			k = i;
39 			for(j=0;j<strlen(fname);j++)  {
40 				c = fname[j];
41 				if(is_lower(c)) c = toupper(c);
42 				if(c == xname[k]) { ++k; continue; }
43 				if(c == '\0') break;
44 				break;
45 				}
46 			if(j == strlen(fname)) {
47 				_close(lun,0);
48 				return(NULL);
49 				}
50 			}
51 	}
52 	return(NULL);
53 }
54 #endif
55 
56 #if	FILOCK && (MSDOS || WINNT || OS2 || SUN || USG || AIX || AUX || AVIION || BSD || FREEBSD || HPUX8 || HPUX9 || AMIGA)
57 #if	OS2 || ((MSDOS || WINNT) && MSC) || BSD || FREEBSD
58 #include	<sys/types.h>
59 #endif
60 #include	<sys/stat.h>
61 #include	<errno.h>
62 #if	MSDOS && TURBO
63 #include	<dir.h>
64 #endif
65 #if	SUN
66 #include	<sys/dir.h>
67 #include	<signal.h>
68 #endif
69 
70 #if	WINNT && MSC
71 #include <direct.h>
72 #define chdir	_chdir
73 #define getcwd	_getcwd
74 #define mkdir	_mkdir
75 #define rmdir	_rmdir
76 #endif
77 
78 #if	OS2 == 0
79 #if	ZTC
80 extern volatile int errno;
81 #else
82 #if	MSC == 0
83 extern int errno;
84 #endif
85 #endif
86 #endif
87 
88 #define LOCKDIR "_xlk"
89 #define LOCKMSG "LOCK ERROR -- "
90 #define	LOCKDEBUG	FALSE
91 
92 /*	dolock:	Generic non-UNIX file locking mechinism	*/
93 
94 /**********************
95  *
96  * dolock -- lock the file fname
97  *
98  * if successful, returns NULL
99  * if file locked, returns username of person locking the file
100  * if other error, returns "LOCK ERROR: explanation"
101  *
102  *********************/
103 
parse_name(filespec)104 char *parse_name(filespec)		/* get name component of filespec */
105 
106 char *filespec;
107 
108 {
109 	char *rname;
110 
111 	rname = &filespec[strlen(filespec) - 1];
112 	while (rname >= filespec) {
113 		if (*rname == DIRSEPCHAR || *rname == DRIVESEPCHAR) {
114 			++rname;
115 			break;
116 		}
117 		--rname;
118 	}
119 
120 	if (rname >= filespec)
121 		return(rname);
122 	else
123 		return(filespec);
124 }
125 
parse_path(filespec)126 char *parse_path(filespec)
127 
128 char *filespec;
129 
130 {
131 	static char rbuff[NFILEN];
132 	char *rname;
133 
134 	/* make a copy we can mung */
135 	strcpy(rbuff,filespec);
136 
137 	/* starting from the end */
138 	rname = &rbuff[strlen(rbuff)-1];
139 
140 	/* scan for a directory separator */
141 	while (rname >= rbuff) {
142 		if (*rname == DIRSEPCHAR)
143 			break;
144 		--rname;
145 	}
146 
147 	/* no path here! */
148 	if (rname < rbuff) {
149 		rbuff[0] = '.';
150 		rbuff[1] = DIRSEPCHAR;
151 		rbuff[2] = 0;
152 		return(rbuff);
153 	}
154 
155 	*(rname + 1) = '\0';	/* point just beyond slash */
156 
157 	/* no skip beyond any drive spec */
158 	rname = rbuff;
159 	while (*rname) {
160 		if (*rname == DRIVESEPCHAR)
161 			return(++rname);
162 		++rname;
163 	}
164 
165 	/* none to be found, return the whole string */
166 	return(rbuff);
167 }
168 
parse_drive(filespec)169 char *parse_drive(filespec)
170 
171 char *filespec;
172 
173 {
174 	static char rbuff[NFILEN];
175 	char *rname;
176 
177 	/* search for a drive specifier */
178 	strcpy(rbuff,filespec);
179 	rname = rbuff;
180 	while (*rname) {
181 		if (*rname == DRIVESEPCHAR) {
182 			*(++rname) = 0;
183 			return(rbuff);
184 		}
185 		++rname;
186 	}
187 
188 	/* no drive letter/name */
189 	return("");
190 }
191 
term_trim(buf)192 VOID term_trim(buf)	/* trim line terminators and whitespace from end of string */
193 
194 char *buf;
195 
196 {
197 	char *c;	/* ptr to current character to examine */
198 
199 	c = buf + strlen(buf) - 1;
200 	while ((c >= buf) && (*c == '\r') || (*c == '\n') || (*c == ' ')
201 	    || (*c == '\t')) {
202 		*c = 0;
203 		c--;
204 	}
205 	return;
206 }
207 
dolock(filespec)208 char *dolock(filespec)
209 
210 char *filespec;		/* full file spec of file to lock */
211 
212 {
213 	struct stat sb;			/* stat buffer for info on files/dirs */
214 	FILE *fp;			/* ptr to lock file */
215 	long proc_id;			/* process id from lock file */
216 	char filename[NFILEN];		/* name of file to lock */
217 	char pathname[NFILEN];		/* path leading to file to lock */
218 	char drivename[NFILEN];		/* drive for file to lock */
219 	char lockpath[NFILEN];		/* lock directory name */
220 	char lockfile[NFILEN];		/* lock file name */
221 	char buf[NSTRING];		/* input buffer */
222 	char host[NSTRING];		/* current host name */
223 	static char result[NSTRING];	/* error return string */
224 
225 	/* separate filespec into components */
226 	strcpy(filename, parse_name(filespec));
227 	strcpy(pathname, parse_path(filespec));
228 	strcpy(drivename, parse_drive(filespec));
229 	if (pathname[0] == 0)
230 		strcpy(pathname, ".");
231 
232 	/* merge the drive into the pathname */
233 	strcat(drivename, pathname);
234 	strcpy(pathname, drivename);
235 
236 #if	LOCKDEBUG
237 	printf("Locking [%s] [%s]\n", pathname, filename); tgetc();
238 #endif
239 
240 #if	MSDOS == 0 && WINNT == 0 && OS2 == 0
241 	/* check to see if we can access the path */
242 	if (stat(pathname, &sb) != 0) {
243 #if	LOCKDEBUG
244 		printf("stat() = %u   errno = %u\n", stat(pathname, &sb), errno); tgetc();
245 #endif
246 		strcpy(result, LOCKMSG);
247 		strcat(result, "Path not found");
248 		return(result);
249 	}
250 	if ((sb.st_mode & S_IFDIR) == 0) {
251 		strcpy(result, LOCKMSG);
252 		strcat(result, "Illegal Path");
253 		return(result);
254 	}
255 #endif
256 
257 	/* create the lock directory if it does not exist */
258 	strcpy(lockpath, pathname);
259 	strcat(lockpath, DIRSEPSTR);
260 	strcat(lockpath, LOCKDIR);
261 #if	LOCKDEBUG
262 	printf("Lockdir [%s]\n", lockpath); tgetc();
263 #endif
264 
265 	if (stat(lockpath, &sb) != 0) {
266 
267 		/* create it! */
268 #if	LOCKDEBUG
269 		printf("MKDIR(%s)\n", lockpath); tgetc();
270 #endif
271 #if	MSDOS || WINNT || OS2
272 		if (mkdir(lockpath) != 0) {
273 #else
274 		if (mkdir(lockpath, 0777) != 0) {
275 #endif
276 			strcpy(result, LOCKMSG);
277 			switch (errno) {
278 
279 			    case EACCES:
280 				strcat(result, "Permission Denied");
281 				break;
282 
283 			    case ENOENT:
284 				strcat(result, "No such file or directory");
285 				break;
286 			}
287 			return(result);
288 		}
289 	}
290 
291 	/* check for the existance of this lockfile */
292 	strcpy(lockfile, lockpath);
293 	strcat(lockfile, DIRSEPSTR);
294 	strcat(lockfile, filename);
295 #if	LOCKDEBUG
296 	printf("Lockfile [%s]\n", lockfile); tgetc();
297 #endif
298 
299 	if (stat(lockfile, &sb) != 0) {
300 
301 		/* create the lock file */
302 		fp = fopen(lockfile, "w");
303 		if (fp == (FILE *)NULL) {
304 			strcpy(result, LOCKMSG);
305 			strcat(result, "Can not open lock file");
306 			return(result);
307 		}
308 
309 		/* and output the info needed */
310 #if	MSDOS || WINNT || OS2
311 		fprintf(fp, "0\n");		/* process ID */
312 #endif
313 #if	SUN
314 		fprintf(fp, "%u\n", getpid());
315 #endif
316 
317 #if HPUX8 | HPUX9
318 		/* user name */
319 		if (getenv("LOGNAME"))
320 			fprintf(fp, "%s\n", getenv("LOGNAME"));
321 #else
322 		/* user name */
323 		if (getenv("USER"))
324 			fprintf(fp, "%s\n", getenv("USER"));
325 #endif
326 		else
327 			fprintf(fp, "<unknown>\n");
328 
329 		/* host name */
330 		if (getenv("HOST"))
331 			fprintf(fp, "%s\n", getenv("HOST"));
332 		else {
333 #if	MSDOS || WINNT || OS2
334 			fprintf(fp, "<unknown>\n");
335 #endif
336 #if	SUN
337 			gethostname(buf, NFILEN);
338 			fprintf(fp, "%s\n", buf);
339 #endif
340 		}
341 
342 		/* time... */
343 		fprintf(fp, "%s\n", timeset());
344 
345 		fclose(fp);
346 		return(NULL);
347 
348 	} else {
349 
350 		/* get the existing lock info */
351 		fp = fopen(lockfile, "r");
352 		if (fp == (FILE *)NULL) {
353 			strcpy(result, LOCKMSG);
354 			strcat(result, "Can not read lock file");
355 			return(result);
356 		}
357 
358 		/* get the process id */
359 		fgets(buf, NSTRING, fp);
360 		proc_id = asc_int(buf);
361 
362 		/* get the user name */
363 		fgets(result, NSTRING, fp);
364 		term_trim(result);
365 
366 		/* get the host name */
367 		strcat(result, "@");
368 		fgets(buf, NSTRING, fp);
369 		term_trim(buf);
370 		strcat(result, buf);
371 
372 #if	SUN
373 		/* is it the current host? */
374 		gethostname(host, NFILEN);
375 		if (strcmp(buf, host) == 0) {
376 
377 			/* see if the process is dead already */
378 			if (kill(proc_id, 0) != 0 && errno == ESRCH) {
379 
380 				/* kill the lock file and retry the lock */
381 				fclose(fp);
382 				unlink(lockfile);
383 				return(dolock(filespec));
384 			}
385 		}
386 #endif
387 
388 		/* get the time */
389 		strcat(result, " at ");
390 		fgets(buf, NSTRING, fp);
391 		term_trim(buf);
392 		strcat(result, buf);
393 		fclose(fp);
394 		return(result);
395 	}
396 }
397 
398 /**********************
399  *
400  * undolock -- unlock the file fname
401  *
402  * if successful, returns NULL
403  * if other error, returns "LOCK ERROR: explanation"
404  *
405  *********************/
406 
undolock(filespec)407 char *undolock(filespec)
408 
409 char *filespec;		/* filespec to unlock */
410 
411 {
412 	char filename[NFILEN];		/* name of file to lock */
413 	char pathname[NFILEN];		/* path leading to file to lock */
414 	char drivename[NFILEN];		/* drive for file to lock */
415 	char lockpath[NFILEN];		/* lock directory name */
416 	char lockfile[NFILEN];		/* lock file name */
417 	static char result[NSTRING];	/* error return string */
418 
419 	/* separate filespec into components */
420 	strcpy(filename, parse_name(filespec));
421 	strcpy(pathname, parse_path(filespec));
422 	strcpy(drivename, parse_drive(filespec));
423 	if (pathname[0] == 0)
424 		strcpy(pathname, ".");
425 
426 	/* merge the drive into the pathname */
427 	strcat(drivename, pathname);
428 	strcpy(pathname, drivename);
429 
430 #if	LOCKDEBUG
431 	printf("\nUnLocking [%s] [%s]\n", pathname, filename); tgetc();
432 #endif
433 
434 	/* create the lock directory if it does not exist */
435 	strcpy(lockpath, pathname);
436 	strcat(lockpath, DIRSEPSTR);
437 	strcat(lockpath, LOCKDIR);
438 #if	LOCKDEBUG
439 	printf("Lockdir [%s]\n", lockpath); tgetc();
440 #endif
441 	/* check for the existance of this lockfile */
442 	strcpy(lockfile, lockpath);
443 	strcat(lockfile, DIRSEPSTR);
444 	strcat(lockfile, filename);
445 #if	LOCKDEBUG
446 	printf("Lockfile [%s]\n", lockfile); tgetc();
447 #endif
448 	if (unlink(lockfile)) {
449 		strcat(result, "could not remove lock file");
450 		return(result);
451 	} else {
452 		rmdir(lockpath);   /* this will work only if dir is empty */
453   	  	return(NULL);
454 	}
455 }
456 
457 #else
dolhello()458 dolhello()
459 {
460 }
461 #endif
462 
463