Rearranged whitespace (and comments) in all the code!
[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         /* Because mh-profile.man documents "Folder-Protect:" as an octal constant,
35            and we don't want to force the user to remember to include a leading
36            zero, we call atooi(folder_perms_ASCII) here rather than
37            strtoul(folder_perms_ASCII, NULL, 0).  Therefore, if anyone ever tries to
38            specify a mode in say, hex, they'll get garbage.  (I guess nmh uses its
39            atooi() function rather than calling strtoul() with a radix of 8 because
40            some ancient platforms are missing that functionality. */
41         folder_perms = atooi(folder_perms_ASCII);
42
43         /* Folders have definite desired permissions that are set -- we don't want
44            to interact with the umask.  Clear it temporarily. */
45         saved_umask = umask(0);
46
47         if (getuid () == geteuid ()) {
48                 c = strncpy(path, dir, sizeof(path));
49
50                 while (!had_an_error && (c = strchr((c + 1), '/')) != NULL) {
51                         *c = (char)0;
52                         if (access(path, X_OK)) {
53                                 if (errno != ENOENT){
54                                         advise (dir, "unable to create directory");
55                                         had_an_error = 1;
56                                 }
57                                 /* Create an outer directory. */
58                                 if (mkdir(path, folder_perms)) {
59                                         advise (dir, "unable to create directory");
60                                         had_an_error = 1;
61                                 }
62                         }
63                         *c = '/';
64                 }
65
66                 if (!had_an_error) {
67                         /* Create the innermost nested subdirectory of the
68                          * path we're being asked to create. */
69                         if (mkdir (dir, folder_perms) == -1) {
70                                 advise (dir, "unable to create directory");
71                                 had_an_error = 1;
72                         }
73                 }
74         } else {
75                 /* Ummm, why do we want to avoid creating directories with the effective
76                    user ID?  None of the nmh tools are installed such that the effective
77                    should be different from the real, and if some parent process made
78                    the two be different, I don't see why it should be our job to enforce
79                    the real UID.  Also, why the heck do we call the mkdir executable
80                    rather than the library function in this case??  If we do want to
81                    call the mkdir executable, we should at least be giving it -p (and
82                    change the single chmod() call below) so it can successfully create
83                    nested directories like the above code can.
84
85                    -- Dan Harkless <dan-nmh@dilvish.speed.net> */
86                 switch (pid = vfork()) {
87                         case -1:
88                                 advise ("fork", "unable to");
89                                 return 0;
90
91                         case 0:
92                                 setgid (getgid ());
93                                 setuid (getuid ());
94
95                                 execl ("/bin/mkdir", "mkdir", dir, NULL);
96                                 execl ("/usr/bin/mkdir", "mkdir", dir, NULL);
97                                 fprintf (stderr, "unable to exec ");
98                                 perror ("mkdir");
99                                 _exit (-1);
100
101                         default:
102                                 if (pidXwait(pid, "mkdir"))
103                                         return 0;
104                                 break;
105                 }
106
107                 chmod (dir, folder_perms);
108         }
109
110         umask(saved_umask);  /* put the user's umask back */
111
112         if (had_an_error)
113                 return 0;  /* opposite of UNIX error return convention */
114         else
115                 return 1;
116 }