source: trunk/ORBit2-2.14.0/linc2/src/cleanup.c

Last change on this file was 92, checked in by cinc, 19 years ago

Orbit2 modified for use with NOM

File size: 4.1 KB
Line 
1#include <config.h>
2
3#include <stdio.h>
4#include <fcntl.h>
5#include <unistd.h>
6#include <dirent.h>
7#include <glib.h>
8
9/*
10 * Two timeouts - waiting while there are other
11 * ( in ms ) handles to be checked.
12 * - waiting after all other handles have
13 * been checked.
14 */
15#define SHORT_TIMEOUT 10
16#define LONG_TIMEOUT 1000
17
18static int total_count = 0;
19static int cleaned_count = 0;
20
21#include <linc-compat.h>
22
23#ifdef AF_UNIX
24
25typedef struct {
26 char *name;
27 int fd;
28} SocketEntry;
29
30static SocketEntry *
31new_socket_entry (const char *dir, const char *fname)
32{
33 SocketEntry *se = g_new0 (SocketEntry, 1);
34
35 se->name = g_build_filename (dir, fname, NULL);
36 se->fd = -1;
37
38 return se;
39}
40
41static void
42free_socket_entry (SocketEntry *se)
43{
44 g_free (se->name);
45 if (se->fd >= 0)
46 close (se->fd);
47 g_free (se);
48}
49
50static GList *
51read_sockets (const char *dir)
52{
53 DIR *dirh;
54 GList *files = NULL;
55 struct dirent *dent;
56
57 dirh = opendir (dir);
58 if (!dirh)
59 return NULL;
60
61 while ((dent = readdir (dirh))) {
62 if (strncmp (dent->d_name, "linc-", 5))
63 continue;
64
65 files = g_list_prepend (
66 files, new_socket_entry (
67 dir, dent->d_name));
68 }
69 closedir (dirh);
70
71 return files;
72}
73
74typedef enum {
75 SOCKET_DEAD_NOW,
76 SOCKET_PENDING,
77 SOCKET_AGAIN,
78 SOCKET_ALIVE
79} SocketStatus;
80
81static SocketStatus
82open_socket (SocketEntry *se)
83{
84 int saddr_len, ret;
85 struct sockaddr_un saddr;
86
87 g_return_val_if_fail (se != NULL, SOCKET_DEAD_NOW);
88 g_return_val_if_fail (se->fd == -1, SOCKET_DEAD_NOW);
89 g_return_val_if_fail (se->name != NULL, SOCKET_DEAD_NOW);
90
91 saddr.sun_family = AF_UNIX;
92
93 g_snprintf (saddr.sun_path, sizeof (saddr.sun_path),
94 "%s", se->name);
95
96 se->fd = socket (AF_UNIX, SOCK_STREAM, 0);
97 g_assert (se->fd >= 0);
98
99 if (fcntl (se->fd, F_SETFL, O_NONBLOCK) < 0)
100 g_error ("Failed to set fd non-blocking");
101
102 saddr_len = sizeof (struct sockaddr_un) -
103 sizeof (saddr.sun_path) + strlen (saddr.sun_path);
104
105 do {
106 ret = connect (se->fd, &saddr, saddr_len);
107 } while (ret < 0 && errno == EINTR);
108
109 if (ret >= 0)
110 return SOCKET_ALIVE;
111 else {
112 switch (errno) {
113 case EINPROGRESS:
114 return SOCKET_PENDING;
115 case ECONNREFUSED:
116 return SOCKET_DEAD_NOW;
117 case EAGAIN:
118 return SOCKET_AGAIN;
119 case EBADF:
120 g_error ("Bad bug fd %d", se->fd);
121 break;
122 default:
123 g_warning ("Error '%s' on socket %d",
124 g_strerror (errno), se->fd);
125 break;
126 }
127 }
128
129 return SOCKET_DEAD_NOW;
130}
131
132static GList *
133poll_open (GList *files, int *pending, int timeout)
134{
135 if (!files)
136 return NULL;
137
138 g_print ("FIXME: should poll unknown descriptors for a bit");
139
140 /* FIXME: we should really do something clever here,
141 * poll for a while, wait for nice connected / bad
142 * signals on the sockets, etc - but what we have
143 * works well for now */
144 while (files && *pending > 0) {
145 free_socket_entry (files->data);
146 files = g_list_delete_link (files, files);
147 (*pending)--;
148 }
149
150 return files;
151}
152
153static void
154clean_dir (const char *dir)
155{
156 int open_max;
157 int pending = 0;
158 int dirty_files = 0;
159 GList *files, *l, *next;
160
161 open_max = sysconf (_SC_OPEN_MAX);
162
163 files = read_sockets (dir);
164
165 dirty_files = g_list_length (files);
166
167 for (l = files; l; l = next) {
168 SocketEntry *se = l->data;
169 SocketStatus status;
170
171 next = l->next;
172
173 status = open_socket (se);
174
175 switch (status) {
176 case SOCKET_DEAD_NOW:
177 cleaned_count++;
178 unlink (se->name);
179 /* drop through */
180 case SOCKET_ALIVE:
181 files = g_list_delete_link (files, l);
182 free_socket_entry (se);
183 total_count++;
184 break;
185 case SOCKET_AGAIN:
186 case SOCKET_PENDING:
187 pending++;
188 break;
189 }
190
191 while (pending >= open_max)
192 files = poll_open (
193 files, &pending, SHORT_TIMEOUT);
194 }
195
196 files = poll_open (files, &pending, LONG_TIMEOUT);
197
198 while (files) {
199 free_socket_entry (files->data);
200 files = g_list_delete_link (files, files);
201 }
202}
203
204#endif /* AF_UNIX */
205
206int
207main (int argc, char **argv)
208{
209 char *dir;
210
211 dir = g_strdup_printf ("%s/orbit-%s", g_get_tmp_dir (), g_get_user_name ());
212
213#ifdef AF_UNIX
214 clean_dir (dir);
215#endif /* AF_UNIX */
216
217 g_free (dir);
218
219 printf ("Cleaned %d files %d still live\n",
220 cleaned_count,
221 total_count - cleaned_count);
222
223 return 0;
224}
Note: See TracBrowser for help on using the repository browser.