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