2 * sock.c - ACPI daemon socket interface
4 * Portions Copyright (C) 2000 Andrew Henroid
5 * Portions Copyright (C) 2001 Sun Microsystems
6 * Portions Copyright (C) 2004 Tim Hockin (thockin@hockin.org)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <sys/types.h>
35 #include "ud_socket.h"
36 #include "connection_list.h"
38 const char *socketfile = ACPID_SOCKETFILE;
39 const char *socketgroup;
40 mode_t socketmode = ACPID_SOCKETMODE;
41 int clientmax = ACPID_CLIENTMAX;
43 /* the number of non-root clients that are connected */
46 /* determine if a file descriptor is in fact a socket */
51 socklen_t l = sizeof(int);
53 return (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
56 /* accept a new client connection */
63 static int accept_errors;
65 /* accept and add to our lists */
66 cli_fd = ud_accept(fd, &creds);
68 acpid_log(LOG_ERR, "can't accept client: %s",
71 if (accept_errors >= 5) {
72 acpid_log(LOG_ERR, "giving up");
73 clean_exit_with_status(EXIT_FAILURE);
79 /* don't allow too many non-root clients */
80 if (creds.uid != 0 && non_root_clients >= clientmax) {
82 acpid_log(LOG_ERR, "too many non-root clients");
89 /* don't leak fds when execing */
90 if (fcntl(cli_fd, F_SETFD, FD_CLOEXEC) < 0) {
92 acpid_log(LOG_ERR, "fcntl() on client for FD_CLOEXEC: %s",
97 /* don't allow clients to block this */
98 if (fcntl(cli_fd, F_SETFL, O_NONBLOCK) < 0) {
100 acpid_log(LOG_ERR, "fcntl() on client for O_NONBLOCK: %s",
105 snprintf(buf, sizeof(buf)-1, "%d[%d:%d]",
106 creds.pid, creds.uid, creds.gid);
107 acpid_add_client(cli_fd, buf);
110 /* set up the socket for client connections */
117 /* if this is a socket passed in via stdin by systemd */
118 if (is_socket(STDIN_FILENO)) {
121 /* create our own socket */
122 fd = ud_create_socket(socketfile);
124 acpid_log(LOG_ERR, "can't open socket %s: %s",
125 socketfile, strerror(errno));
129 if (chmod(socketfile, socketmode) < 0) {
131 acpid_log(LOG_ERR, "chmod() on socket %s: %s",
132 socketfile, strerror(errno));
136 /* if we need to change the socket's group, do so */
141 gr = getgrnam(socketgroup);
143 acpid_log(LOG_ERR, "group %s does not exist", socketgroup);
146 if (stat(socketfile, &buf) < 0) {
147 acpid_log(LOG_ERR, "can't stat %s: %s",
148 socketfile, strerror(errno));
151 if (chown(socketfile, buf.st_uid, gr->gr_gid) < 0) {
152 acpid_log(LOG_ERR, "can't chown %s: %s",
153 socketfile, strerror(errno));
159 /* don't leak fds when execing */
160 if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
162 acpid_log(LOG_ERR, "fcntl() on socket %s for FD_CLOEXEC: %s",
163 socketfile, strerror(errno));
167 /* avoid a potential hang */
168 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
170 acpid_log(LOG_ERR, "fcntl() on socket %s for O_NONBLOCK: %s",
171 socketfile, strerror(errno));
175 /* add a connection to the list */
177 c.process = process_sock;