xref: /openbsd/usr.bin/mg/dir.c (revision d89ec533)
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