Reformated comments and long lines
[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                 /* Ummm, why do we want to avoid creating directories with the effective
83                    user ID?  None of the nmh tools are installed such that the effective
84                    should be different from the real, and if some parent process made
85                    the two be different, I don't see why it should be our job to enforce
86                    the real UID.  Also, why the heck do we call the mkdir executable
87                    rather than the library function in this case??  If we do want to
88                    call the mkdir executable, we should at least be giving it -p (and
89                    change the single chmod() call below) so it can successfully create
90                    nested directories like the above code can.
91
92                    -- Dan Harkless <dan-nmh@dilvish.speed.net> */
93                 switch (pid = vfork()) {
94                         case -1:
95                                 advise ("fork", "unable to");
96                                 return 0;
97
98                         case 0:
99                                 setgid (getgid ());
100                                 setuid (getuid ());
101
102                                 execl ("/bin/mkdir", "mkdir", dir, NULL);
103                                 execl ("/usr/bin/mkdir", "mkdir", dir, NULL);
104                                 fprintf (stderr, "unable to exec ");
105                                 perror ("mkdir");
106                                 _exit (-1);
107
108                         default:
109                                 if (pidXwait(pid, "mkdir"))
110                                         return 0;
111                                 break;
112                 }
113
114                 chmod (dir, folder_perms);
115         }
116
117         umask(saved_umask);  /* put the user's umask back */
118
119         if (had_an_error)
120                 return 0;  /* opposite of UNIX error return convention */
121         else
122                 return 1;
123 }