~ubuntu-branches/ubuntu/maverick/fuse/maverick-proposed

« back to all changes in this revision

Viewing changes to util/ulockmgr_server.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2008-01-29 10:38:39 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20080129103839-kmz63d04pnttuuoc
Tags: 2.7.2-1ubuntu1
* Resynchronise with Debian. Remaining changes:
  - Don't install the init script; install the udev rule and the module
    configuration file instead.
  - debian/45-fuse.rules: set /dev/fuse group to fuse.
  - debian/fuse-utils.modprobe: module configuration file that mounts the
    control filesystem when fuse is loaded and unmounts it when fuse is
    unloaded, along with checking that the control FS is mounting before
    unmounting it.
  - debian/fuse-utils.install: add the udev rule, the module configuration
    file, and ulockmgr_server.
  - Load fuse on install, and set it so it gets loaded on reboot.
  - Move fusermount and ulockmgr_server to /bin and associated libraries
    to /lib.
  - Create libfuse2-udeb and fuse-utils-udeb.
  - Copy /sbin/mount.fuse and the fuse kernel module into the initramfs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
    ulockmgr_server: Userspace Lock Manager Server
3
 
    Copyright (C) 2006  Miklos Szeredi <miklos@szeredi.hu>
 
2
  ulockmgr_server: Userspace Lock Manager Server
 
3
  Copyright (C) 2006  Miklos Szeredi <miklos@szeredi.hu>
4
4
 
5
 
    This program can be distributed under the terms of the GNU GPL.
6
 
    See the file COPYING.
 
5
  This program can be distributed under the terms of the GNU GPL.
 
6
  See the file COPYING.
7
7
*/
8
8
 
9
9
/* #define DEBUG 1 */
23
23
#include <sys/wait.h>
24
24
 
25
25
struct message {
26
 
    unsigned intr : 1;
27
 
    unsigned nofd : 1;
28
 
    pthread_t thr;
29
 
    int cmd;
30
 
    int fd;
31
 
    struct flock lock;
32
 
    int error;
 
26
        unsigned intr : 1;
 
27
        unsigned nofd : 1;
 
28
        pthread_t thr;
 
29
        int cmd;
 
30
        int fd;
 
31
        struct flock lock;
 
32
        int error;
33
33
};
34
34
 
35
35
struct fd_store {
36
 
    struct fd_store *next;
37
 
    int fd;
38
 
    int origfd;
39
 
    int inuse;
 
36
        struct fd_store *next;
 
37
        int fd;
 
38
        int origfd;
 
39
        int inuse;
40
40
};
41
41
 
42
42
struct owner {
43
 
    struct fd_store *fds;
44
 
    pthread_mutex_t lock;
 
43
        struct fd_store *fds;
 
44
        pthread_mutex_t lock;
45
45
};
46
46
 
47
47
struct req_data {
48
 
    struct owner *o;
49
 
    int cfd;
50
 
    struct fd_store *f;
51
 
    struct message msg;
 
48
        struct owner *o;
 
49
        int cfd;
 
50
        struct fd_store *f;
 
51
        struct message msg;
52
52
};
53
53
 
54
54
#define MAX_SEND_FDS 2
55
55
 
56
56
static int receive_message(int sock, void *buf, size_t buflen, int *fdp,
57
 
                           int *numfds)
 
57
                           int *numfds)
58
58
{
59
 
    struct msghdr msg;
60
 
    struct iovec iov;
61
 
    size_t ccmsg[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)];
62
 
    struct cmsghdr *cmsg;
63
 
    int res;
64
 
    int i;
65
 
 
66
 
    assert(*numfds <= MAX_SEND_FDS);
67
 
    iov.iov_base = buf;
68
 
    iov.iov_len = buflen;
69
 
 
70
 
    memset(&msg, 0, sizeof(msg));
71
 
    memset(ccmsg, -1, sizeof(ccmsg));
72
 
    msg.msg_iov = &iov;
73
 
    msg.msg_iovlen = 1;
74
 
    msg.msg_control = ccmsg;
75
 
    msg.msg_controllen = sizeof(ccmsg);
76
 
 
77
 
    res = recvmsg(sock, &msg, MSG_WAITALL);
78
 
    if (!res) {
79
 
        /* retry on zero return, see do_recv() in ulockmgr.c */
80
 
        res = recvmsg(sock, &msg, MSG_WAITALL);
81
 
        if (!res)
82
 
            return 0;
83
 
    }
84
 
    if (res == -1) {
85
 
        perror("ulockmgr_server: recvmsg");
86
 
        return -1;
87
 
    }
88
 
    if ((size_t) res != buflen) {
89
 
        fprintf(stderr, "ulockmgr_server: short message received\n");
90
 
        return -1;
91
 
    }
92
 
 
93
 
    cmsg = CMSG_FIRSTHDR(&msg);
94
 
    if (cmsg) {
95
 
        if (!cmsg->cmsg_type == SCM_RIGHTS) {
96
 
            fprintf(stderr, "ulockmgr_server: unknown control message %d\n",
97
 
                    cmsg->cmsg_type);
98
 
            return -1;
99
 
        }
100
 
        memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
101
 
        if (msg.msg_flags & MSG_CTRUNC) {
102
 
            fprintf(stderr, "ulockmgr_server: control message truncated\n");
103
 
            for (i = 0; i < *numfds; i++)
104
 
                close(fdp[i]);
105
 
            *numfds = 0;
106
 
        }
107
 
    } else {
108
 
        if (msg.msg_flags & MSG_CTRUNC) {
109
 
            fprintf(stderr, "ulockmgr_server: control message truncated(*)\n");
110
 
 
111
 
            /* There's a bug in the Linux kernel, that if not all file
112
 
               descriptors were allocated, then the cmsg header is not
113
 
               filled in */
114
 
            cmsg = (struct cmsghdr *) ccmsg;
115
 
            memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
116
 
            for (i = 0; i < *numfds; i++)
117
 
                close(fdp[i]);
118
 
        }
119
 
        *numfds = 0;
120
 
    }
121
 
    return res;
 
59
        struct msghdr msg;
 
60
        struct iovec iov;
 
61
        size_t ccmsg[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)];
 
62
        struct cmsghdr *cmsg;
 
63
        int res;
 
64
        int i;
 
65
 
 
66
        assert(*numfds <= MAX_SEND_FDS);
 
67
        iov.iov_base = buf;
 
68
        iov.iov_len = buflen;
 
69
 
 
70
        memset(&msg, 0, sizeof(msg));
 
71
        memset(ccmsg, -1, sizeof(ccmsg));
 
72
        msg.msg_iov = &iov;
 
73
        msg.msg_iovlen = 1;
 
74
        msg.msg_control = ccmsg;
 
75
        msg.msg_controllen = sizeof(ccmsg);
 
76
 
 
77
        res = recvmsg(sock, &msg, MSG_WAITALL);
 
78
        if (!res) {
 
79
                /* retry on zero return, see do_recv() in ulockmgr.c */
 
80
                res = recvmsg(sock, &msg, MSG_WAITALL);
 
81
                if (!res)
 
82
                        return 0;
 
83
        }
 
84
        if (res == -1) {
 
85
                perror("ulockmgr_server: recvmsg");
 
86
                return -1;
 
87
        }
 
88
        if ((size_t) res != buflen) {
 
89
                fprintf(stderr, "ulockmgr_server: short message received\n");
 
90
                return -1;
 
91
        }
 
92
 
 
93
        cmsg = CMSG_FIRSTHDR(&msg);
 
94
        if (cmsg) {
 
95
                if (!cmsg->cmsg_type == SCM_RIGHTS) {
 
96
                        fprintf(stderr,
 
97
                                "ulockmgr_server: unknown control message %d\n",
 
98
                                cmsg->cmsg_type);
 
99
                        return -1;
 
100
                }
 
101
                memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
 
102
                if (msg.msg_flags & MSG_CTRUNC) {
 
103
                        fprintf(stderr,
 
104
                                "ulockmgr_server: control message truncated\n");
 
105
                        for (i = 0; i < *numfds; i++)
 
106
                                close(fdp[i]);
 
107
                        *numfds = 0;
 
108
                }
 
109
        } else {
 
110
                if (msg.msg_flags & MSG_CTRUNC) {
 
111
                        fprintf(stderr,
 
112
                                "ulockmgr_server: control message truncated(*)\n");
 
113
 
 
114
                        /* There's a bug in the Linux kernel, that if
 
115
                           not all file descriptors were allocated,
 
116
                           then the cmsg header is not filled in */
 
117
                        cmsg = (struct cmsghdr *) ccmsg;
 
118
                        memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
 
119
                        for (i = 0; i < *numfds; i++)
 
120
                                close(fdp[i]);
 
121
                }
 
122
                *numfds = 0;
 
123
        }
 
124
        return res;
122
125
}
123
126
 
124
127
static int closefrom(int minfd)
125
128
{
126
 
    DIR *dir = opendir("/proc/self/fd");
127
 
    if (dir) {
128
 
        int dfd = dirfd(dir);
129
 
        struct dirent *ent;
130
 
        while ((ent = readdir(dir))) {
131
 
            char *end;
132
 
            int fd = strtol(ent->d_name, &end, 10);
133
 
            if (ent->d_name[0] && !end[0] && fd >= minfd && fd != dfd)
134
 
                close(fd);
135
 
        }
136
 
        closedir(dir);
137
 
    }
138
 
    return 0;
 
129
        DIR *dir = opendir("/proc/self/fd");
 
130
        if (dir) {
 
131
                int dfd = dirfd(dir);
 
132
                struct dirent *ent;
 
133
                while ((ent = readdir(dir))) {
 
134
                        char *end;
 
135
                        int fd = strtol(ent->d_name, &end, 10);
 
136
                        if (ent->d_name[0] && !end[0] && fd >= minfd &&
 
137
                            fd != dfd)
 
138
                                close(fd);
 
139
                }
 
140
                closedir(dir);
 
141
        }
 
142
        return 0;
139
143
}
140
144
 
141
145
static void send_reply(int cfd, struct message *msg)
142
146
{
143
 
    int res = send(cfd, msg, sizeof(struct message), MSG_NOSIGNAL);
144
 
    if (res == -1)
145
 
        perror("ulockmgr_server: sending reply");
 
147
        int res = send(cfd, msg, sizeof(struct message), MSG_NOSIGNAL);
 
148
        if (res == -1)
 
149
                perror("ulockmgr_server: sending reply");
146
150
#ifdef DEBUG
147
 
    fprintf(stderr, "ulockmgr_server: error: %i\n", msg->error);
 
151
        fprintf(stderr, "ulockmgr_server: error: %i\n", msg->error);
148
152
#endif
149
153
}
150
154
 
151
155
static void *process_request(void *d_)
152
156
{
153
 
    struct req_data *d = d_;
154
 
    int res;
155
 
 
156
 
    assert(d->msg.cmd == F_SETLKW);
157
 
    res = fcntl(d->f->fd, F_SETLK, &d->msg.lock);
158
 
    if (res == -1 && errno == EAGAIN) {
159
 
        d->msg.error = EAGAIN;
160
 
        d->msg.thr = pthread_self();
161
 
        send_reply(d->cfd, &d->msg);
162
 
        res = fcntl(d->f->fd, F_SETLKW, &d->msg.lock);
163
 
    }
164
 
    d->msg.error = (res == -1) ? errno : 0;
165
 
    pthread_mutex_lock(&d->o->lock);
166
 
    d->f->inuse--;
167
 
    pthread_mutex_unlock(&d->o->lock);
168
 
    send_reply(d->cfd, &d->msg);
169
 
    close(d->cfd);
170
 
    free(d);
171
 
 
172
 
    return NULL;
 
157
        struct req_data *d = d_;
 
158
        int res;
 
159
 
 
160
        assert(d->msg.cmd == F_SETLKW);
 
161
        res = fcntl(d->f->fd, F_SETLK, &d->msg.lock);
 
162
        if (res == -1 && errno == EAGAIN) {
 
163
                d->msg.error = EAGAIN;
 
164
                d->msg.thr = pthread_self();
 
165
                send_reply(d->cfd, &d->msg);
 
166
                res = fcntl(d->f->fd, F_SETLKW, &d->msg.lock);
 
167
        }
 
168
        d->msg.error = (res == -1) ? errno : 0;
 
169
        pthread_mutex_lock(&d->o->lock);
 
170
        d->f->inuse--;
 
171
        pthread_mutex_unlock(&d->o->lock);
 
172
        send_reply(d->cfd, &d->msg);
 
173
        close(d->cfd);
 
174
        free(d);
 
175
 
 
176
        return NULL;
173
177
}
174
178
 
175
179
static void process_message(struct owner *o, struct message *msg, int cfd,
176
 
                            int fd)
 
180
                            int fd)
177
181
{
178
 
    struct fd_store *f = NULL;
179
 
    struct fd_store *newf = NULL;
180
 
    struct fd_store **fp;
181
 
    struct req_data *d;
182
 
    pthread_t tid;
183
 
    int res;
 
182
        struct fd_store *f = NULL;
 
183
        struct fd_store *newf = NULL;
 
184
        struct fd_store **fp;
 
185
        struct req_data *d;
 
186
        pthread_t tid;
 
187
        int res;
184
188
 
185
189
#ifdef DEBUG
186
 
    fprintf(stderr, "ulockmgr_server: %i %i %i %lli %lli\n",
187
 
            msg->cmd, msg->lock.l_type, msg->lock.l_whence, msg->lock.l_start,
188
 
            msg->lock.l_len);
 
190
        fprintf(stderr, "ulockmgr_server: %i %i %i %lli %lli\n",
 
191
                msg->cmd, msg->lock.l_type, msg->lock.l_whence,
 
192
                msg->lock.l_start, msg->lock.l_len);
189
193
#endif
190
194
 
191
 
    if (msg->cmd == F_SETLK  && msg->lock.l_type == F_UNLCK && 
192
 
        msg->lock.l_start == 0 && msg->lock.l_len == 0) {
193
 
        for (fp = &o->fds; *fp;) {
194
 
            f = *fp;
195
 
            if (f->origfd == msg->fd && !f->inuse) {
196
 
                close(f->fd);
197
 
                *fp = f->next;
198
 
                free(f);
199
 
            } else
200
 
                fp = &f->next;
201
 
        }
202
 
        if (!msg->nofd)
203
 
            close(fd);
204
 
 
205
 
        msg->error = 0;
206
 
        send_reply(cfd, msg);
207
 
        close(cfd);
208
 
        return;
209
 
    }
210
 
 
211
 
    if (msg->nofd) {
212
 
        for (fp = &o->fds; *fp; fp = &(*fp)->next) {
213
 
            f = *fp;
214
 
            if (f->origfd == msg->fd)
215
 
                break;
216
 
        }
217
 
        if (!*fp) {
218
 
            fprintf(stderr, "ulockmgr_server: fd %i not found\n", msg->fd);
219
 
            msg->error = EIO;
220
 
            send_reply(cfd, msg);
221
 
            close(cfd);
222
 
            return;
223
 
        }
224
 
    } else {
225
 
        newf = f = malloc(sizeof(struct fd_store));
226
 
        if (!f) {
227
 
            msg->error = ENOLCK;
228
 
            send_reply(cfd, msg);
229
 
            close(cfd);
230
 
            return;
231
 
        }
232
 
 
233
 
        f->fd = fd;
234
 
        f->origfd = msg->fd;
235
 
        f->inuse = 0;
236
 
    }
237
 
 
238
 
    if (msg->cmd == F_GETLK || msg->cmd == F_SETLK ||
239
 
        msg->lock.l_type == F_UNLCK) {
240
 
        res = fcntl(f->fd, msg->cmd, &msg->lock);
241
 
        msg->error = (res == -1) ? errno : 0;
242
 
        send_reply(cfd, msg);
243
 
        close(cfd);
244
 
        if (newf) {
245
 
            newf->next = o->fds;
246
 
            o->fds = newf;
247
 
        }
248
 
        return;
249
 
    }
250
 
 
251
 
    d = malloc(sizeof(struct req_data));
252
 
    if (!d) {
253
 
        msg->error = ENOLCK;
254
 
        send_reply(cfd, msg);
255
 
        close(cfd);
256
 
        free(newf);
257
 
        return;
258
 
    }
259
 
 
260
 
    f->inuse++;
261
 
    d->o = o;
262
 
    d->cfd = cfd;
263
 
    d->f = f;
264
 
    d->msg = *msg;
265
 
    res = pthread_create(&tid, NULL, process_request, d);
266
 
    if (res) {
267
 
        msg->error = ENOLCK;
268
 
        send_reply(cfd, msg);
269
 
        close(cfd);
270
 
        free(d);
271
 
        f->inuse--;
272
 
        free(newf);
273
 
        return;
274
 
    }
275
 
 
276
 
    if (newf) {
277
 
        newf->next = o->fds;
278
 
        o->fds = newf;
279
 
    }
280
 
    pthread_detach(tid);
 
195
        if (msg->cmd == F_SETLK  && msg->lock.l_type == F_UNLCK &&
 
196
            msg->lock.l_start == 0 && msg->lock.l_len == 0) {
 
197
                for (fp = &o->fds; *fp;) {
 
198
                        f = *fp;
 
199
                        if (f->origfd == msg->fd && !f->inuse) {
 
200
                                close(f->fd);
 
201
                                *fp = f->next;
 
202
                                free(f);
 
203
                        } else
 
204
                                fp = &f->next;
 
205
                }
 
206
                if (!msg->nofd)
 
207
                        close(fd);
 
208
 
 
209
                msg->error = 0;
 
210
                send_reply(cfd, msg);
 
211
                close(cfd);
 
212
                return;
 
213
        }
 
214
 
 
215
        if (msg->nofd) {
 
216
                for (fp = &o->fds; *fp; fp = &(*fp)->next) {
 
217
                        f = *fp;
 
218
                        if (f->origfd == msg->fd)
 
219
                                break;
 
220
                }
 
221
                if (!*fp) {
 
222
                        fprintf(stderr, "ulockmgr_server: fd %i not found\n",
 
223
                                msg->fd);
 
224
                        msg->error = EIO;
 
225
                        send_reply(cfd, msg);
 
226
                        close(cfd);
 
227
                        return;
 
228
                }
 
229
        } else {
 
230
                newf = f = malloc(sizeof(struct fd_store));
 
231
                if (!f) {
 
232
                        msg->error = ENOLCK;
 
233
                        send_reply(cfd, msg);
 
234
                        close(cfd);
 
235
                        return;
 
236
                }
 
237
 
 
238
                f->fd = fd;
 
239
                f->origfd = msg->fd;
 
240
                f->inuse = 0;
 
241
        }
 
242
 
 
243
        if (msg->cmd == F_GETLK || msg->cmd == F_SETLK ||
 
244
            msg->lock.l_type == F_UNLCK) {
 
245
                res = fcntl(f->fd, msg->cmd, &msg->lock);
 
246
                msg->error = (res == -1) ? errno : 0;
 
247
                send_reply(cfd, msg);
 
248
                close(cfd);
 
249
                if (newf) {
 
250
                        newf->next = o->fds;
 
251
                        o->fds = newf;
 
252
                }
 
253
                return;
 
254
        }
 
255
 
 
256
        d = malloc(sizeof(struct req_data));
 
257
        if (!d) {
 
258
                msg->error = ENOLCK;
 
259
                send_reply(cfd, msg);
 
260
                close(cfd);
 
261
                free(newf);
 
262
                return;
 
263
        }
 
264
 
 
265
        f->inuse++;
 
266
        d->o = o;
 
267
        d->cfd = cfd;
 
268
        d->f = f;
 
269
        d->msg = *msg;
 
270
        res = pthread_create(&tid, NULL, process_request, d);
 
271
        if (res) {
 
272
                msg->error = ENOLCK;
 
273
                send_reply(cfd, msg);
 
274
                close(cfd);
 
275
                free(d);
 
276
                f->inuse--;
 
277
                free(newf);
 
278
                return;
 
279
        }
 
280
 
 
281
        if (newf) {
 
282
                newf->next = o->fds;
 
283
                o->fds = newf;
 
284
        }
 
285
        pthread_detach(tid);
281
286
}
282
287
 
283
288
static void sigusr1_handler(int sig)
284
289
{
285
 
    (void) sig;
286
 
    /* Nothing to do */
 
290
        (void) sig;
 
291
        /* Nothing to do */
287
292
}
288
293
 
289
294
static void process_owner(int cfd)
290
295
{
291
 
    struct owner o;
292
 
    struct sigaction sa;
293
 
 
294
 
    memset(&sa, 0, sizeof(struct sigaction));
295
 
    sa.sa_handler = sigusr1_handler;
296
 
    sigemptyset(&sa.sa_mask);
297
 
 
298
 
    if (sigaction(SIGUSR1, &sa, NULL) == -1) {
299
 
        perror("ulockmgr_server: cannot set sigusr1 signal handler");
300
 
        exit(1);
301
 
    }
302
 
 
303
 
    memset(&o, 0, sizeof(struct owner));
304
 
    pthread_mutex_init(&o.lock, NULL);
305
 
    while (1) {
306
 
        struct message msg;
307
 
        int rfds[2];
308
 
        int res;
309
 
        int numfds = 2;
310
 
 
311
 
        res  = receive_message(cfd, &msg, sizeof(msg), rfds, &numfds);
312
 
        if (!res)
313
 
            break;
314
 
        if (res == -1)
315
 
            exit(1);
316
 
 
317
 
        if (msg.intr) {
318
 
            if (numfds != 0)
319
 
                fprintf(stderr, "ulockmgr_server: too many fds for intr\n");
320
 
            pthread_kill(msg.thr, SIGUSR1);
321
 
        } else {
322
 
            if (numfds != 2)
323
 
                continue;
324
 
 
325
 
            pthread_mutex_lock(&o.lock);
326
 
            process_message(&o, &msg, rfds[0], rfds[1]);
327
 
            pthread_mutex_unlock(&o.lock);
328
 
        }
329
 
    }
330
 
    if (o.fds)
331
 
        fprintf(stderr, "ulockmgr_server: open file descriptors on exit\n");
 
296
        struct owner o;
 
297
        struct sigaction sa;
 
298
 
 
299
        memset(&sa, 0, sizeof(struct sigaction));
 
300
        sa.sa_handler = sigusr1_handler;
 
301
        sigemptyset(&sa.sa_mask);
 
302
 
 
303
        if (sigaction(SIGUSR1, &sa, NULL) == -1) {
 
304
                perror("ulockmgr_server: cannot set sigusr1 signal handler");
 
305
                exit(1);
 
306
        }
 
307
 
 
308
        memset(&o, 0, sizeof(struct owner));
 
309
        pthread_mutex_init(&o.lock, NULL);
 
310
        while (1) {
 
311
                struct message msg;
 
312
                int rfds[2];
 
313
                int res;
 
314
                int numfds = 2;
 
315
 
 
316
                res  = receive_message(cfd, &msg, sizeof(msg), rfds, &numfds);
 
317
                if (!res)
 
318
                        break;
 
319
                if (res == -1)
 
320
                        exit(1);
 
321
 
 
322
                if (msg.intr) {
 
323
                        if (numfds != 0)
 
324
                                fprintf(stderr,
 
325
                                        "ulockmgr_server: too many fds for intr\n");
 
326
                        pthread_kill(msg.thr, SIGUSR1);
 
327
                } else {
 
328
                        if (numfds != 2)
 
329
                                continue;
 
330
 
 
331
                        pthread_mutex_lock(&o.lock);
 
332
                        process_message(&o, &msg, rfds[0], rfds[1]);
 
333
                        pthread_mutex_unlock(&o.lock);
 
334
                }
 
335
        }
 
336
        if (o.fds)
 
337
                fprintf(stderr,
 
338
                        "ulockmgr_server: open file descriptors on exit\n");
332
339
}
333
340
 
334
341
int main(int argc, char *argv[])
335
342
{
336
 
    int nullfd;
337
 
    char *end;
338
 
    int cfd;
339
 
    sigset_t empty;
340
 
 
341
 
    if (argc != 2 || !argv[1][0])
342
 
        goto out_inval;
343
 
 
344
 
    cfd = strtol(argv[1], &end, 10);
345
 
    if (*end)
346
 
        goto out_inval;
347
 
 
348
 
    if (daemon(0, 1) == -1) {
349
 
        perror("ulockmgr_server: daemon");
350
 
        exit(1);
351
 
    }
352
 
 
353
 
    sigemptyset(&empty);
354
 
    sigprocmask(SIG_SETMASK, &empty, NULL);
355
 
 
356
 
    if (dup2(cfd, 4) == -1) {
357
 
        perror("ulockmgr_server: dup2");
358
 
        exit(1);
359
 
    }
360
 
    cfd = 4;
361
 
    nullfd = open("/dev/null", O_RDWR);
362
 
    dup2(nullfd, 0);
363
 
    dup2(nullfd, 1);
364
 
    close(3);
365
 
    closefrom(5);
366
 
    while (1) {
367
 
        char c;
368
 
        int sock;
369
 
        int pid;
370
 
        int numfds = 1;
371
 
        int res = receive_message(cfd, &c, sizeof(c), &sock, &numfds);
372
 
        if (!res)
373
 
            break;
374
 
        if (res == -1)
375
 
            exit(1);
376
 
        assert(numfds == 1);
377
 
 
378
 
        pid = fork();
379
 
        if (pid == -1) {
380
 
            perror("ulockmgr_server: fork");
381
 
            close(sock);
382
 
            continue;
383
 
        }
384
 
        if (pid == 0) {
385
 
            close(cfd);
386
 
            pid = fork();
387
 
            if (pid == -1) {
388
 
                perror("ulockmgr_server: fork");
389
 
                _exit(1);
390
 
            }
391
 
            if (pid == 0)
392
 
                process_owner(sock);
393
 
            _exit(0);
394
 
        }
395
 
        waitpid(pid, NULL, 0);
396
 
        close(sock);
397
 
    }
398
 
    return 0;
399
 
 
400
 
 out_inval:
401
 
    fprintf(stderr, "%s should be started by libulockmgr\n", argv[0]);
402
 
    return 1;
 
343
        int nullfd;
 
344
        char *end;
 
345
        int cfd;
 
346
        sigset_t empty;
 
347
 
 
348
        if (argc != 2 || !argv[1][0])
 
349
                goto out_inval;
 
350
 
 
351
        cfd = strtol(argv[1], &end, 10);
 
352
        if (*end)
 
353
                goto out_inval;
 
354
 
 
355
        if (daemon(0, 1) == -1) {
 
356
                perror("ulockmgr_server: daemon");
 
357
                exit(1);
 
358
        }
 
359
 
 
360
        sigemptyset(&empty);
 
361
        sigprocmask(SIG_SETMASK, &empty, NULL);
 
362
 
 
363
        if (dup2(cfd, 4) == -1) {
 
364
                perror("ulockmgr_server: dup2");
 
365
                exit(1);
 
366
        }
 
367
        cfd = 4;
 
368
        nullfd = open("/dev/null", O_RDWR);
 
369
        dup2(nullfd, 0);
 
370
        dup2(nullfd, 1);
 
371
        close(3);
 
372
        closefrom(5);
 
373
        while (1) {
 
374
                char c;
 
375
                int sock;
 
376
                int pid;
 
377
                int numfds = 1;
 
378
                int res = receive_message(cfd, &c, sizeof(c), &sock, &numfds);
 
379
                if (!res)
 
380
                        break;
 
381
                if (res == -1)
 
382
                        exit(1);
 
383
                assert(numfds == 1);
 
384
 
 
385
                pid = fork();
 
386
                if (pid == -1) {
 
387
                        perror("ulockmgr_server: fork");
 
388
                        close(sock);
 
389
                        continue;
 
390
                }
 
391
                if (pid == 0) {
 
392
                        close(cfd);
 
393
                        pid = fork();
 
394
                        if (pid == -1) {
 
395
                                perror("ulockmgr_server: fork");
 
396
                                _exit(1);
 
397
                        }
 
398
                        if (pid == 0)
 
399
                                process_owner(sock);
 
400
                        _exit(0);
 
401
                }
 
402
                waitpid(pid, NULL, 0);
 
403
                close(sock);
 
404
        }
 
405
        return 0;
 
406
 
 
407
out_inval:
 
408
        fprintf(stderr, "%s should be started by libulockmgr\n", argv[0]);
 
409
        return 1;
403
410
}