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