1 /* ptyfs.c - communication to PTYFS */
2
3 #include <minix/driver.h>
4 #include <minix/ds.h>
5
6 #include "ptyfs.h"
7
8 /*
9 * Perform synchronous communication with PTYFS, if PTYFS is actually running.
10 * This function is expected to return only once PTYFS has acknowledged
11 * processing the request, in order to avoid race conditions between PTYFS and
12 * userland. The function must always fail when PTYFS is not available for any
13 * reason. Return OK on success, or an IPC-level error on failure.
14 */
15 static int
ptyfs_sendrec(message * m_ptr)16 ptyfs_sendrec(message * m_ptr)
17 {
18 endpoint_t endpt;
19
20 /*
21 * New pseudoterminals are created sufficiently rarely that we need not
22 * optimize this by for example caching the PTYFS endpoint, especially
23 * since caching brings along new issues, such as having to reissue the
24 * request if the cached endpoint turns out to be outdated (e.g., when
25 * ptyfs is unmounted and remounted for whatever reason).
26 */
27 if (ds_retrieve_label_endpt("ptyfs", &endpt) != OK)
28 return EDEADSRCDST; /* ptyfs is not available */
29
30 return ipc_sendrec(endpt, m_ptr);
31 }
32
33 /*
34 * Add or update a node on PTYFS, with the given node index and attributes.
35 * Return OK on success, or an error code on failure. Errors may include
36 * communication failures and out-of-memory conditions.
37 */
38 int
ptyfs_set(unsigned int index,mode_t mode,uid_t uid,gid_t gid,dev_t dev)39 ptyfs_set(unsigned int index, mode_t mode, uid_t uid, gid_t gid, dev_t dev)
40 {
41 message m;
42 int r;
43
44 memset(&m, 0, sizeof(m));
45
46 m.m_type = PTYFS_SET;
47 m.m_pty_ptyfs_req.index = index;
48 m.m_pty_ptyfs_req.mode = mode;
49 m.m_pty_ptyfs_req.uid = uid;
50 m.m_pty_ptyfs_req.gid = gid;
51 m.m_pty_ptyfs_req.dev = dev;
52
53 if ((r = ptyfs_sendrec(&m)) != OK)
54 return r;
55
56 return m.m_type;
57 }
58
59 /*
60 * Remove a node from PTYFS. Return OK on success, or an error code on
61 * failure. The function succeeds even if no node existed for the given index.
62 */
63 int
ptyfs_clear(unsigned int index)64 ptyfs_clear(unsigned int index)
65 {
66 message m;
67 int r;
68
69 memset(&m, 0, sizeof(m));
70
71 m.m_type = PTYFS_CLEAR;
72 m.m_pty_ptyfs_req.index = index;
73
74 if ((r = ptyfs_sendrec(&m)) != OK)
75 return r;
76
77 return m.m_type;
78 }
79
80 /*
81 * Obtain the file name for the PTYFS node with the given index, and store it
82 * in the given 'name' buffer which consists of 'size' bytes. On success,
83 * return OK, with the file name stored as a null-terminated string. The
84 * returned name does not include the PTYFS mount path. On failure, return an
85 * error code. Among other reasons, the function fails if no node is allocated
86 * for the given index, and if the name does not fit in the given buffer.
87 */
88 int
ptyfs_name(unsigned int index,char * name,size_t size)89 ptyfs_name(unsigned int index, char * name, size_t size)
90 {
91 message m;
92 int r;
93
94 memset(&m, 0, sizeof(m));
95
96 m.m_type = PTYFS_NAME;
97 m.m_pty_ptyfs_req.index = index;
98
99 if ((r = ptyfs_sendrec(&m)) != OK)
100 return r;
101
102 if (m.m_type != OK)
103 return m.m_type;
104
105 /* Ensure null termination, and make sure the string fits. */
106 m.m_ptyfs_pty_name.name[sizeof(m.m_ptyfs_pty_name.name) - 1] = 0;
107 if (strlen(m.m_ptyfs_pty_name.name) >= size)
108 return ENAMETOOLONG;
109
110 strlcpy(name, m.m_ptyfs_pty_name.name, size);
111 return OK;
112 }
113