1 /*
2 * Copyright (C) 1997 Red Hat Software, Inc.
3 * Written for afterstep by Cristian Gafton <gafton@redhat.com>
4 * Modified for KDE by Kevin Vajk <kvajk@ricochet.net>
5 *
6 * Modify: 2015/11/26 Tommy Scheunemann <net@arrishq.net>
7 *
8 * Modify: 2014/01/07 Tommy Scheunemann <net@arrishq.net>
9 *
10 * Modify: 2013/07/03 Tommy Scheunemann <net@arrishq.net>
11 *
12 * Modify: 2013/03/19 Tommy Scheunemann <net@arrishq.net>
13 *
14 * Modify: 2013/01/06 Tommy Scheunemann <net@arrishq.net>
15 *
16 * Modify: 2012/12/18 Tommy Scheunemann <net@arrishq.net>
17 *
18 * Modify: 2010/12/27 Tommy Scheunemann <net@arrishq.net>
19 *
20 * Modify: 2008/21/01 Tommy Scheunemann <net@arrishq.net>
21 *
22 * Modify: 2006/24/10 Tommy Scheunemann <net@arrishq.net>
23 *
24 * Modify: 2005/12/10 Tommy Scheunemann <net@arrishq.net>
25 *
26 * Modify: 2005/01/11 Tommy Scheunemann <net@arrishq.net>
27 *
28 * Modify: 2004/08/09 Tommy Scheunemann <net@arrishq.net>
29 *
30 * Modify: 2004/07/10 Tommy Scheunemann <net@arrishq.net>
31 *
32 * Modify: 2003/11/19 Tommy Scheunemann <net@arrishq.org>
33 *
34 *
35 * This program is free software; you can redistribute it and/or modify
36 * it under the terms of the GNU General Public License as published by
37 * the Free Software Foundation; either version 2 of the License, or
38 * (at your option) any later version.
39 *
40 * This program is distributed in the hope that it will be useful,
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 * GNU General Public License for more details.
44 *
45 * You should have received a copy of the GNU General Public License
46 * along with this program; if not, write to the Free Software
47 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
48 */
49
50 /*
51 * Functions needed for producing a KDE directory hierarchy
52 * configuration
53 *
54 * In this case the rootmenu is the top level directory
55 */
56
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <sys/types.h>
60 #include <sys/stat.h>
61 #include <fcntl.h>
62 #include <unistd.h>
63 #include <dirent.h>
64 #include <errno.h>
65 #include <string.h>
66 #include <ctype.h>
67 #include <pwd.h>
68 #include <strings.h>
69
70 #include "wmconfig.h"
71 #include "prototypes.h"
72 #include "package.h"
73
74 #if (defined(__unix__) || defined(unix)) && !defined(USG)
75 #include <limits.h>
76 #include <sys/param.h>
77 #endif
78
79 #define KDE_DIR ".kde/share/applnk/wmconfig"
80 #define KDE_MENU_ICON "package.xpm"
81
82 extern const char *root_menu_name;
83 extern const char *output_directory;
84 extern unsigned int flags;
85
create_kdelnk(const char * file,struct package * app)86 static void create_kdelnk(const char *file, struct package *app)
87 {
88 int fd;
89 FILE *f;
90
91 if (app == (struct package *)NULL) {
92 return;
93 }
94
95 /* KDE does not like starting things in the background */
96 if (app->exec != NULL) {
97 char *p;
98 p = strrchr(app->exec, '&');
99 if (p != NULL) {
100 *p = '\0';
101 }
102 }
103
104 /* At the very least we need a filename and command to execute: */
105 if (file == NULL || app->exec == NULL || app->restart) {
106 return;
107 }
108
109 fd = open(file, O_CREAT | O_EXCL | O_RDWR, 0600);
110 f = fdopen (fd, "wx");
111 if (f == (FILE *) NULL) {
112 fprintf(stderr, gettext ("Could not create file %s\n"), file);
113 perror("Error code");
114 return;
115 }
116
117 /* Write the .kdelnk file: */
118 fprintf(f, "# KDE Config File\n");
119 fprintf(f, "[KDE Desktop Entry]\n");
120 if (app->name != NULL) {
121 fprintf(f, "Name=%s\n", app->name);
122 }
123 if ((app->icon != NULL) && (!is_set(NO_ICONS))) {
124 fprintf(f, "Icon=%s\n", app->icon);
125 }
126 if ((app->mini_icon != NULL) && (!is_set(NO_MINI_ICONS))) {
127 fprintf(f, "MiniIcon=%s\n", app->mini_icon);
128 }
129 if (app->description != NULL) {
130 fprintf(f, "Comment=%s\n", app->description);
131 }
132 if (app->terminal != NULL) {
133 fprintf(f, "Terminal=true\n");
134 }
135 fprintf(f, "Exec=%s\n", app->exec);
136 fprintf(f, "Type=Application\n");
137
138 /* Mimetype Support */
139 if (app->mimetype != NULL) {
140 fprintf(f, "MimeType=%s;\n", app->mimetype);
141 }
142 fclose(f);
143 }
144
145 /* Like mkdir -p */
make_directory_path(const char * path)146 static void make_directory_path(const char *path)
147 {
148 char buf[PATH_MAX];
149 int pi=0;
150 int bi=0;
151 while( path[pi] != '\0' ) {
152 buf[bi] = path[pi];
153 bi++ ; pi++ ;
154 buf[bi] = '\0';
155 if ( path[pi] == '\0' || path[pi] == '/' ) {
156 mkdir(buf, 0700);
157 }
158 }
159 }
160
161
create_kde_menu_directory(const char * directory,const char * name)162 static void create_kde_menu_directory(const char *directory, const char *name)
163 {
164 char dot_directory[PATH_MAX+1];
165 int fd;
166 FILE *f;
167
168 make_directory_path(directory);
169 snprintf(dot_directory, sizeof(dot_directory), "%s/.directory", directory);
170 fd = open(dot_directory, O_CREAT | O_EXCL | O_RDWR, 0600);
171 f = fdopen (fd, "wx");
172 if (f == (FILE *) NULL) {
173 fprintf(stderr, gettext ("Could not create file %s\n"), dot_directory);
174 perror("Error code");
175 return;
176 }
177 fprintf(f, "# KDE Config File\n");
178 fprintf(f, "[KDE Desktop Entry]\n");
179 fprintf(f, "Icon=%s\n", KDE_MENU_ICON);
180 fprintf(f, "Name=%s\n", name);
181 fclose(f);
182 }
183
make_dir(struct group * root,int level,const char * dir_name)184 static void make_dir(struct group *root, int level, const char *dir_name)
185 {
186 struct item *item;
187 char c_tmp[PATH_MAX];
188
189 if (root == (struct group *)NULL) {
190 return;
191 }
192
193 item = root->items;
194 while (item->type != 0) {
195 if (item->type == ITEM_MENU) {
196 struct group *tmp;
197
198 tmp = (struct group *)item->data;
199 snprintf(c_tmp, sizeof(c_tmp), "%s/%s", single_string(dir_name), single_string(tmp->name) );
200 create_kde_menu_directory(c_tmp, tmp->name);
201 } else if (item->type == ITEM_APP) {
202 struct package *app;
203
204 app = (struct package *)item->data;
205 if (app->name && app->exec) {
206 snprintf(c_tmp, sizeof(c_tmp), "%s/%s.kdelnk", single_string(dir_name), single_string(app->name) );
207 create_kdelnk(c_tmp, app);
208 }
209 }
210 item++;
211 }
212 /* second pass, recursive output... */
213 item = root->items;
214 while (item->type != 0) {
215 if (item->type == ITEM_MENU) {
216 struct group *tmp;
217
218 tmp = (struct group *)item->data;
219 snprintf(c_tmp, sizeof(c_tmp), "%s/%s", dir_name, tmp->name);
220 make_dir(item->data, level+1, c_tmp);
221 }
222 item++;
223 }
224 }
225
clean_dir(const char * dir_name)226 static void clean_dir(const char *dir_name)
227 {
228 struct dirent **namelist;
229 int nr_files;
230 int i;
231
232 if (dir_name == NULL) {
233 return;
234 }
235
236 /* read the whole directory in one pass */
237 nr_files = scandir(dir_name, &namelist, NULL, alphasort);
238 for (i = 0; i < nr_files; i++) {
239 if ( (strcmp(namelist[i]->d_name, ".") != 0) && (strcmp(namelist[i]->d_name, "..") != 0) ) {
240 struct stat st;
241 char tmp[PATH_MAX];
242 int retval;
243
244 snprintf(tmp, sizeof(tmp), "%s/%s", dir_name, namelist[i]->d_name);
245 if (stat(tmp, &st) != 0) {
246 fprintf(stderr, gettext ("Could not stat %s\n"), tmp);
247 return;
248 }
249 if (S_ISDIR(st.st_mode)) {
250 clean_dir(tmp);
251 retval = rmdir(tmp);
252 } else {
253 retval = unlink(tmp);
254 }
255 if (retval != 0) {
256 perror("Could not remove");
257 return;
258 }
259 }
260 free(namelist[i]);
261 }
262
263 if (nr_files && namelist) {
264 free(namelist);
265 }
266 }
267
268 /*
269 * Main function
270 */
output_kde(struct group * root)271 void output_kde(struct group *root)
272 {
273 struct stat st;
274 char root_dir[PATH_MAX];
275 struct passwd *pw = NULL;
276
277 pw = getpwuid(getuid());
278 if (pw == (struct passwd *)NULL) {
279 fprintf(stderr, gettext ("Could not find out who you are (getpwnam failed)!\n"));
280 return;
281 }
282
283 if (output_directory == NULL) {
284 snprintf(root_dir, sizeof(root_dir), "%s/%s", pw->pw_dir, KDE_DIR);
285 } else {
286 snprintf(root_dir, sizeof(root_dir), "%s", output_directory);
287 }
288
289 /* First, check if the root_dir already exists and remove it */
290 if (stat(root_dir, &st) == 0) {
291 /* that one exists */
292 if (!S_ISDIR(st.st_mode)) {
293 fprintf(stderr, gettext ("Error: %s exists but it is not a directory\n"), root_dir);
294 return;
295 }
296 clean_dir(root_dir);
297 rmdir(root_dir);
298 }
299 create_kde_menu_directory(root_dir, DEFAULT_ROOT_NAME);
300 make_dir(root, 0, root_dir);
301 }
302