1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999-2021 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16 #ifdef HAVE_CONFIG_H
17 # include <config.h>
18 #endif
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <sys/un.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26
27 #include <mailutils/types.h>
28 #include <mailutils/alloc.h>
29 #include <mailutils/error.h>
30 #include <mailutils/errno.h>
31 #include <mailutils/nls.h>
32 #include <mailutils/stream.h>
33 #include <mailutils/sys/file_stream.h>
34
35 static int
_socket_open(mu_stream_t stream)36 _socket_open (mu_stream_t stream)
37 {
38 struct _mu_file_stream *s = (struct _mu_file_stream *) stream;
39 int fd;
40 struct sockaddr_un addr;
41
42 if (!s)
43 return EINVAL;
44
45 fd = socket (PF_UNIX, SOCK_STREAM, 0);
46 if (fd < 0)
47 return errno;
48
49 memset (&addr, 0, sizeof addr);
50 addr.sun_family = AF_UNIX;
51 strncpy (addr.sun_path, s->filename, sizeof addr.sun_path - 1);
52 addr.sun_path[sizeof addr.sun_path - 1] = 0;
53 if (connect (fd, (struct sockaddr *) &addr, sizeof(addr)))
54 {
55 close (fd);
56 return errno;
57 }
58
59 s->fd = fd;
60
61 return 0;
62 }
63
64 int
_socket_shutdown(mu_stream_t stream,int how)65 _socket_shutdown (mu_stream_t stream, int how)
66 {
67 struct _mu_file_stream *s = (struct _mu_file_stream *) stream;
68 int flag;
69
70 switch (how)
71 {
72 case MU_STREAM_READ:
73 flag = SHUT_RD;
74 break;
75
76 case MU_STREAM_WRITE:
77 flag = SHUT_WR;
78 }
79
80 if (shutdown (s->fd, flag))
81 return errno;
82 return 0;
83 }
84
85 int
mu_socket_stream_create(mu_stream_t * pstream,const char * filename,int flags)86 mu_socket_stream_create (mu_stream_t *pstream, const char *filename, int flags)
87 {
88 int rc;
89 mu_stream_t transport;
90 int need_cache;
91 struct _mu_file_stream *fstr;
92
93 need_cache = flags & MU_STREAM_SEEK;
94 if (need_cache && (flags & MU_STREAM_WRITE))
95 /* Write caches are not supported */
96 return EINVAL;
97
98 /* Create transport stream. */
99 rc = _mu_file_stream_create (&fstr, sizeof (*fstr),
100 filename, -1,
101 flags & ~MU_STREAM_SEEK);
102 if (rc)
103 return rc;
104 fstr->stream.open = _socket_open;
105 fstr->stream.shutdown = _socket_shutdown;
106 transport = (mu_stream_t) fstr;
107
108 /* Wrap it in cache, if required */
109 if (need_cache)
110 {
111 mu_stream_t str;
112 rc = mu_rdcache_stream_create (&str, transport, flags);
113 mu_stream_unref (transport);
114 if (rc)
115 return rc;
116 transport = str;
117 }
118
119 rc = mu_stream_open (transport);
120 if (rc)
121 mu_stream_unref (transport);
122 else
123 *pstream = transport;
124 return rc;
125 }
126