Change to the linux kernel coding style
[wmaker-crm.git] / util / wmsetup.c
1 /* wmsetup.c- create wmaker config file dir structure and copy default
2  *      config files.
3  *
4  *  Copyright (c) 2000-2003 Alfredo K. Kojima
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 #if 1
21 int main()
22 {
23 }
24 #else
25 #define PROG_VERSION "wmsetup 0.0 (Window Maker)"
26
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <unistd.h>
30
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34
35 #include <WINGs/WINGs.h>
36
37 #include "../src/config.h"
38
39 char *RequiredDirectories[] = {
40         "/Defaults",
41         "/Library",
42         "/Library/Icons",
43         "/Library/WindowMaker",
44         "/Library/WindowMaker/Backgrounds",
45         "/Library/WindowMaker/IconSets",
46         "/Library/WindowMaker/Pixmaps",
47         "/Library/WindowMaker/CachedPixmaps",
48         "/Library/WindowMaker/SoundSets",
49         "/Library/WindowMaker/Sounds",
50         "/Library/WindowMaker/Styles",
51         "/Library/WindowMaker/Themes",
52         "/Library/WindowMaker/WPrefs",
53         NULL
54 };
55
56 char *RequiredFiles[] = {
57         "/Defaults/WindowMaker",
58         "/Defaults/WMWindowAttributes",
59         NULL
60 };
61
62 WMScreen *scr;
63
64 #define wlog wwarning
65
66 #if 0
67 void wlog(const char *msg, ...)
68 {
69         va_list args;
70         char buf[MAXLINE];
71
72         va_start(args, msg);
73
74         vsprintf(buf, msg, args);
75         puts(buf);
76
77         va_end(args);
78 }
79 #endif
80
81 void alert(const char *msg, ...)
82 {
83         va_list args;
84         char buffer[2048];
85
86         va_start(args, msg);
87
88         vsprintf(buf, msg, args);
89
90         WMRunAlertPanel(scr, NULL, _("Error"), buffer, _("OK"), NULL, NULL);
91
92         va_end(args);
93 }
94
95 Bool ask(char *title, char *yes, char *no, const char *msg, ...)
96 {
97         va_list args;
98         char buffer[2048];
99
100         va_start(args, msg);
101
102         vsprintf(buf, msg, args);
103
104         WMRunAlertPanel(scr, NULL, title, buffer, yes, no, NULL);
105
106         va_end(args);
107 }
108
109 char *renameName(char *path)
110 {
111         char *buf = wmalloc(strlen(path) + 8);
112         int i;
113
114         sprintf(buf, "%s~", path);
115
116         if (access(buf, F_OK) < 0) {
117                 return buf;
118         }
119
120         for (i = 0; i < 10; i++) {
121                 sprintf(buf, "%s~%i", path, i);
122
123                 if (access(buf, F_OK) < 0) {
124                         return buf;
125                 }
126         }
127
128         sprintf(buf, "%s~", path);
129
130         return buf;
131 }
132
133 void showFileError(int error, Bool directory, char *path)
134 {
135         switch (error) {
136         case EACCESS:
137                 if (directory) {
138                         alert(_("The directory %s needs to be fully accessible, but is\n"
139                                 "not. Make sure all of it's parent directories have\n"
140                                 "read and execute permissions set."), path);
141                 } else {
142                         alert(_("The file %s needs to be fully accessible, but is not.\n"
143                                 "Make sure it has read and write permissions set and\n"
144                                 "all of it's parent directories have read and execute\n" "permissions."), path);
145                 }
146                 break;
147
148         case EROFS:
149                 alert(_("The %s %s is in a read-only file system, but it needs to be\n"
150                         "writable. Start wmaker with the --static command line option."),
151                       directory ? _("directory") : _("file"), path);
152                 break;
153
154         default:
155                 alert(_("An error occurred while accessing the %s %s. Please make sure\n"
156                         "it exists and is accessible.\n%s"),
157                       directory ? _("directory") : _("file"), path, wstrerror(error));
158                 break;
159         }
160 }
161
162 Bool checkDir(char *path, Bool fatal)
163 {
164         if (access(path, F_OK) < 0) {
165                 if (mkdir(path, 0775) < 0) {
166                         alert(_("could not create directory %s\n%s"), path, wstrerror(errno));
167                         return False;
168                 } else {
169                         wlog(_("created directory %s"), path);
170                 }
171         }
172
173         if (access(path, R_OK | W_OK | X_OK) == 0) {
174                 return True;
175         }
176         wsyserror("bad access to directory %s", path);
177
178         if (!fatal) {
179                 struct stat buf;
180
181                 if (stat(path, &buf) < 0) {
182                         alert(_("The directory %s could not be stat()ed. Please make sure\n"
183                                 "it exists and is accessible."), path);
184                         return False;
185                 }
186
187                 if (!S_ISDIR(buf)) {
188                         char *newName = renameName(path);
189
190                         if (ask(_("Rename"), _("OK"), _("Cancel"),
191                                 _("A directory named %s needs to be created but a file with\n"
192                                   "the same name already exists. The file will be renamed to\n"
193                                   "%s and the directory will be created."), path, newName)) {
194
195                                 if (rename(path, newName) < 0) {
196                                         alert(_("Could not rename %s to %s:%s"), path, newName, wstrerror(errno));
197                                 }
198                         }
199                         wfree(newName);
200
201                         return False;
202                 }
203                 if (!(buf.st_mode & S_IRWXU)) {
204                         if (chmod(path, (buf.st_mode & 00077) | 7) < 0) {
205                                 return False;
206                         }
207                 }
208
209                 return checkDir(path, True);
210         }
211
212         showFileError(errno, True, path);
213
214         return False;
215 }
216
217 Bool checkFile(char *path)
218 {
219         if (access(path, F_OK | R_OK | W_OK) == 0) {
220                 return True;
221         }
222
223         showFileError(errno, False, path);
224
225         return False;
226 }
227
228 Bool checkCurrentSetup(char *home)
229 {
230         char path[1024];
231         char *p;
232
233         if (!checkDir(home, False)) {
234                 wlog("couldnt make directory %s", home);
235                 return False;
236         }
237
238         for (p = RequiredDirectories; p != NULL; p++) {
239                 sprintf(path, "%s%s", home, p);
240                 if (!checkDir(p, False)) {
241                         wlog("couldnt make directory %s", p);
242                         return False;
243                 }
244         }
245
246         for (p = RequiredFiles; p != NULL; p++) {
247                 sprintf(path, "%s%s", home, p);
248                 if (!checkFile(p, False)) {
249                         return False;
250                 }
251         }
252
253         return True;
254 }
255
256 Bool copyAllFiles(char *gsdir)
257 {
258         FILE *f;
259         char path[2048];
260         char file[256];
261         char target[2048];
262
263         /* copy misc data files */
264
265         sprintf(path, "%s/USER_FILES", DATADIR);
266
267         f = fopen(path, "rb");
268         while (!feof(f)) {
269                 if (!fgets(file, 255, f)) {
270                         break;
271                 }
272                 sprintf(path, "%s/%s", DATADIR, file);
273                 sprintf(target, "%s/Library/WindowMaker/%s", gsdir, file);
274                 if (!copyFile(path, target)) {
275                         return False;
276                 }
277         }
278         fclose(f);
279
280         /* copy auto{start,finish} scripts */
281
282         /* select and copy menu */
283
284         /* copy Defaults stuff */
285
286         sprintf(path, "%s/USER_FILES", ETCDIR);
287
288         f = fopen(path, "rb");
289         while (!feof(f)) {
290                 if (!fgets(path, 255, f)) {
291                         break;
292                 }
293                 sprintf(path, "%s/%s", ETCDIR, file);
294                 sprintf(target, "%s/Defaults/%s", gsdir, file);
295                 if (!copyFile(path, target)) {
296                         return False;
297                 }
298         }
299         fclose(f);
300
301         /* setup .xinitrc */
302
303 }
304
305 void showFinishSplash(char *gsdir)
306 {
307 #if 0
308         WMWindow *win;
309
310         win = WMCreateWindow(scr, "finished");
311 #endif
312 }
313
314 int main(int argc, char **argv)
315 {
316         Display *dpy;
317         char *gsdir;
318         int i;
319
320         for (i = 1; i < argc; i++) {
321                 if (strcmp(argv[i], "-display") == 0) {
322                         i++;
323                         if (i >= argc) {
324                                 wwarning(_("too few arguments for %s"), argv[i - 1]);
325                                 exit(0);
326                         }
327                         DisplayName = argv[i];
328                 } else if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "--version") == 0) {
329                         puts(PROG_VERSION);
330                         exit(0);
331                 }
332         }
333
334         WMInitializeApplication("WMSetup", &argc, argv);
335
336         dpy = XOpenDisplay("");
337         if (!dpy) {
338                 printf("could not open display\n");
339                 exit(1);
340         }
341
342         scr = WMCreateScreen(dpy, DefaultScreen(dpy));
343
344         gsdir = wusergnusteppath();
345
346         /* check directory structure and copy files */
347         if (access(gsdir, F_OK) != 0) {
348                 if (!ask(_("Window Maker"), _("OK"), _("Cancel"),
349                          _("Window Maker will create a directory named %s, where\n"
350                            "it will store it's configuration files and other data."), gsdir)) {
351                         alert(_("Window Maker will be started in 'static' mode, where\n"
352                                 "it will use default configuration and will not write\n"
353                                 "any information to disk."));
354                         return 1;
355                 }
356         }
357
358         if (checkCurrentSetup(gsdir)) {
359                 printf(_("%s: wmaker configuration files already installed\n"), argv[0]);
360                 return 0;
361         }
362
363         if (!copyAllFiles(gsdir)) {
364                 alert(_("An error occurred while doing user specific setup of\n"
365                         "Window Maker. It will be started in 'static' mode, where\n"
366                         "the default configuration will be used and it will not write\n"
367                         "any information to disk."));
368                 return 1;
369         }
370
371         showFinishSplash(gsdir);
372
373         return 0;
374 }
375 #endif