1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2006-2007 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program 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
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include <sys/socket.h>
35 #include <glib/gprintf.h>
47 #include <sys/resource.h>
53 #include "pwmd_error.h"
56 void send_to_client(struct client_s
*client
, const gchar
*fmt
, ...)
65 for (p
= client
->outbuf
, n
= 0; *p
; p
++, n
++);
67 if ((client
->outbuf
= g_realloc(client
->outbuf
, (n
+ 2) * sizeof(gchar
*))) == NULL
) {
72 client
->outbuf
[n
++] = g_strdup_vprintf(fmt
, ap
);
73 client
->outbuf
[n
] = NULL
;
77 void send_error(struct client_s
*client
, int pwmd_errno
)
79 send_to_client(client
, "ERR %03i %s\n", pwmd_errno
, pwmd_strerror(pwmd_errno
));
82 void log_write(const gchar
*fmt
, ...)
94 if ((fd
= open(logfile
, O_WRONLY
|O_CREAT
|O_APPEND
, 0600)) == -1) {
100 g_vasprintf(&args
, fmt
, ap
);
103 tm
= localtime(&now
);
104 strftime(tbuf
, sizeof(tbuf
), "%b %d %Y %H:%M:%S ", tm
);
105 tbuf
[sizeof(tbuf
) - 1] = 0;
106 line
= g_strdup_printf("%s %i %s\n", tbuf
, getpid(), args
);
107 write(fd
, line
, strlen(line
));
113 static void catchsig(gint sig
)
117 log_write("caught signal %i (%s)", sig
, strsignal(sig
));
121 waitpid(-1, &status
, 0);
124 log_write("clearing file cache");
125 memset(shm_data
, 0, cache_size
);
129 shutdown(sfd
, SHUT_RDWR
);
135 static void usage(gchar
*pn
)
138 "Usage: %s [-hv] [-f <rcfile>]\n"
139 " -f load the specified rcfile (~/.pwmdrc)\n"
141 " -h this help text\n",
146 gchar
**split_input_line(gchar
*str
, gchar
*delim
, gint n
)
151 return g_strsplit(str
, delim
, n
);
154 static void setup_gcrypt()
156 gcry_check_version(NULL
);
158 if (gcry_cipher_algo_info(GCRY_CIPHER_AES256
, GCRYCTL_TEST_ALGO
, NULL
,
160 errx(EXIT_FAILURE
, "AES cipher not supported");
162 gcry_cipher_algo_info(GCRY_CIPHER_AES256
, GCRYCTL_GET_KEYLEN
, NULL
, &gcrykeysize
);
163 gcry_cipher_algo_info(GCRY_CIPHER_AES256
, GCRYCTL_GET_BLKLEN
, NULL
, &gcryblocksize
);
166 static gint
input_parser(gchar
*str
)
172 str
= g_strchug(str
);
177 while ((p
= strsep(&str
, "\n")) != NULL
) {
178 if (g_ascii_strcasecmp(p
, "QUIT") == 0)
180 else if (g_ascii_strcasecmp(p
, "HELP") == 0)
181 help_command(cl
, NULL
);
182 else if (g_ascii_strncasecmp(p
, "HELP ", 5) == 0) {
187 else if (g_ascii_strcasecmp(p
, "LIST") == 0 ||
188 g_ascii_strncasecmp(p
, "LIST ", 5) == 0) {
189 if (cl
->state
!= STATE_OPEN
)
190 send_error(cl
, EPWMD_NO_FILE
);
194 else if (g_ascii_strncasecmp(p
, "STORE ", 6) == 0) {
198 if (cl
->state
!= STATE_OPEN
)
199 send_error(cl
, EPWMD_NO_FILE
);
201 if ((req
= split_input_line(t
, "\t", 0)) != NULL
) {
202 if (store_command(cl
, req
) == TRUE
)
203 send_to_client(cl
, "OK \n");
206 send_error(cl
, EPWMD_COMMAND_SYNTAX
);
209 else if (g_ascii_strncasecmp(p
, "DELETE ", 7) == 0) {
212 if (cl
->state
!= STATE_OPEN
)
213 send_error(cl
, EPWMD_NO_FILE
);
215 if ((req
= split_input_line(t
, "\t", 0)) != NULL
) {
216 if (delete_command(cl
, req
) == TRUE
)
217 send_to_client(cl
, "OK \n");
220 send_error(cl
, EPWMD_COMMAND_SYNTAX
);
223 else if (g_ascii_strncasecmp(p
, "GET ", 4) == 0) {
227 if (cl
->state
!= STATE_OPEN
)
228 send_error(cl
, EPWMD_NO_FILE
);
230 if ((req
= split_input_line(t
, "\t", 0)) != NULL
)
231 get_command(cl
, &cl
->reader
, req
, 0);
233 send_error(cl
, EPWMD_COMMAND_SYNTAX
);
236 else if (g_ascii_strncasecmp(p
, "ATTR ", 5) == 0) {
240 if (cl
->state
!= STATE_OPEN
)
241 send_error(cl
, EPWMD_NO_FILE
);
243 if ((req
= split_input_line(t
, " ", 4)) != NULL
) {
244 if (attr_command(cl
, req
) == TRUE
)
245 send_to_client(cl
, "OK \n");
248 send_error(cl
, EPWMD_COMMAND_SYNTAX
);
251 else if (g_ascii_strncasecmp(p
, "OPEN ", 5) == 0) {
255 if (cl
->state
== STATE_OPEN
)
256 send_error(cl
, EPWMD_FILE_OPENED
);
258 if ((req
= split_input_line(t
, " ", 2)) != NULL
) {
259 if (open_command(cl
, req
) == TRUE
) {
260 send_to_client(cl
, "OK \n");
261 cl
->state
= STATE_OPEN
;
265 * The document has been parsed and is stored in cl->doc.
268 memset(cl
->xml
, 0, cl
->len
);
274 send_error(cl
, EPWMD_COMMAND_SYNTAX
);
277 else if (g_ascii_strncasecmp(p
, "SAVE", 4) == 0) {
281 if (cl
->state
!= STATE_OPEN
)
282 send_error(cl
, EPWMD_NO_FILE
);
284 req
= split_input_line(t
, " ", 1);
286 if (save_command(cl
, cl
->filename
, (req
) ? req
[0] : NULL
) == TRUE
)
287 send_to_client(cl
, "OK \n");
290 else if (g_ascii_strncasecmp(p
, "CACHE ", 6) == 0) {
293 req
= split_input_line(t
, " ", 2);
295 if (cache_command(cl
, req
) == TRUE
)
296 send_to_client(cl
, "OK \n");
298 else if (g_ascii_strncasecmp(p
, "DUMP", 4) == 0) {
299 if (cl
->state
!= STATE_OPEN
)
300 send_error(cl
, EPWMD_NO_FILE
);
302 if (dump_command(cl
) == TRUE
)
303 send_to_client(cl
, "OK \n");
307 send_error(cl
, EPWMD_COMMAND_SYNTAX
);
318 static gboolean
source_prepare(GSource
*src
, gint
*to
)
320 if (cl
->gfd
.revents
& (G_IO_HUP
|G_IO_NVAL
|G_IO_ERR
))
326 static gboolean
source_check(GSource
*src
)
328 if (cl
->gfd
.revents
& (G_IO_IN
|G_IO_PRI
))
331 if (cl
->outbuf
&& (cl
->gfd
.revents
& (G_IO_OUT
)))
337 static gboolean
source_dispatch(GSource
*src
, GSourceFunc cb
, gpointer data
)
342 static gboolean
source_cb(gpointer data
)
347 GError
*gerror
= NULL
;
350 if (cl
->gfd
.revents
& (G_IO_HUP
|G_IO_NVAL
|G_IO_ERR
))
353 if (cl
->outbuf
&& (cl
->gfd
.revents
& (G_IO_OUT
))) {
354 for (p
= cl
->outbuf
; *p
; p
++) {
355 ret
= g_io_channel_write_chars(cl
->ioc
, *p
, -1, &len
, &gerror
);
357 if (ret
== G_IO_STATUS_NORMAL
)
358 g_io_channel_flush(cl
->ioc
, &gerror
);
360 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gerror
->message
);
362 g_clear_error(&gerror
);
368 g_strfreev(cl
->outbuf
);
372 if (!cl
->gfd
.revents
& (G_IO_IN
))
375 ret
= g_io_channel_read_line(cl
->ioc
, &line
, &len
, NULL
, &gerror
);
377 if (ret
!= G_IO_STATUS_NORMAL
) {
378 if (ret
== G_IO_STATUS_EOF
)
381 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gerror
->message
);
382 g_clear_error(&gerror
);
386 line
[g_utf8_strlen(line
, -1) - 1] = 0;
388 switch (input_parser(line
)) {
392 memset(line
, 0, len
);
396 g_clear_error(&gerror
);
399 memset(cl
->xml
, 0, cl
->len
);
404 gcry_cipher_close(cl
->gh
);
410 xmlFreeTextReader(cl
->reader
);
416 g_free(cl
->filename
);
419 g_slist_free(memlist
);
421 g_main_loop_unref(gloop
);
422 g_main_loop_quit(gloop
);
428 memset(line
, 0, len
);
433 static void xmlfree(void *ptr
)
443 if ((p
= g_slist_nth_data(memlist
, n
)) == NULL
)
448 if (data
->data
== ptr
) {
449 memset(data
->data
, 0, data
->size
);
451 memlist
= g_slist_remove(memlist
, p
);
457 warnx("xmlfree(): %p not found", ptr
);
462 static void *xmlmalloc(size_t size
)
470 if ((new = malloc(sizeof(mem_t
))) == NULL
)
473 if ((p
= malloc(size
)) == NULL
) {
480 memlist
= g_slist_append(memlist
, new);
484 static void *xmlrealloc(void *ptr
, size_t size
)
491 return xmlmalloc(size
);
497 if ((p
= g_slist_nth_data(memlist
, n
)) == NULL
)
502 if (data
->data
== ptr
) {
503 if ((new = malloc(size
)) == NULL
)
506 memcpy(new, data
->data
, (size
< data
->size
) ? size
: data
->size
);
507 memset(data
->data
, 0, data
->size
);
516 warnx("xmlrealloc(): %p not found", ptr
);
522 static char *xmlstrdup(const char *str
)
532 len
= strlen(str
) + 1;
534 if ((new = xmlmalloc(len
* sizeof(char))) == NULL
)
537 for (p
= str
, np
= new; *p
; p
++)
545 * Called every time a connection is made.
547 static void doit(int fd
)
549 static GSourceFuncs gsrcf
= {
550 source_prepare
, source_check
, source_dispatch
, NULL
, 0, 0
552 GPollFD gfd
= { fd
, G_IO_IN
|G_IO_OUT
|G_IO_HUP
|G_IO_ERR
, 0 };
555 if (use_mlock
&& mlockall(MCL_FUTURE
) == -1)
556 err(EXIT_FAILURE
, "mlockall()");
559 gloop
= g_main_loop_new(NULL
, TRUE
);
560 cl
= g_malloc0(sizeof(struct client_s
));
561 cl
->src
= g_source_new(&gsrcf
, sizeof(GSource
));
563 cl
->state
= STATE_CONNECTED
;
564 cl
->ioc
= g_io_channel_unix_new(fd
);
565 g_source_add_poll(cl
->src
, &cl
->gfd
);
566 g_source_set_callback(cl
->src
, source_cb
, NULL
, NULL
);
567 g_source_attach(cl
->src
, NULL
);
574 if ((gcryerrno
= gcry_cipher_open(&cl
->gh
, GCRY_CIPHER_AES256
, GCRY_CIPHER_MODE_CBC
, 0))) {
575 send_to_client(cl
, "ERR %03i gcrypt: %s\n", EPWMD_ERROR
, gcry_strerror(gcryerrno
));
576 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gcry_strerror(gcryerrno
));
580 // FIXME 100% CPU if removed (poll()).
581 send_to_client(cl
, "OK \n");
583 xmlMemSetup(xmlfree
, xmlmalloc
, xmlrealloc
, xmlstrdup
);
585 g_main_loop_run(gloop
);
586 g_io_channel_unref(cl
->ioc
);
588 shutdown(fd
, SHUT_RDWR
);
589 log_write("exiting");
593 static void set_rcfile_defaults(GKeyFile
*kf
)
597 snprintf(buf
, sizeof(buf
), "~/.pwmd/socket");
598 g_key_file_set_string(kf
, "default", "socket_path", buf
);
599 snprintf(buf
, sizeof(buf
), "~/.pwmd");
600 g_key_file_set_string(kf
, "default", "data_directory", buf
);
601 snprintf(buf
, sizeof(buf
), "~/.pwmd/.log");
602 g_key_file_set_string(kf
, "default", "log_path", buf
);
603 g_key_file_set_boolean(kf
, "default", "enable_logging", FALSE
);
604 g_key_file_set_integer(kf
, "default", "cache_size", cache_size
);
605 g_key_file_set_boolean(kf
, "default", "disable_mlockall", FALSE
);
608 static GKeyFile
*parse_rcfile(const gchar
*filename
)
610 GKeyFile
*kf
= g_key_file_new();
611 GError
*error
= NULL
;
613 if (g_key_file_load_from_file(kf
, filename
, G_KEY_FILE_NONE
, &error
) == FALSE
) {
614 if (error
->code
== G_FILE_ERROR_NOENT
) {
615 g_clear_error(&error
);
616 set_rcfile_defaults(kf
);
620 warnx("%s: %s", filename
, error
->message
);
621 g_clear_error(&error
);
629 static gboolean
try_xml_decrypt(gint fd
, struct stat st
, guchar
*key
, gchar
**xml
,
636 if ((gcryerrno
= gcry_cipher_open(&gh
, GCRY_CIPHER_AES256
, GCRY_CIPHER_MODE_CBC
, 0))) {
637 warnx("%s(%i): %s", __FUNCTION__
, __LINE__
, gcry_strerror(gcryerrno
));
641 inbuf
= gcry_malloc(st
.st_size
);
642 read(fd
, inbuf
, st
.st_size
);
644 iv
= gcry_malloc(gcryblocksize
);
645 memcpy(iv
, inbuf
, gcryblocksize
);
647 if (decrypt_xml(gh
, key
, gcrykeysize
, iv
, inbuf
+ gcryblocksize
,
648 st
.st_size
- gcryblocksize
, NULL
, 0) == FALSE
) {
649 memset(inbuf
, 0, st
.st_size
);
656 memmove(inbuf
, inbuf
+ gcryblocksize
, st
.st_size
- gcryblocksize
);
658 *len
= st
.st_size
- gcryblocksize
;
660 if (g_strncasecmp(*xml
, "<?xml version=\"1.0\"?>", 21) != 0)
666 static gboolean
get_input(const gchar
*filename
, guchar
*key
)
668 gchar buf
[LINE_MAX
], *p
;
669 struct termios told
, tnew
;
675 gint tty
= isatty(STDIN_FILENO
);
677 if ((fd
= open_file(filename
, &st
)) == -1)
680 if (st
.st_size
== 0) {
681 fprintf(stderr
, "Skipping empty file '%s'.\n", filename
);
687 if (tcgetattr(STDIN_FILENO
, &told
) == -1)
688 err(EXIT_FAILURE
, "tcgetattr()");
690 memcpy(&tnew
, &told
, sizeof(struct termios
));
691 tnew
.c_lflag
&= ~(ECHO
);
692 tnew
.c_lflag
|= ICANON
|ECHONL
;
697 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tnew
) == -1) {
698 tcsetattr(STDIN_FILENO
, TCSANOW
, &told
);
699 err(EXIT_FAILURE
, "tcsetattr()");
703 printf("Password for '%s': ", filename
);
705 if ((p
= fgets(buf
, sizeof(buf
), stdin
)) == NULL
) {
707 tcsetattr(STDIN_FILENO
, TCSANOW
, &told
);
714 tcsetattr(STDIN_FILENO
, TCSANOW
, &told
);
716 p
[strlen(p
) - 1] = 0;
719 fprintf(stderr
, "Skipping.\n");
724 gcry_md_hash_buffer(GCRY_MD_SHA256
, key
, p
, strlen(p
));
725 memset(buf
, 0, sizeof(buf
));
727 if (try_xml_decrypt(fd
, st
, key
, &xml
, &len
) == FALSE
) {
734 fprintf(stderr
, "Invalid password. Skipping file.\n");
738 fprintf(stderr
, "Invalid password.\n");
748 gint
cache_file_count()
755 for (p
= shm_data
, len
= 0; len
<= cache_size
;) {
756 memcpy(&f
, p
, sizeof(file_cache_t
));
761 p
+= sizeof(file_cache_t
);
762 len
+= sizeof(file_cache_t
);
764 if (len
+ sizeof(file_cache_t
) > cache_size
)
771 gboolean
cache_add_file(const guchar
*md5file
, const guchar
*shakey
)
775 gint nfiles
= cache_file_count();
779 * Make sure there is enough secure memory.
781 if (!md5file
|| (nfiles
+ 1) * sizeof(file_cache_t
) > cache_size
)
785 * Find the first available "slot".
787 for (p
= shm_data
, len
= 0; len
<= cache_size
;) {
788 memcpy(&f
, p
, sizeof(file_cache_t
));
790 if (f
.used
== FALSE
) {
791 memcpy(&f
.filename
, md5file
, sizeof(f
.filename
));
794 memcpy(&f
.key
, shakey
, sizeof(f
.key
));
797 memcpy(p
, &f
, sizeof(file_cache_t
));
801 p
+= sizeof(file_cache_t
);
802 len
+= sizeof(file_cache_t
);
804 if (len
+ sizeof(file_cache_t
) > cache_size
)
811 int main(int argc
, char *argv
[])
814 struct sockaddr_un addr
;
815 struct passwd
*pw
= getpwuid(getuid());
817 gchar
*socketpath
= NULL
, *socketdir
, *socketname
= NULL
;
818 gchar
*socketarg
= NULL
;
819 gchar
*datadir
= NULL
;
824 gchar
**cache_push
= NULL
;
827 #ifdef HAVE_SETRLIMIT
830 rl
.rlim_cur
= rl
.rlim_max
= 0;
832 if (setrlimit(RLIMIT_CORE
, &rl
) != 0)
833 err(EXIT_FAILURE
, "setrlimit()");
837 rcfile
= g_strdup_printf("%s/.pwmdrc", pw
->pw_dir
);
839 if ((page_size
= sysconf(_SC_PAGESIZE
)) == -1)
840 err(EXIT_FAILURE
, "sysconf()");
842 cache_size
= page_size
;
846 * Default to using mlockall().
851 while ((opt
= getopt(argc
, argv
, "hvf:")) != EOF
) {
855 rcfile
= g_strdup(optarg
);
858 printf("%s\n%s\n", PACKAGE_STRING
, PACKAGE_BUGREPORT
);
866 if ((kf
= parse_rcfile(rcfile
)) == NULL
)
869 g_key_file_set_list_separator(kf
, ',');
871 if ((p
= g_key_file_get_string(kf
, "default", "socket_path", NULL
)) == NULL
)
872 errx(EXIT_FAILURE
, "%s: socket_path not defined", rcfile
);
876 snprintf(buf
, sizeof(buf
), "%s%s", g_get_home_dir(), p
--);
878 socketarg
= g_strdup(buf
);
883 if ((p
= g_key_file_get_string(kf
, "default", "data_directory", NULL
)) == NULL
)
884 errx(EXIT_FAILURE
, "%s: data_directory not defined", rcfile
);
888 snprintf(buf
, sizeof(buf
), "%s%s", g_get_home_dir(), p
--);
890 datadir
= g_strdup(buf
);
895 if (g_key_file_has_key(kf
, "default", "cache_size", NULL
) == TRUE
) {
896 cache_size
= g_key_file_get_integer(kf
, "default", "cache_size", NULL
);
898 if (cache_size
< page_size
|| cache_size
% page_size
)
899 errx(EXIT_FAILURE
, "cache size must be in multiples of %li.", page_size
);
903 if (g_key_file_has_key(kf
, "default", "disable_mlockall", NULL
) == TRUE
)
904 use_mlock
= g_key_file_get_integer(kf
, "default", "disable_mlockall", NULL
);
907 if (g_key_file_has_key(kf
, "default", "log_path", NULL
) == TRUE
) {
908 if (g_key_file_has_key(kf
, "default", "enable_logging", NULL
) == TRUE
) {
909 n
= g_key_file_get_boolean(kf
, "default", "enable_logging", NULL
);
912 p
= g_key_file_get_string(kf
, "default", "log_path", NULL
);
916 snprintf(buf
, sizeof(buf
), "%s%s", g_get_home_dir(), p
--);
918 logfile
= g_strdup(buf
);
926 if (g_key_file_has_key(kf
, "default", "cache_push", NULL
) == TRUE
)
927 cache_push
= g_key_file_get_string_list(kf
, "default", "cache_push", NULL
, NULL
);
931 if (strchr(socketarg
, '/') == NULL
) {
932 socketdir
= g_get_current_dir();
933 socketname
= g_strdup(socketarg
);
934 socketpath
= g_strdup_printf("%s/%s", socketdir
, socketname
);
937 socketname
= g_strdup(strrchr(socketarg
, '/'));
939 socketarg
[strlen(socketarg
) - strlen(socketname
) -1] = 0;
940 socketdir
= g_strdup(socketarg
);
941 socketpath
= g_strdup_printf("%s/%s", socketdir
, socketname
);
944 snprintf(buf
, sizeof(buf
), "%s", datadir
);
946 if (mkdir(buf
, 0700) == -1 && errno
!= EEXIST
)
947 err(EXIT_FAILURE
, "%s", buf
);
949 #ifdef MMAP_ANONYMOUS_SHARED
950 if ((shm_data
= mmap(NULL
, cache_size
, PROT_READ
|PROT_WRITE
,
951 MAP_SHARED
|MAP_ANONYMOUS
, -1, 0)) == NULL
) {
952 err(EXIT_FAILURE
, "mmap()");
955 snprintf(buf
, sizeof(buf
), "pwmd.%i", pw
->pw_uid
);
957 if ((fd
= shm_open(buf
, O_CREAT
|O_RDWR
|O_EXCL
, 0600)) == -1)
958 err(EXIT_FAILURE
, "shm_open(): %s", buf
);
961 * Should be enough for the file cache.
963 if (ftruncate(fd
, cache_size
) == -1)
964 err(EXIT_FAILURE
, "ftruncate()");
966 if ((shm_data
= mmap(NULL
, cache_size
, PROT_READ
|PROT_WRITE
, MAP_SHARED
,
969 err(EXIT_FAILURE
, "mmap()");
975 if (mlock(shm_data
, cache_size
) == -1)
979 * bind() doesn't like the full pathname of the socket or any non alphanum
980 * characters so change to the directory where the socket is wanted then
981 * create it then change to datadir.
983 if (chdir(socketdir
))
984 err(EXIT_FAILURE
, "%s", socketdir
);
988 if ((sfd
= socket(PF_UNIX
, SOCK_STREAM
, 0)) == -1)
989 err(EXIT_FAILURE
, "socket()");
991 addr
.sun_family
= AF_UNIX
;
992 snprintf(addr
.sun_path
, sizeof(addr
.sun_path
), "%s", socketname
);
993 g_free(--socketname
);
995 if (bind(sfd
, (struct sockaddr
*)&addr
, sizeof(struct sockaddr
)) == -1)
996 err(EXIT_FAILURE
, "bind()");
998 if (chdir(datadir
)) {
1001 err(EXIT_FAILURE
, "%s", datadir
);
1008 * Set the cache entry for a file. Prompts for the password.
1014 for (opt
= 0; cache_push
[opt
]; opt
++) {
1015 p
= cache_push
[opt
];
1023 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, p
, strlen(p
));
1025 if (access(p
, R_OK
|W_OK
) != 0) {
1026 if (errno
!= ENOENT
) {
1028 err(EXIT_FAILURE
, "%s", p
);
1035 if (get_input(p
, key
) == FALSE
) {
1036 memset(key
, 0, sizeof(key
));
1040 if (cache_add_file(md5file
, key
) == FALSE
) {
1041 memset(key
, 0, sizeof(key
));
1042 errx(EXIT_FAILURE
, "%s: couldn't add file (cache_size?)", p
);
1045 fprintf(stderr
, "Added.\n");
1046 memset(key
, 0, sizeof(key
));
1047 memset(md5file
, 0, sizeof(md5file
));
1050 g_strfreev(cache_push
);
1051 fprintf(stderr
, "Done! Daemonizing...\n");
1056 if (listen(sfd
, 0) == -1)
1057 err(EXIT_FAILURE
, "listen()");
1059 signal(SIGCHLD
, catchsig
);
1060 signal(SIGTERM
, catchsig
);
1061 signal(SIGINT
, catchsig
);
1062 signal(SIGHUP
, catchsig
);
1063 log_write("%s starting: %li slots available", PACKAGE_STRING
, cache_size
/ sizeof(file_cache_t
));
1066 socklen_t slen
= sizeof(struct sockaddr_un
);
1067 struct sockaddr_un raddr
;
1070 if ((fd
= accept(sfd
, (struct sockaddr_un
*)&raddr
, &slen
)) == -1) {
1072 log_write("accept(): %s", strerror(errno
));
1077 switch ((pid
= fork())) {
1079 log_write("fork(): %s", strerror(errno
));
1088 log_write("new connection: fd=%i, pid=%i", fd
, pid
);
1094 if (munmap(shm_data
, cache_size
) == -1)
1095 log_write("munmap(): %s", strerror(errno
));
1097 #ifndef MMAP_ANONYMOUS_SHARED
1098 if (shm_unlink(buf
) == -1)
1099 log_write("shm_unlink(): %s: %s", buf
, strerror(errno
));
1102 log_write("pwmd exiting normally");