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