r189: Effective permissions are shown in brackets.
[rox-filer.git] / ROX-Filer / src / support.c
blobb5f3e81abc2790d1b58f1fdc24a1f0a427de3815
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 1999, Thomas Leonard, <tal197@ecs.soton.ac.uk>.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* support.c - (non-GUI) useful routines */
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <ctype.h>
28 #include <sys/param.h>
29 #include <unistd.h>
30 #include <pwd.h>
31 #include <grp.h>
32 #include <fcntl.h>
33 #include <sys/wait.h>
34 #include <sys/stat.h>
36 #include <glib.h>
38 #include "main.h"
39 #include "support.h"
41 /* Static prototypes */
44 /* Like g_strdup, but does realpath() too (if possible) */
45 char *pathdup(char *path)
47 char real[MAXPATHLEN];
49 g_return_val_if_fail(path != NULL, NULL);
51 if (realpath(path, real))
52 return g_strdup(real);
54 return g_strdup(path);
57 /* Join the path to the leaf (adding a / between them) and
58 * return a pointer to a buffer with the result. Buffer is valid until
59 * the next call to make_path.
61 GString *make_path(char *dir, char *leaf)
63 static GString *buffer = NULL;
65 if (!buffer)
66 buffer = g_string_new(NULL);
68 g_return_val_if_fail(dir != NULL, buffer);
69 g_return_val_if_fail(leaf != NULL, buffer);
71 g_string_sprintf(buffer, "%s%s%s",
72 dir,
73 dir[0] == '/' && dir[1] == '\0' ? "" : "/",
74 leaf);
76 return buffer;
79 /* Return our complete host name */
80 char *our_host_name()
82 static char *name = NULL;
84 if (!name)
86 char buffer[4096];
88 g_return_val_if_fail(gethostname(buffer, 4096) == 0,
89 "localhost");
91 buffer[4095] = '\0';
92 name = g_strdup(buffer);
95 return name;
98 /* fork() and run a new program.
99 * Returns the new PID, or 0 on failure.
101 pid_t spawn(char **argv)
103 return spawn_full(argv, NULL);
106 /* As spawn(), but cd to dir first (if dir is non-NULL) */
107 pid_t spawn_full(char **argv, char *dir)
109 int child;
111 child = fork();
113 if (child == -1)
114 return 0; /* Failure */
115 else if (child == 0)
117 /* We are the child process */
118 if (dir)
119 if (chdir(dir))
120 fprintf(stderr, "chdir() failed: %s\n",
121 g_strerror(errno));
122 dup2(to_error_log, STDERR_FILENO);
123 fcntl(STDERR_FILENO, F_SETFD, 0);
124 execvp(argv[0], argv);
125 fprintf(stderr, "execvp(%s, ...) failed: %s\n",
126 argv[0],
127 g_strerror(errno));
128 _exit(0);
131 /* We are the parent */
132 return child;
135 void debug_free_string(void *data)
137 g_print("Freeing string '%s'\n", (char *) data);
138 g_free(data);
141 char *user_name(uid_t uid)
143 struct passwd *passwd;
144 GString *tmp;
145 char *retval;
147 passwd = getpwuid(uid);
148 if (passwd)
149 return passwd->pw_name;
150 tmp = g_string_new(NULL);
151 g_string_sprintf(tmp, "[%d]", (int) uid);
152 retval = tmp->str;
153 g_string_free(tmp, FALSE);
154 return retval;
157 char *group_name(gid_t gid)
159 struct group *group;
160 GString *tmp;
161 char *retval;
163 group = getgrgid(gid);
164 if (group)
165 return group->gr_name;
166 tmp = g_string_new(NULL);
167 g_string_sprintf(tmp, "[%d]", (int) gid);
168 retval = tmp->str;
169 g_string_free(tmp, FALSE);
170 return retval;
173 /* Return a string in the form '23Mb' in a static buffer valid until
174 * the next call.
176 char *format_size(unsigned long size)
178 static char *buffer = NULL;
179 char *units;
181 if (size >= PRETTY_SIZE_LIMIT)
183 size += 1023;
184 size >>= 10;
185 if (size >= PRETTY_SIZE_LIMIT)
187 size += 1023;
188 size >>= 10;
189 if (size >= PRETTY_SIZE_LIMIT)
191 size += 1023;
192 size >>= 10;
193 units = "Gb";
195 else
196 units = "Mb";
198 else
199 units = "K";
201 else
202 units = "bytes";
204 if (buffer)
205 g_free(buffer);
206 buffer = g_strdup_printf("%ld %s", size, units);
208 return buffer;
211 /* Fork and exec argv. Wait and return the child's exit status.
212 * -1 if spawn fails.
214 int fork_exec_wait(char **argv)
216 pid_t child;
217 int status = -1;
219 child = spawn_full(argv, NULL);
221 while (child)
223 if (waitpid(child, &status, 0) == -1)
225 if (errno != EINTR)
226 return -1;
228 else
229 break;
232 return status;
235 /* Converts a file's mode to a string. Result is a pointer
236 * to a static buffer, valid until the next call.
237 * uid and gid are for the file - the permissions that affect the
238 * filer will be highlighted.
240 char *pretty_permissions(uid_t uid, gid_t gid, mode_t m)
242 static char buffer[] = "(rwx),rwx,rwx/UGT";
243 int high;
245 if (uid == euid)
246 high = 0;
247 else if (gid == egid)
248 high = 1;
249 else
251 int i;
253 high = 2;
254 for (i = 0; i < ngroups; i++)
256 if (supplemental_groups[i] == gid)
258 high = 1;
259 break;
264 sprintf(buffer, "%s%c%c%c%s,%s%c%c%c%s,%s%c%c%c%s/%c%c"
265 #ifdef S_ISVTX
266 "%c"
267 #endif
270 high == 0 ? "(" : "",
271 m & S_IRUSR ? 'r' : '-',
272 m & S_IWUSR ? 'w' : '-',
273 m & S_IXUSR ? 'x' : '-',
274 high == 0 ? ")" : "",
276 high == 1 ? "(" : "",
277 m & S_IRGRP ? 'r' : '-',
278 m & S_IWGRP ? 'w' : '-',
279 m & S_IXGRP ? 'x' : '-',
280 high == 1 ? ")" : "",
282 high == 2 ? "(" : "",
283 m & S_IROTH ? 'r' : '-',
284 m & S_IWOTH ? 'w' : '-',
285 m & S_IXOTH ? 'x' : '-',
286 high == 2 ? ")" : "",
288 m & S_ISUID ? 'U' : '-',
289 m & S_ISGID ? 'G' : '-'
290 #ifdef S_ISVTX
291 , m & S_ISVTX ? 'T' : '-'
292 #endif
295 return buffer;