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