diff options
Diffstat (limited to 'helper/helper_proto.c')
-rw-r--r-- | helper/helper_proto.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/helper/helper_proto.c b/helper/helper_proto.c new file mode 100644 index 0000000..3abe263 --- /dev/null +++ b/helper/helper_proto.c @@ -0,0 +1,167 @@ +/* Part of mate-screensaver. + * + * Copyright (c) 2019-2021 Paul Wolneykien <[email protected]> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/* Provides functions for two-way communication between the screensaver + * and the helper program. The idea of helper program is to be able to + * run mate-screensaver-dialog without any setuid bits. + */ + +#include "config.h" + +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#include "helper_proto.h" + +static ssize_t +read_all (int fd, void *buf, size_t count) +{ + ssize_t rd, t_rd = 0; + + if (0 == count) + return 0; + + while (t_rd < count) + { + rd = read (fd, buf + t_rd, count - t_rd); + if (0 == rd) + break; + if (rd < 0) + return rd; + t_rd += rd; + } + + return t_rd; +} + +ssize_t +read_msg (int fd, char *buf, size_t length) +{ + size_t msg_len; + ssize_t rd; + + rd = read_all (fd, &msg_len, sizeof msg_len); + if (rd < 0) + return HELPER_IO_ERR; + if (rd > 0 && rd != sizeof msg_len) + return HELPER_LENGTH_READ_ERR; + + if (msg_len >= length) + return HELPER_TOO_LONG_ERR; + + if (msg_len > 0) + { + rd = read_all (fd, buf, msg_len); + if (rd < 0) + return HELPER_IO_ERR; + if (rd != msg_len) + return HELPER_MSG_READ_ERR; + } + else + rd = 0; + buf[rd] = '\0'; + + return rd; +} + +int +read_prompt (int fd, char *buf, size_t *length) +{ + int msg_type, rd; + + rd = read_all (fd, &msg_type, sizeof msg_type); + if (0 == rd) + return 0; + if (rd < 0) + return HELPER_IO_ERR; + if (rd > 0 && rd != sizeof msg_type) + return HELPER_TYPE_READ_ERR; + + rd = read_msg (fd, buf, *length); + if (rd < 0) + return rd; + + *length = rd; + return msg_type; +} + +static ssize_t +write_all (int fd, const void *buf, size_t count) +{ + ssize_t wt, t_wt = 0; + + if (0 == count) + return 0; + + while (t_wt < count) + { + wt = write (fd, buf + t_wt, count - t_wt); + if (0 == wt) + break; + if (wt < 0) + return wt; + t_wt += wt; + } + + return t_wt; +} + +ssize_t +write_msg (int fd, const void *buf, size_t length) +{ + ssize_t wt; + + wt = write_all (fd, &length, sizeof length); + if (wt < 0) + return HELPER_IO_ERR; + if (wt > 0 && wt != sizeof length) + return HELPER_LENGTH_WRITE_ERR; + + if (length > 0) + { + wt = write_all (fd, buf, length); + if (wt < 0) + return HELPER_IO_ERR; + if (wt != length) + return HELPER_MSG_WRITE_ERR; + } + else + wt = 0; + + return wt; +} + +int +write_prompt (int fd, int msg_type, const void *buf, size_t length) +{ + ssize_t wt; + + wt = write_all (fd, &msg_type, sizeof msg_type); + if (wt < 0) + return HELPER_IO_ERR; + if (wt > 0 && wt != sizeof msg_type) + return HELPER_TYPE_WRITE_ERR; + + wt = write_msg (fd, buf, length); + + return wt; +} |