xref: /minix/minix/drivers/tty/pty/ptyfs.c (revision 0a6a1f1d)
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
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
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
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
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