1/* $OpenBSD: dir.c,v 1.33 2023/03/08 04:43:11 guenther 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 21static char mgcwd[NFILEN]; 22 23/* 24 * Initialize anything the directory management routines need. 25 */ 26void 27dirinit(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 */ 39int 40changedir(int f, int n) 41{ 42 char bufc[NFILEN], *bufp; 43 44 (void)strlcpy(bufc, mgcwd, sizeof(bufc)); 45 if ((bufp = eread("Change default directory: ", bufc, NFILEN, 46 EFDEF | EFNEW | EFCR | EFFILE)) == NULL) 47 return (ABORT); 48 else if (bufp[0] == '\0') 49 return (FALSE); 50 /* Append trailing slash */ 51 if (chdir(bufc) == -1) { 52 dobeep(); 53 ewprintf("Can't change dir to %s", bufc); 54 return (FALSE); 55 } 56 if ((bufp = getcwd(mgcwd, sizeof(mgcwd))) == NULL) { 57 if (bufc[0] == '/') 58 (void)strlcpy(mgcwd, bufc, sizeof(mgcwd)); 59 else 60 (void)strlcat(mgcwd, bufc, sizeof(mgcwd)); 61 } 62 if (mgcwd[strlen(mgcwd) - 1] != '/') 63 (void)strlcat(mgcwd, "/", sizeof(mgcwd)); 64 ewprintf("Current directory is now %s", mgcwd); 65 return (TRUE); 66} 67 68/* 69 * Show current directory. 70 */ 71int 72showcwdir(int f, int n) 73{ 74 ewprintf("Current directory: %s", mgcwd); 75 return (TRUE); 76} 77 78int 79getcwdir(char *buf, size_t len) 80{ 81 if (strlcpy(buf, mgcwd, len) >= len) 82 return (FALSE); 83 84 return (TRUE); 85} 86 87/* Create the directory and its parents. */ 88int 89makedir(int f, int n) 90{ 91 return (ask_makedir()); 92} 93 94int 95ask_makedir(void) 96{ 97 98 char bufc[NFILEN]; 99 char *path; 100 101 if (getbufcwd(bufc, sizeof(bufc)) != TRUE) 102 return (ABORT); 103 if ((path = eread("Make directory: ", bufc, NFILEN, 104 EFDEF | EFNEW | EFCR | EFFILE)) == NULL) 105 return (ABORT); 106 else if (path[0] == '\0') 107 return (FALSE); 108 109 return (do_makedir(path)); 110} 111 112int 113do_makedir(char *path) 114{ 115 struct stat sb; 116 int finished, ishere; 117 mode_t dir_mode, f_mode, oumask; 118 char *slash; 119 120 if ((path = adjustname(path, TRUE)) == NULL) 121 return (FALSE); 122 123 /* Remove trailing slashes */ 124 slash = strrchr(path, '\0'); 125 while (--slash > path && *slash == '/') 126 *slash = '\0'; 127 128 slash = path; 129 130 oumask = umask(0); 131 f_mode = 0777 & ~oumask; 132 dir_mode = f_mode | S_IWUSR | S_IXUSR; 133 134 for (;;) { 135 slash += strspn(slash, "/"); 136 slash += strcspn(slash, "/"); 137 138 finished = (*slash == '\0'); 139 *slash = '\0'; 140 141 ishere = !stat(path, &sb); 142 if (finished && ishere) { 143 dobeep(); 144 ewprintf("Cannot create directory %s: file exists", 145 path); 146 return(FALSE); 147 } else if (!finished && ishere && S_ISDIR(sb.st_mode)) { 148 *slash = '/'; 149 continue; 150 } 151 152 if (mkdir(path, finished ? f_mode : dir_mode) == 0) { 153 if (f_mode > 0777 && chmod(path, f_mode) == -1) { 154 umask(oumask); 155 return (ABORT); 156 } 157 } else { 158 if (!ishere || !S_ISDIR(sb.st_mode)) { 159 if (!ishere) { 160 dobeep(); 161 ewprintf("Creating directory: " 162 "permission denied, %s", path); 163 } else 164 eerase(); 165 166 umask(oumask); 167 return (FALSE); 168 } 169 } 170 171 if (finished) 172 break; 173 174 *slash = '/'; 175 } 176 177 eerase(); 178 umask(oumask); 179 return (TRUE); 180} 181