1 /* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
25 #include <sys/socket.h>
30 #include "utmp-private.h"
31 #include "programs/utmpd.h"
34 /* Descriptor for the socket. */
35 static int daemon_sock
= -1;
38 /* Functions defined here. */
39 static int setutent_daemon (void);
40 static int getutent_r_daemon (struct utmp
*buffer
, struct utmp
**result
);
41 static int getutid_r_daemon (const struct utmp
*line
, struct utmp
*buffer
,
42 struct utmp
**result
);
43 static int getutline_r_daemon (const struct utmp
*id
, struct utmp
*buffer
,
44 struct utmp
**result
);
45 static struct utmp
*pututline_daemon (const struct utmp
*utmp
);
46 static void endutent_daemon (void);
47 static int updwtmp_daemon (const char *file
, const struct utmp
*utmp
);
49 /* Jump table for daemon functions. */
50 struct utfuncs __libc_utmp_daemon_functions
=
61 static int do_setutent (int sock
);
62 static int do_getutent (int sock
, struct utmp
*buffer
);
63 static int do_getutid (int sock
, const struct utmp
*id
,
65 static int do_pututline (int sock
, const struct utmp
*utmp
);
66 static int do_getutline (int sock
, const struct utmp
*line
,
68 static int do_pututline (int sock
, const struct utmp
*utmp
);
69 static int do_endutent (int sock
);
70 static int do_updwtmp (int sock
, const char *file
,
71 const struct utmp
*utmp
);
73 static int open_socket (const char *name
);
74 static int send_request (int sock
, const request_header
*request
,
79 setutent_daemon (void)
81 if (__access (_PATH_UTMPD_RW
, F_OK
) == -1
82 && __access (_PATH_UTMPD_RO
, F_OK
) == -1)
89 daemon_sock
= open_socket (_PATH_UTMPD_RW
);
92 /* Hhm, read-write access did not work. Try read-only. */
93 daemon_sock
= open_socket (_PATH_UTMPD_RO
);
98 /* We have to make sure the socket is `closed on exec'. */
99 result
= __fcntl (daemon_sock
, F_GETFD
, 0);
101 result
= __fcntl (daemon_sock
, F_SETFD
, result
| FD_CLOEXEC
);
109 /* Send request to the daemon. */
110 if (do_setutent (daemon_sock
) < 0)
118 getutent_r_daemon (struct utmp
*buffer
, struct utmp
**result
)
120 assert (daemon_sock
>= 0);
122 /* Send request to the daemon. */
123 if (do_getutent (daemon_sock
, buffer
) < 0)
135 getutid_r_daemon (const struct utmp
*id
, struct utmp
*buffer
,
136 struct utmp
**result
)
138 assert (daemon_sock
>= 0);
140 /* Send request to the daemon. */
141 if (do_getutid (daemon_sock
, id
, buffer
) < 0)
153 getutline_r_daemon (const struct utmp
*line
, struct utmp
*buffer
,
154 struct utmp
**result
)
156 assert (daemon_sock
>= 0);
158 /* Send request to the daemon. */
159 if (do_getutline (daemon_sock
, line
, buffer
) < 0)
171 pututline_daemon (const struct utmp
*utmp
)
173 assert (daemon_sock
>= 0);
175 /* Send request to the daemon. */
176 if (do_pututline (daemon_sock
, utmp
) < 0)
179 return (struct utmp
*)utmp
;
184 endutent_daemon (void)
186 assert (daemon_sock
>= 0);
188 /* Send request to the daemon. */
189 do_endutent (daemon_sock
);
191 __close (daemon_sock
);
197 updwtmp_daemon (const char *file
, const struct utmp
*utmp
)
201 /* Only try to open for both reading and writing. */
202 sock
= open_socket (_PATH_UTMPD_RW
);
206 /* Send request to the daemon. */
207 if (do_updwtmp (sock
, file
, utmp
) < 0)
219 do_setutent (int sock
)
221 setutent_request
*request
;
222 setutent_reply reply
;
226 name_len
= strlen (__libc_utmp_file_name
) + 1;
227 size
= sizeof (setutent_request
) + name_len
;
229 request
= malloc (size
);
233 request
->header
.version
= UTMPD_VERSION
;
234 request
->header
.size
= size
;
235 request
->header
.type
= UTMPD_REQ_SETUTENT
;
236 memcpy (request
->file
, __libc_utmp_file_name
, name_len
);
238 reply
.header
.version
= UTMPD_VERSION
;
239 reply
.header
.size
= sizeof (setutent_reply
);
240 reply
.header
.type
= UTMPD_REQ_SETUTENT
;
242 if (send_request (sock
, &request
->header
, &reply
.header
) < 0)
248 if (reply
.result
< 0)
249 __set_errno (reply
.errnum
);
256 do_getutent (int sock
, struct utmp
*buffer
)
258 getutent_request request
;
259 getutent_reply reply
;
261 request
.header
.version
= UTMPD_VERSION
;
262 request
.header
.size
= sizeof (getutent_request
);
263 request
.header
.type
= UTMPD_REQ_GETUTENT
;
265 reply
.header
.version
= UTMPD_VERSION
;
266 reply
.header
.size
= sizeof (getutent_reply
);
267 reply
.header
.type
= UTMPD_REQ_GETUTENT
;
269 if (send_request (sock
, &request
.header
, &reply
.header
) < 0)
272 if (reply
.result
< 0)
273 __set_errno (reply
.errnum
);
275 memcpy (buffer
, &reply
.entry
, sizeof (struct utmp
));
281 do_getutid (int sock
, const struct utmp
*id
, struct utmp
*buffer
)
283 getutid_request request
;
286 request
.header
.version
= UTMPD_VERSION
;
287 request
.header
.size
= sizeof (getutid_request
);
288 request
.header
.type
= UTMPD_REQ_GETUTID
;
289 memcpy (&request
.id
, id
, sizeof (struct utmp
));
291 reply
.header
.version
= UTMPD_VERSION
;
292 reply
.header
.size
= sizeof (getutid_reply
);
293 reply
.header
.type
= UTMPD_REQ_GETUTID
;
295 if (send_request (sock
, &request
.header
, &reply
.header
) < 0)
298 if (reply
.result
< 0)
299 __set_errno (reply
.errnum
);
301 memcpy (buffer
, &reply
.entry
, sizeof (struct utmp
));
307 do_getutline (int sock
, const struct utmp
*line
, struct utmp
*buffer
)
309 getutline_request request
;
310 getutline_reply reply
;
312 request
.header
.version
= UTMPD_VERSION
;
313 request
.header
.size
= sizeof (getutline_request
);
314 request
.header
.type
= UTMPD_REQ_GETUTLINE
;
315 memcpy (&request
.line
, line
, sizeof (struct utmp
));
317 reply
.header
.version
= UTMPD_VERSION
;
318 reply
.header
.size
= sizeof (getutline_reply
);
319 reply
.header
.type
= UTMPD_REQ_GETUTLINE
;
321 if (send_request (sock
, &request
.header
, &reply
.header
) < 0)
324 if (reply
.result
< 0)
325 __set_errno (reply
.errnum
);
327 memcpy (buffer
, &reply
.entry
, sizeof (struct utmp
));
333 do_pututline (int sock
, const struct utmp
*utmp
)
335 pututline_request request
;
336 pututline_reply reply
;
338 request
.header
.version
= UTMPD_VERSION
;
339 request
.header
.size
= sizeof (pututline_request
);
340 request
.header
.type
= UTMPD_REQ_PUTUTLINE
;
341 memcpy (&request
.utmp
, utmp
, sizeof (struct utmp
));
343 reply
.header
.version
= UTMPD_VERSION
;
344 reply
.header
.size
= sizeof (pututline_reply
);
345 reply
.header
.type
= UTMPD_REQ_PUTUTLINE
;
347 if (send_request (sock
, &request
.header
, &reply
.header
) < 0)
350 if (reply
.result
< 0)
351 __set_errno (reply
.errnum
);
357 do_endutent (int sock
)
359 endutent_request request
;
360 endutent_reply reply
;
362 request
.header
.version
= UTMPD_VERSION
;
363 request
.header
.size
= sizeof (endutent_request
);
364 request
.header
.type
= UTMPD_REQ_ENDUTENT
;
366 reply
.header
.version
= UTMPD_VERSION
;
367 reply
.header
.size
= sizeof (endutent_reply
);
368 reply
.header
.type
= UTMPD_REQ_ENDUTENT
;
370 if (send_request (sock
, &request
.header
, &reply
.header
) < 0)
373 if (reply
.result
< 0)
374 __set_errno (reply
.errnum
);
380 do_updwtmp (int sock
, const char *file
, const struct utmp
*utmp
)
382 updwtmp_request
*request
;
387 file_len
= strlen (file
) + 1;
388 size
= sizeof (updwtmp_request
) + file_len
;
390 request
= malloc (size
);
394 request
->header
.version
= UTMPD_VERSION
;
395 request
->header
.size
= size
;
396 request
->header
.type
= UTMPD_REQ_UPDWTMP
;
397 memcpy (&request
->utmp
, utmp
, sizeof (struct utmp
));
398 memcpy (request
->file
, file
, file_len
);
400 reply
.header
.version
= UTMPD_VERSION
;
401 reply
.header
.size
= sizeof (updwtmp_reply
);
402 reply
.header
.type
= UTMPD_REQ_UPDWTMP
;
404 if (send_request (sock
, &request
->header
, &reply
.header
) < 0)
410 if (reply
.result
< 0)
411 __set_errno (reply
.errnum
);
418 /* Create a socket connected to NAME. */
420 open_socket (const char *name
)
422 struct sockaddr_un addr
;
425 sock
= __socket (PF_UNIX
, SOCK_STREAM
, 0);
429 addr
.sun_family
= AF_UNIX
;
430 strcpy (addr
.sun_path
, name
);
431 if (__connect (sock
, (struct sockaddr
*) &addr
, sizeof (addr
)) < 0)
440 /* Send REQUEST to SOCK, and wait for reply. Returns 0 if successful,
441 storing the reply in REPLY, and -1 if not. */
443 send_request (int sock
, const request_header
*request
,
449 nbytes
= __write (sock
, request
, request
->size
);
450 if (nbytes
!= (ssize_t
) request
->size
)
453 nbytes
= __read (sock
, &header
, sizeof (reply_header
));
454 if (nbytes
!= sizeof (reply_header
))
457 if (reply
->version
!= header
.version
458 || reply
->size
!= header
.size
459 || reply
->type
!= header
.type
)
462 nbytes
= __read (sock
, reply
+ 1, reply
->size
- sizeof (reply_header
));
463 if (nbytes
!= (ssize_t
) (reply
->size
- sizeof (reply_header
)))