1 /* $OpenBSD: dir.c,v 1.31 2019/06/28 13:35:02 deraadt Exp $ */ 2 3 /* This file is in the public domain. */ 4 5 /* 6 * Name: MG 2a 7 * Directory management functions 8 * Created: Ron Flax (ron@vsedev.vse.com) 9 * Modified for MG 2a by Mic Kaczmarczik 03-Aug-1987 10 */ 11 12 #include <sys/queue.h> 13 #include <sys/stat.h> 14 #include <signal.h> 15 #include <stdio.h> 16 #include <string.h> 17 #include <unistd.h> 18 19 #include "def.h" 20 21 static char mgcwd[NFILEN]; 22 23 /* 24 * Initialize anything the directory management routines need. 25 */ 26 void 27 dirinit(void) 28 { 29 mgcwd[0] = '\0'; 30 if (getcwd(mgcwd, sizeof(mgcwd)) == NULL) 31 ewprintf("Can't get current directory!"); 32 if (mgcwd[0] != '\0' && !(mgcwd[0] == '/' && mgcwd[1] == '\0')) 33 (void)strlcat(mgcwd, "/", sizeof(mgcwd)); 34 } 35 36 /* 37 * Change current working directory. 38 */ 39 /* ARGSUSED */ 40 int 41 changedir(int f, int n) 42 { 43 char bufc[NFILEN], *bufp; 44 45 (void)strlcpy(bufc, mgcwd, sizeof(bufc)); 46 if ((bufp = eread("Change default directory: ", bufc, NFILEN, 47 EFDEF | EFNEW | EFCR | EFFILE)) == NULL) 48 return (ABORT); 49 else if (bufp[0] == '\0') 50 return (FALSE); 51 /* Append trailing slash */ 52 if (chdir(bufc) == -1) { 53 dobeep(); 54 ewprintf("Can't change dir to %s", bufc); 55 return (FALSE); 56 } 57 if ((bufp = getcwd(mgcwd, sizeof(mgcwd))) == NULL) { 58 if (bufc[0] == '/') 59 (void)strlcpy(mgcwd, bufc, sizeof(mgcwd)); 60 else 61 (void)strlcat(mgcwd, bufc, sizeof(mgcwd)); 62 } 63 if (mgcwd[strlen(mgcwd) - 1] != '/') 64 (void)strlcat(mgcwd, "/", sizeof(mgcwd)); 65 ewprintf("Current directory is now %s", mgcwd); 66 return (TRUE); 67 } 68 69 /* 70 * Show current directory. 71 */ 72 /* ARGSUSED */ 73 int 74 showcwdir(int f, int n) 75 { 76 ewprintf("Current directory: %s", mgcwd); 77 return (TRUE); 78 } 79 80 int 81 getcwdir(char *buf, size_t len) 82 { 83 if (strlcpy(buf, mgcwd, len) >= len) 84 return (FALSE); 85 86 return (TRUE); 87 } 88 89 /* Create the directory and it's parents. */ 90 /* ARGSUSED */ 91 int 92 makedir(int f, int n) 93 { 94 return (ask_makedir()); 95 } 96 97 int 98 ask_makedir(void) 99 { 100 101 char bufc[NFILEN]; 102 char *path; 103 104 if (getbufcwd(bufc, sizeof(bufc)) != TRUE) 105 return (ABORT); 106 if ((path = eread("Make directory: ", bufc, NFILEN, 107 EFDEF | EFNEW | EFCR | EFFILE)) == NULL) 108 return (ABORT); 109 else if (path[0] == '\0') 110 return (FALSE); 111 112 return (do_makedir(path)); 113 } 114 115 int 116 do_makedir(char *path) 117 { 118 struct stat sb; 119 int finished, ishere; 120 mode_t dir_mode, f_mode, oumask; 121 char *slash; 122 123 if ((path = adjustname(path, TRUE)) == NULL) 124 return (FALSE); 125 126 /* Remove trailing slashes */ 127 slash = strrchr(path, '\0'); 128 while (--slash > path && *slash == '/') 129 *slash = '\0'; 130 131 slash = path; 132 133 oumask = umask(0); 134 f_mode = 0777 & ~oumask; 135 dir_mode = f_mode | S_IWUSR | S_IXUSR; 136 137 for (;;) { 138 slash += strspn(slash, "/"); 139 slash += strcspn(slash, "/"); 140 141 finished = (*slash == '\0'); 142 *slash = '\0'; 143 144 ishere = !stat(path, &sb); 145 if (finished && ishere) { 146 dobeep(); 147 ewprintf("Cannot create directory %s: file exists", 148 path); 149 return(FALSE); 150 } else if (!finished && ishere && S_ISDIR(sb.st_mode)) { 151 *slash = '/'; 152 continue; 153 } 154 155 if (mkdir(path, finished ? f_mode : dir_mode) == 0) { 156 if (f_mode > 0777 && chmod(path, f_mode) == -1) { 157 umask(oumask); 158 return (ABORT); 159 } 160 } else { 161 if (!ishere || !S_ISDIR(sb.st_mode)) { 162 if (!ishere) { 163 dobeep(); 164 ewprintf("Creating directory: " 165 "permission denied, %s", path); 166 } else 167 eerase(); 168 169 umask(oumask); 170 return (FALSE); 171 } 172 } 173 174 if (finished) 175 break; 176 177 *slash = '/'; 178 } 179 180 eerase(); 181 umask(oumask); 182 return (TRUE); 183 } 184