source: trunk/gtk/util.c @ 24

Last change on this file since 24 was 24, checked in by root, 16 years ago

Update 2006-01-03

File size: 5.4 KB
Line 
1/*
2  Copyright (c) 2005 Joshua Elsasser. All rights reserved.
3   
4  Redistribution and use in source and binary forms, with or without
5  modification, are permitted provided that the following conditions
6  are met:
7   
8   1. Redistributions of source code must retain the above copyright
9      notice, this list of conditions and the following disclaimer.
10   2. Redistributions in binary form must reproduce the above copyright
11      notice, this list of conditions and the following disclaimer in the
12      documentation and/or other materials provided with the distribution.
13   
14  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS "AS IS" AND
15  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  POSSIBILITY OF SUCH DAMAGE.
25*/
26
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <errno.h>
30#include <signal.h>
31#include <stdarg.h>
32#include <string.h>
33
34#include <gtk/gtk.h>
35
36#include "util.h"
37
38static void
39sigexithandler(int sig);
40static void
41errcb(GtkWidget *wind, int resp, gpointer data);
42
43gboolean
44strbool(const char *str) {
45  switch(str[0]) {
46    case 'y':
47    case 'Y':
48    case '1':
49    case 'j':
50    case 'e':
51      return TRUE;
52    default:
53      if(0 == g_ascii_strcasecmp("on", str))
54        return TRUE;
55      break;
56  }
57
58  return FALSE;
59}
60
61char *
62readablesize(guint64 size, int decimals) {
63  const char *sizes[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
64  unsigned int ii;
65  double small = size;
66
67  for(ii = 0; ii + 1 < ALEN(sizes) && 1024.0 <= small / 1024.0; ii++)
68    small /= 1024.0;
69
70  if(1024.0 <= small) {
71    small /= 1024.0;
72    ii++;
73  }
74
75  return g_strdup_printf("%.*f %s", decimals, small, sizes[ii]);
76}
77
78gboolean
79mkdir_p(const char *name, mode_t mode) {
80  struct stat sb;
81  char *parent;
82  gboolean ret;
83  int oerrno;
84
85  if(0 != stat(name, &sb)) {
86    if(ENOENT != errno)
87      return FALSE;
88    parent = g_path_get_dirname(name);
89    ret = mkdir_p(parent, mode);
90    oerrno = errno;
91    g_free(parent);
92    errno = oerrno;
93    return (ret ? (0 == mkdir(name, mode)) : FALSE);
94  }
95
96  if(!S_ISDIR(sb.st_mode)) {
97    errno = ENOTDIR;
98    return FALSE;
99  }
100
101  return TRUE;
102}
103
104static int exit_sigs[] = {SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGUSR2};
105static callbackfunc_t exit_func = NULL;
106static void *exit_data = NULL;
107static int exit_block_level = 0;
108
109void
110setuphandlers(callbackfunc_t func, void *data) {
111  struct sigaction sa;
112  unsigned int ii;
113
114  exit_data = data;
115  exit_func = func;
116
117  bzero(&sa, sizeof(sa));
118  sa.sa_handler = sigexithandler;
119  for(ii = 0; ii < ALEN(exit_sigs); ii++)
120    sigaction(exit_sigs[ii], &sa, NULL);
121}
122
123void
124clearhandlers(void) {
125  struct sigaction sa;
126  unsigned int ii;
127
128  bzero(&sa, sizeof(sa));
129  sa.sa_handler = SIG_DFL;
130  for(ii = 0; ii < ALEN(exit_sigs); ii++)
131    sigaction(exit_sigs[ii], &sa, NULL);
132}
133
134static void
135sigexithandler(int sig) {
136  exit_func(exit_data);
137  clearhandlers();
138  raise(sig);
139}
140
141void
142blocksigs(void) {
143  sigset_t mask;
144  unsigned int ii;
145
146  if(0 < (exit_block_level++))
147    return;
148
149  sigemptyset(&mask);
150  for(ii = 0; ii < ALEN(exit_sigs); ii++)
151    sigaddset(&mask, exit_sigs[ii]);
152  sigprocmask(SIG_BLOCK, &mask, NULL);
153}
154
155void
156unblocksigs(void) {
157  sigset_t mask;
158  unsigned int ii;
159
160  if(0 < (--exit_block_level))
161    return;
162
163  sigemptyset(&mask);
164  for(ii = 0; ii < ALEN(exit_sigs); ii++)
165    sigaddset(&mask, exit_sigs[ii]);
166  sigprocmask(SIG_UNBLOCK, &mask, NULL);
167}
168
169GtkWidget *
170errmsg(GtkWindow *wind, const char *format, ...) {
171  GtkWidget *dialog;
172  va_list ap;
173
174  va_start(ap, format);
175  dialog = verrmsg(wind, NULL, NULL, format, ap);
176  va_end(ap);
177
178  return dialog;
179}
180
181GtkWidget *
182errmsg_full(GtkWindow *wind, callbackfunc_t func, void *data,
183            const char *format, ...) {
184  GtkWidget *dialog;
185  va_list ap;
186
187  va_start(ap, format);
188  dialog = verrmsg(wind, func, data, format, ap);
189  va_end(ap);
190
191  return dialog;
192}
193
194GtkWidget *
195verrmsg(GtkWindow *wind, callbackfunc_t func, void *data,
196        const char *format, va_list ap) {
197  GtkWidget *dialog;
198  char *msg;
199  GList *funcdata;
200
201  msg = g_strdup_vprintf(format, ap);
202
203  if(NULL == wind)
204    dialog = gtk_message_dialog_new(
205      NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", msg);
206  else
207    dialog = gtk_message_dialog_new(wind,
208      GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
209      GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", msg);
210
211  if(NULL == func)
212    funcdata = NULL;
213  else
214    funcdata = g_list_append(g_list_append(NULL, func), data);
215  g_signal_connect(dialog, "response", G_CALLBACK(errcb), funcdata);
216  if(NULL != wind)
217    gtk_widget_show(dialog);
218  g_free(msg);
219
220  return dialog;
221}
222
223static void
224errcb(GtkWidget *widget, int resp SHUTUP, gpointer data) {
225  GList *funcdata;
226  callbackfunc_t func;
227
228  if(NULL != data) {
229    funcdata = g_list_first(data);
230    func = funcdata->data;
231    data = funcdata->next->data;
232    func(data);
233    g_list_free(funcdata);
234  }
235
236  gtk_widget_destroy(widget);
237}
Note: See TracBrowser for help on using the repository browser.