/* * Copyright(c) 1997, Space Science and Engineering Center, UW-Madison * Refer to "McIDAS Software Acquisition and Distribution Policies" * in the file mcidas/data/license.txt */ /**** $Id: special.c,v 1.16 2019/11/14 17:22:55 davep Exp $ ****/ #include #include #include #include #include #include #include #include #include "mcidas.h" #include "m0glue.h" #include "m0panel.h" #define ENV_LOCK "MCLOCKDIR" #define LOCK_PATH M0prefixRootPath("/tmp/mclock") /* This file is used as a lock name * but it is also a legitimate file, so * it should not be on the 'special file' list * RESOLV.SRV * * the lockname WINDCO and the file name winquefil * have the possibility of having different scope. * we decided that it is not worth it to make spacial * files for this case, which will seldom come up */ /* * This is a list of the files which occur per instance * in McIDAS sessions. * * The following are other known lock files; do they belong * in the list of special files? * * verify_del */ static const char * const special_files[] = { "BASICVV1", /* storage for RUN variables */ FRAMEDIR, "FRAMENH.001", "TERMCHAR.001", "GRAPHICS.KEY", "RGBFRMS.KEY", "STRTABLE", /* stores the string table */ MCCLEAN_FILE, /* lockfile with session scope */ 0 }; /* removed by RODR for Dynamic Graphics system */ /* "SYSIMAGE.SAV", stores frames w/o graphics applied */ static char *path = 0; /* path name for new temporary * directory */ static int lockfd = -1; /* *| Name: *| M0specfiles - list of per-instance files *| *| Interface: *| #include "m0glue.h" *| *| const char * const * *| M0specfiles(void) *| *| Input: *| none *| *| Input and Output: *| none *| *| Output: *| none *| *| Return values: *| none *| *| Remarks: *| none *| *| Categories: *| SYSTEM */ const char * const * M0specfiles(void) { return special_files; } /* *| Name: *| M0makefiles - create files which exist for each instance of McIDAS *| *| Interface: *| #include "m0glue.h" *| *| int *| M0makefiles(void) *| *| Input: *| none *| *| Input and Output: *| none *| *| Output: *| none *| *| Return values: *| -1 indicates failure *| 0 indicates possible success *| *| Remarks: *| The files are created in a directory under $MCTMPDIR/.mctmp *| (if set), $HOME/.mctmp, or /tmp/mctmp *| *| A special file named in the macro MCCLEAN_FILE is created *| and locked in that directory, so the mcclean function can *| detect whether the directory continues in use. *| The lock is never explicitly released, so it has the duration *| of this process. *| *| Categories: *| SYSTEM */ int M0makefiles(void) { const char *oldmcpath; char *mcpath; char *dirpath; int i; const char * const *specials = M0specfiles(); char *home; char *mctmpdir; int tmpflag = 0; /* true if instance directory in /tmp */ oldmcpath = getenv("MCPATH"); /* if there is no mcpath, or it's empty, pretend it is a "." */ if (!oldmcpath || !*oldmcpath) oldmcpath = "."; /* * A directory name is constructed which is $MCTMPDIR/.mctmp * if $MCTMPDIR is set $HOME/.mctmp, or /tmp/mctmp. We call * mkdir but do not check its return. The directory may already * exist. then a slash and the positive UC key are cated to the * end and we call mkdir again to create the specific directory * under the generic one, which will be the real location of the * per-instance files. This time, mkdir is checked. */ /* see if $MCTMPDIR is set */ /* if not, see if $HOME is set */ mctmpdir = getenv("MCTMPDIR"); home = getenv("HOME"); if (mctmpdir && *mctmpdir) { dirpath = stralloc(mctmpdir, "/.mctmp", (char *) 0); } else if (home && *home) { dirpath = stralloc(home, "/.mctmp", (char *) 0); } else { dirpath = stralloc(M0prefixRootPath("/tmp/mctmp"), (char *) 0); tmpflag = 1; } assert(dirpath); /* * this may or may not work, depending on if it is already * there */ (void) mkdir(dirpath, S_IRUSR | S_IWUSR | S_IXUSR); /* * If we are making a directory in /tmp, we chmod it so that * others can write there, too. */ if (tmpflag) { chmod(dirpath, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH); } path = stralloc(dirpath, "/", getenv(M0ENV_POSUC), (char *) 0); assert(path); free(dirpath); /* trash any prior instance of this stuff */ M0delfiles(); /* now insist on being able to make the directory */ if (mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR) != 0) return -1; /* * create the per-instance files. Make them 1 byte long */ for (i = 0; specials[i] != 0; i++) { char *name; const unsigned char mis = MCMISSING; int fd; /* create files by writing on them */ name = stralloc(path, "/", specials[i], (char *) 0); assert(name); fd = open(name, O_RDWR | O_CREAT, 0600); assert(fd > -1); write(fd, &mis, 1); /* * one of these files is to be locked * * the continued existance of the lock implies that the * temporary directory is still in use * * note that fd is not closed in this case except * implicitly at process termination */ if (strcmp(MCCLEAN_FILE, specials[i]) == 0) { struct flock lk; int flags; flags = fcntl(fd, F_GETFD, 0); flags = flags | FD_CLOEXEC; (void) fcntl(fd, F_SETFD, flags); lk.l_type = F_WRLCK; lk.l_start = 0; lk.l_whence = SEEK_SET; lk.l_len = 1; fcntl(fd, F_SETLK, &lk); lockfd = fd; } else { close(fd); } free(name); } /* * add this to mcpath (don't free the storage, env now points * to it) */ mcpath = stralloc("MCPATH=", oldmcpath, ":", path, (char *) 0); assert(mcpath != 0); putenv(mcpath); return 0; } /* *| Name: *| M0delfiles - remove files and directory created by M0makefiles *| *| Interface: *| #include "m0glue.h" *| *| void *| M0delfiles(void) *| *| Input: *| none *| *| Input and Output: *| none *| *| Output: *| none *| *| Return values: *| none *| *| Remarks: *| none *| *| Categories: *| SYSTEM */ void M0delfiles(void) { char *rmvec[4]; char *lockpath = strdup (LOCK_PATH); char *buf; /* no path, no action */ if (path == 0) return; if(lockfd>-1) close(lockfd); rmvec[0] = M0prefixRootPath ("/bin/rm"); rmvec[1] = "-rf"; rmvec[2] = path; rmvec[3] = (char *) 0; buf = malloc ( strlen (rmvec[0]) + strlen (rmvec[1]) + strlen (rmvec[2]) + 3); sprintf (buf, "%s %s %s", rmvec[0], rmvec[1], rmvec[2]); /* delete the directory and all in it */ (void) system(buf); free (buf); /* ? change lock path ? */ if(getenv(ENV_LOCK)) { lockpath = getenv(ENV_LOCK); } lockpath = stralloc(lockpath, "/", getenv(M0ENV_POSUC), (char *) 0); unlink(lockpath); free(lockpath); }