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
21 static char mgcwd[NFILEN];
22
23 /*
24 * Initialize anything the directory management routines need.
25 */
26 void
dirinit(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 int
changedir(int f,int n)40 changedir(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 */
71 int
showcwdir(int f,int n)72 showcwdir(int f, int n)
73 {
74 ewprintf("Current directory: %s", mgcwd);
75 return (TRUE);
76 }
77
78 int
getcwdir(char * buf,size_t len)79 getcwdir(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. */
88 int
makedir(int f,int n)89 makedir(int f, int n)
90 {
91 return (ask_makedir());
92 }
93
94 int
ask_makedir(void)95 ask_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
112 int
do_makedir(char * path)113 do_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