Removed the space between function names and the opening parenthesis.
[mmh] / sbr / makedir.c
1 /*
2 ** makedir.c -- make a directory
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 /*
10 ** Modified to try recursive create.
11 */
12
13 #include <h/mh.h>
14 #include <errno.h>
15 #include <sys/param.h>
16 #include <sys/file.h>
17
18 int
19 makedir(char *dir)
20 {
21         char path[PATH_MAX];
22         char* folder_perms_ASCII;
23         int had_an_error = 0;
24         mode_t folder_perms, saved_umask;
25         pid_t pid;
26         register char* c;
27
28         context_save();  /* save the context file */
29         fflush(stdout);
30
31         if (!(folder_perms_ASCII = context_find("folder-protect")))
32                 folder_perms_ASCII = foldprot;  /* defaults to "700" */
33
34         /*
35         ** Because mh-profile.man documents "Folder-Protect:" as an octal
36         ** constant, and we don't want to force the user to remember to
37         ** include a leading zero, we call atooi(folder_perms_ASCII) here
38         ** rather than strtoul(folder_perms_ASCII, NULL, 0).  Therefore,
39         ** if anyone ever tries to specify a mode in say, hex, they'll
40         ** get garbage.  (I guess nmh uses its atooi() function rather
41         ** than calling strtoul() with a radix of 8 because some ancient
42         ** platforms are missing that functionality.
43         */
44         folder_perms = atooi(folder_perms_ASCII);
45
46         /*
47         ** Folders have definite desired permissions that are set -- we
48         ** don't want to interact with the umask.  Clear it temporarily.
49         */
50         saved_umask = umask(0);
51
52         if (getuid() == geteuid()) {
53                 c = strncpy(path, dir, sizeof(path));
54
55                 while (!had_an_error && (c = strchr((c + 1), '/')) != NULL) {
56                         *c = (char)0;
57                         if (access(path, X_OK)) {
58                                 if (errno != ENOENT){
59                                         advise(dir, "unable to create directory");
60                                         had_an_error = 1;
61                                 }
62                                 /* Create an outer directory. */
63                                 if (mkdir(path, folder_perms)) {
64                                         advise(dir, "unable to create directory");
65                                         had_an_error = 1;
66                                 }
67                         }
68                         *c = '/';
69                 }
70
71                 if (!had_an_error) {
72                         /*
73                         ** Create the innermost nested subdirectory of the
74                         ** path we're being asked to create.
75                         */
76                         if (mkdir(dir, folder_perms) == -1) {
77                                 advise(dir, "unable to create directory");
78                                 had_an_error = 1;
79                         }
80                 }
81         } else {
82                 /*
83                 ** Ummm, why do we want to avoid creating directories
84                 ** with the effective user ID?  None of the nmh tools are
85                 ** installed such that the effective should be different
86                 ** from the real, and if some parent process made the two
87                 ** be different, I don't see why it should be our job to
88                 ** enforce the real UID.  Also, why the heck do we call
89                 ** the mkdir executable rather than the library function in
90                 ** this case??  If we do want to call the mkdir executable,
91                 ** we should at least be giving it -p (and change the single
92                 ** chmod() call below) so it can successfully create nested
93                 ** directories like the above code can.
94                 ** -- Dan Harkless <dan-nmh@dilvish.speed.net>
95                 */
96                 switch (pid = vfork()) {
97                         case -1:
98                                 advise("fork", "unable to");
99                                 return 0;
100
101                         case 0:
102                                 setgid(getgid());
103                                 setuid(getuid());
104
105                                 execl("/bin/mkdir", "mkdir", dir, NULL);
106                                 execl("/usr/bin/mkdir", "mkdir", dir, NULL);
107                                 fprintf(stderr, "unable to exec ");
108                                 perror("mkdir");
109                                 _exit(-1);
110
111                         default:
112                                 if (pidXwait(pid, "mkdir"))
113                                         return 0;
114                                 break;
115                 }
116
117                 chmod(dir, folder_perms);
118         }
119
120         umask(saved_umask);  /* put the user's umask back */
121
122         if (had_an_error)
123                 return 0;  /* opposite of UNIX error return convention */
124         else
125                 return 1;
126 }