There's this "pattern" in mg where it first access(2) a path, then does a buch of other things and finally opens it. It can do better.
Diff below removes the access() calls for conffile handling. startupfile() now does an ffropen() (fopen() wrapper) instead of access() and returns the file via parameter; callers will pass it to load() and then close it. There's one more subtle fix in here that may not be obvious on first look. I've moved the adjustname() call from load() to evalfile() to avoid doing a double tilde expansion. All call to load(), except evalfile(), have a path that's been constructed by mg itself or it has been passed by the user via -b/-u, thus not need to be "adjusted". Consider: % mkdir \~ ; mv ~/.mg \~/ ; mg -u \~/.mg which admittedly is a very corner case but shows the problem in doing an extra adjustname(). evalfile() -- aka M-x load -- prompts the user for a path so it's not unreasonable to call adjustname() on it. ok? Index: def.h =================================================================== RCS file: /home/cvs/src/usr.bin/mg/def.h,v retrieving revision 1.177 diff -u -p -r1.177 def.h --- def.h 20 Oct 2022 18:59:24 -0000 1.177 +++ def.h 30 Mar 2023 11:04:59 -0000 @@ -486,7 +486,7 @@ int ffputbuf(FILE *, struct buffer *, int ffgetline(FILE *, char *, int, int *); int fbackupfile(const char *); char *adjustname(const char *, int); -char *startupfile(char *, char *); +char *startupfile(FILE **, char *, char *); int copy(char *, char *); struct list *make_file_list(char *); int fisdir(const char *); @@ -594,7 +594,7 @@ int extend(int, int); int evalexpr(int, int); int evalbuffer(int, int); int evalfile(int, int); -int load(const char *); +int load(FILE *, const char *); int excline(char *, int, int); char *skipwhite(char *); Index: extend.c =================================================================== RCS file: /home/cvs/src/usr.bin/mg/extend.c,v retrieving revision 1.77 diff -u -p -r1.77 extend.c --- extend.c 8 Mar 2023 04:43:11 -0000 1.77 +++ extend.c 30 Mar 2023 11:04:59 -0000 @@ -620,37 +620,37 @@ evalbuffer(int f, int n) int evalfile(int f, int n) { + FILE *ffp; char fname[NFILEN], *bufp; + int ret; if ((bufp = eread("Load file: ", fname, NFILEN, EFNEW | EFCR)) == NULL) return (ABORT); - else if (bufp[0] == '\0') + if (bufp[0] == '\0') return (FALSE); - return (load(fname)); + if ((bufp = adjustname(fname, TRUE)) == NULL) + return (FALSE); + ret = ffropen(&ffp, bufp, NULL); + if (ret != FIOSUC) { + if (ret == FIODIR) + (void)ffclose(ffp, NULL); + return (FALSE); + } + ret = load(ffp, bufp); + (void)ffclose(ffp, NULL); + return (ret); } /* * load - go load the file name we got passed. */ int -load(const char *fname) +load(FILE *ffp, const char *fname) { - int s = TRUE, line, ret; + int s = TRUE, line; int nbytes = 0; char excbuf[BUFSIZE], fncpy[NFILEN]; - FILE *ffp; - - if ((fname = adjustname(fname, TRUE)) == NULL) - /* just to be careful */ - return (FALSE); - - ret = ffropen(&ffp, fname, NULL); - if (ret != FIOSUC) { - if (ret == FIODIR) - (void)ffclose(ffp, NULL); - return (FALSE); - } /* keep a note of fname in case of errors in loaded file. */ (void)strlcpy(fncpy, fname, sizeof(fncpy)); @@ -666,7 +666,6 @@ load(const char *fname) break; } } - (void)ffclose(ffp, NULL); excbuf[nbytes] = '\0'; if (s != FIOEOF || (nbytes && excline(excbuf, nbytes, ++line) != TRUE)) return (FALSE); Index: fileio.c =================================================================== RCS file: /home/cvs/src/usr.bin/mg/fileio.c,v retrieving revision 1.110 diff -u -p -r1.110 fileio.c --- fileio.c 30 Mar 2023 07:26:15 -0000 1.110 +++ fileio.c 30 Mar 2023 11:04:59 -0000 @@ -329,7 +329,7 @@ adjustname(const char *fn, int slashslas * to the startup file name. */ char * -startupfile(char *suffix, char *conffile) +startupfile(FILE **ffp, char *suffix, char *conffile) { static char file[NFILEN]; char *home; @@ -350,8 +350,13 @@ startupfile(char *suffix, char *conffile return (NULL); } - if (access(file, R_OK) == 0) + ret = ffropen(ffp, file, NULL); + if (ret == FIOSUC) return (file); + if (ret == FIODIR) + (void)ffclose(*ffp, NULL); + *ffp = NULL; + nohome: #ifdef STARTUPFILE if (suffix == NULL) { @@ -365,8 +370,12 @@ nohome: return (NULL); } - if (access(file, R_OK) == 0) + ret = ffropen(ffp, file, NULL); + if (ret == FIOSUC) return (file); + if (ret == FIODIR) + (void)ffclose(*ffp, NULL); + *ffp = NULL; #endif /* STARTUPFILE */ return (NULL); } Index: main.c =================================================================== RCS file: /home/cvs/src/usr.bin/mg/main.c,v retrieving revision 1.92 diff -u -p -r1.92 main.c --- main.c 30 Mar 2023 08:07:07 -0000 1.92 +++ main.c 30 Mar 2023 13:26:13 -0000 @@ -62,6 +62,7 @@ usage() int main(int argc, char **argv) { + FILE *ffp; char *cp, *conffile = NULL, *init_fcn_name = NULL; char *batchfile = NULL; PF init_fcn = NULL; @@ -107,7 +108,7 @@ main(int argc, char **argv) pty_init(); conffile = batchfile; } - if (conffile != NULL && access(conffile, R_OK) != 0) { + if ((cp = startupfile(&ffp, NULL, conffile)) != NULL && conffile) { fprintf(stderr, "%s: Problem with file: %s\n", __progname, conffile); exit(1); @@ -159,8 +160,10 @@ main(int argc, char **argv) update(CMODE); /* user startup file. */ - if ((cp = startupfile(NULL, conffile)) != NULL) - (void)load(cp); + if (cp) { + (void)load(ffp, cp); + ffclose(ffp, NULL); + } if (batch) return (0); Index: ttykbd.c =================================================================== RCS file: /home/cvs/src/usr.bin/mg/ttykbd.c,v retrieving revision 1.21 diff -u -p -r1.21 ttykbd.c --- ttykbd.c 30 Mar 2023 08:07:07 -0000 1.21 +++ ttykbd.c 30 Mar 2023 11:04:59 -0000 @@ -31,6 +31,7 @@ char *keystrings[] = {NULL}; void ttykeymapinit(void) { + FILE *ffp; char *cp; /* Bind keypad function keys. */ @@ -57,10 +58,11 @@ ttykeymapinit(void) if (key_dc) dobindkey(fundamental_map, "delete-char", key_dc); - if ((cp = getenv("TERM"))) { - if (((cp = startupfile(cp, NULL)) != NULL) && - (load(cp) != TRUE)) + if ((cp = getenv("TERM")) != NULL && + (cp = startupfile(&ffp, cp, NULL)) != NULL) { + if (load(ffp, cp) != TRUE) ewprintf("Error reading key initialization file"); + (void)ffclose(ffp, NULL); } if (keypad_xmit) /* turn on keypad */