xref: /minix3/minix/fs/ptyfs/ptyfs.c (revision da21d850255e4f11bb2023f69a0b3aad4eab62e2)
1*da21d850SDavid van Moolenbroek /* PTYFS - file system for Unix98 pseudoterminal slave nodes (/dev/pts) */
2*da21d850SDavid van Moolenbroek 
3*da21d850SDavid van Moolenbroek #include <minix/drivers.h>
4*da21d850SDavid van Moolenbroek #include <minix/fsdriver.h>
5*da21d850SDavid van Moolenbroek #include <minix/vfsif.h>
6*da21d850SDavid van Moolenbroek #include <minix/ds.h>
7*da21d850SDavid van Moolenbroek #include <sys/dirent.h>
8*da21d850SDavid van Moolenbroek #include <assert.h>
9*da21d850SDavid van Moolenbroek 
10*da21d850SDavid van Moolenbroek #include "node.h"
11*da21d850SDavid van Moolenbroek 
12*da21d850SDavid van Moolenbroek #define ROOT_INO_NR	1	/* inode number of the root directory */
13*da21d850SDavid van Moolenbroek #define BASE_INO_NR	2	/* first inode number for slave nodes */
14*da21d850SDavid van Moolenbroek 
15*da21d850SDavid van Moolenbroek #define GETDENTS_BUF	1024	/* size of the temporary buffer for getdents */
16*da21d850SDavid van Moolenbroek 
17*da21d850SDavid van Moolenbroek static struct node_data root_data = {
18*da21d850SDavid van Moolenbroek 	.mode	= S_IFDIR | 0755,
19*da21d850SDavid van Moolenbroek 	.uid	= 0,
20*da21d850SDavid van Moolenbroek 	.gid	= 0,
21*da21d850SDavid van Moolenbroek 	.dev	= NO_DEV
22*da21d850SDavid van Moolenbroek };
23*da21d850SDavid van Moolenbroek 
24*da21d850SDavid van Moolenbroek /*
25*da21d850SDavid van Moolenbroek  * Mount the file system.
26*da21d850SDavid van Moolenbroek  */
27*da21d850SDavid van Moolenbroek static int
ptyfs_mount(dev_t __unused dev,unsigned int flags,struct fsdriver_node * root_node,unsigned int * res_flags)28*da21d850SDavid van Moolenbroek ptyfs_mount(dev_t __unused dev, unsigned int flags,
29*da21d850SDavid van Moolenbroek 	struct fsdriver_node * root_node, unsigned int * res_flags)
30*da21d850SDavid van Moolenbroek {
31*da21d850SDavid van Moolenbroek 
32*da21d850SDavid van Moolenbroek 	/* This file system can not be used as a root file system. */
33*da21d850SDavid van Moolenbroek 	if (flags & REQ_ISROOT)
34*da21d850SDavid van Moolenbroek 		return EINVAL;
35*da21d850SDavid van Moolenbroek 
36*da21d850SDavid van Moolenbroek 	/* Return the details of the root node. */
37*da21d850SDavid van Moolenbroek 	root_node->fn_ino_nr = ROOT_INO_NR;
38*da21d850SDavid van Moolenbroek 	root_node->fn_mode = root_data.mode;
39*da21d850SDavid van Moolenbroek 	root_node->fn_uid = root_data.uid;
40*da21d850SDavid van Moolenbroek 	root_node->fn_gid = root_data.gid;
41*da21d850SDavid van Moolenbroek 	root_node->fn_size = 0;
42*da21d850SDavid van Moolenbroek 	root_node->fn_dev = root_data.dev;
43*da21d850SDavid van Moolenbroek 
44*da21d850SDavid van Moolenbroek 	*res_flags = RES_NOFLAGS;
45*da21d850SDavid van Moolenbroek 
46*da21d850SDavid van Moolenbroek 	return OK;
47*da21d850SDavid van Moolenbroek }
48*da21d850SDavid van Moolenbroek 
49*da21d850SDavid van Moolenbroek /*
50*da21d850SDavid van Moolenbroek  * Generate the name string of a slave node based on its node number.  Return
51*da21d850SDavid van Moolenbroek  * OK on success, with the null-terminated name stored in the buffer 'name'
52*da21d850SDavid van Moolenbroek  * which is 'size' bytes in size.  Return an error code on failure.
53*da21d850SDavid van Moolenbroek  */
54*da21d850SDavid van Moolenbroek static int
make_name(char * name,size_t size,node_t index)55*da21d850SDavid van Moolenbroek make_name(char * name, size_t size, node_t index)
56*da21d850SDavid van Moolenbroek {
57*da21d850SDavid van Moolenbroek 	ssize_t r;
58*da21d850SDavid van Moolenbroek 
59*da21d850SDavid van Moolenbroek 	if ((r = snprintf(name, sizeof(name), "%u", index)) < 0)
60*da21d850SDavid van Moolenbroek 		return EINVAL;
61*da21d850SDavid van Moolenbroek 
62*da21d850SDavid van Moolenbroek 	if (r >= size)
63*da21d850SDavid van Moolenbroek 		return ENAMETOOLONG;
64*da21d850SDavid van Moolenbroek 
65*da21d850SDavid van Moolenbroek 	return OK;
66*da21d850SDavid van Moolenbroek }
67*da21d850SDavid van Moolenbroek 
68*da21d850SDavid van Moolenbroek /*
69*da21d850SDavid van Moolenbroek  * Parse the name of a slave node as given by a user, and check whether it is a
70*da21d850SDavid van Moolenbroek  * valid slave node number.  A valid slave number is any name that can be
71*da21d850SDavid van Moolenbroek  * produced by make_name().  Return TRUE if the string was successfully parsed
72*da21d850SDavid van Moolenbroek  * as a slave node number (which may or may not actually be allocated), with
73*da21d850SDavid van Moolenbroek  * the number stored in 'indexp'.  Return FALSE if the name is not a number.
74*da21d850SDavid van Moolenbroek  */
75*da21d850SDavid van Moolenbroek static int
parse_name(const char * name,node_t * indexp)76*da21d850SDavid van Moolenbroek parse_name(const char * name, node_t * indexp)
77*da21d850SDavid van Moolenbroek {
78*da21d850SDavid van Moolenbroek 	node_t index;
79*da21d850SDavid van Moolenbroek 	const char *p;
80*da21d850SDavid van Moolenbroek 
81*da21d850SDavid van Moolenbroek 	index = 0;
82*da21d850SDavid van Moolenbroek 	for (p = name; *p; p++) {
83*da21d850SDavid van Moolenbroek 		/* Digits only. */
84*da21d850SDavid van Moolenbroek 		if (*p < '0' || *p > '9')
85*da21d850SDavid van Moolenbroek 			return FALSE;
86*da21d850SDavid van Moolenbroek 
87*da21d850SDavid van Moolenbroek 		/* No leading zeroes. */
88*da21d850SDavid van Moolenbroek 		if (p != name && index == 0)
89*da21d850SDavid van Moolenbroek 			return FALSE;
90*da21d850SDavid van Moolenbroek 
91*da21d850SDavid van Moolenbroek 		/* No overflow. */
92*da21d850SDavid van Moolenbroek 		if (index * 10 < index)
93*da21d850SDavid van Moolenbroek 			return FALSE;
94*da21d850SDavid van Moolenbroek 
95*da21d850SDavid van Moolenbroek 		index = index * 10 + *p - '0';
96*da21d850SDavid van Moolenbroek 	}
97*da21d850SDavid van Moolenbroek 
98*da21d850SDavid van Moolenbroek 	*indexp = index;
99*da21d850SDavid van Moolenbroek 	return TRUE;
100*da21d850SDavid van Moolenbroek }
101*da21d850SDavid van Moolenbroek 
102*da21d850SDavid van Moolenbroek /*
103*da21d850SDavid van Moolenbroek  * Look up a name in a directory, yielding a node on success.  For a successful
104*da21d850SDavid van Moolenbroek  * lookup, the given name must either be a single dot, which resolves to the
105*da21d850SDavid van Moolenbroek  * file system root directory, or the number of an allocated slave node.
106*da21d850SDavid van Moolenbroek  */
107*da21d850SDavid van Moolenbroek static int
ptyfs_lookup(ino_t dir_nr,char * name,struct fsdriver_node * node,int * is_mountpt)108*da21d850SDavid van Moolenbroek ptyfs_lookup(ino_t dir_nr, char * name, struct fsdriver_node * node,
109*da21d850SDavid van Moolenbroek 	int * is_mountpt)
110*da21d850SDavid van Moolenbroek {
111*da21d850SDavid van Moolenbroek 	struct node_data *data;
112*da21d850SDavid van Moolenbroek 	node_t index;
113*da21d850SDavid van Moolenbroek 	ino_t ino_nr;
114*da21d850SDavid van Moolenbroek 
115*da21d850SDavid van Moolenbroek 	assert(name[0] != '\0');
116*da21d850SDavid van Moolenbroek 
117*da21d850SDavid van Moolenbroek 	if (dir_nr != ROOT_INO_NR)
118*da21d850SDavid van Moolenbroek 		return ENOENT;
119*da21d850SDavid van Moolenbroek 
120*da21d850SDavid van Moolenbroek 	if (name[0] == '.' && name[1] == '\0') {
121*da21d850SDavid van Moolenbroek 		/* The root directory itself is requested. */
122*da21d850SDavid van Moolenbroek 		ino_nr = ROOT_INO_NR;
123*da21d850SDavid van Moolenbroek 
124*da21d850SDavid van Moolenbroek 		data = &root_data;
125*da21d850SDavid van Moolenbroek 	} else {
126*da21d850SDavid van Moolenbroek 		/* Parse the user-provided name, which must be a number. */
127*da21d850SDavid van Moolenbroek 		if (!parse_name(name, &index))
128*da21d850SDavid van Moolenbroek 			return ENOENT;
129*da21d850SDavid van Moolenbroek 
130*da21d850SDavid van Moolenbroek 		ino_nr = BASE_INO_NR + index;
131*da21d850SDavid van Moolenbroek 
132*da21d850SDavid van Moolenbroek 		/* See if the number is in use, and get its details. */
133*da21d850SDavid van Moolenbroek 		if ((data = get_node(index)) == NULL)
134*da21d850SDavid van Moolenbroek 			return ENOENT;
135*da21d850SDavid van Moolenbroek 	}
136*da21d850SDavid van Moolenbroek 
137*da21d850SDavid van Moolenbroek 	node->fn_ino_nr = ino_nr;
138*da21d850SDavid van Moolenbroek 	node->fn_mode = data->mode;
139*da21d850SDavid van Moolenbroek 	node->fn_uid = data->uid;
140*da21d850SDavid van Moolenbroek 	node->fn_gid = data->gid;
141*da21d850SDavid van Moolenbroek 	node->fn_size = 0;
142*da21d850SDavid van Moolenbroek 	node->fn_dev = data->dev;
143*da21d850SDavid van Moolenbroek 
144*da21d850SDavid van Moolenbroek 	*is_mountpt = FALSE;
145*da21d850SDavid van Moolenbroek 
146*da21d850SDavid van Moolenbroek 	return OK;
147*da21d850SDavid van Moolenbroek }
148*da21d850SDavid van Moolenbroek 
149*da21d850SDavid van Moolenbroek /*
150*da21d850SDavid van Moolenbroek  * Enumerate directory contents.
151*da21d850SDavid van Moolenbroek  */
152*da21d850SDavid van Moolenbroek static ssize_t
ptyfs_getdents(ino_t ino_nr,struct fsdriver_data * data,size_t bytes,off_t * posp)153*da21d850SDavid van Moolenbroek ptyfs_getdents(ino_t ino_nr, struct fsdriver_data * data,
154*da21d850SDavid van Moolenbroek 	size_t bytes, off_t * posp)
155*da21d850SDavid van Moolenbroek {
156*da21d850SDavid van Moolenbroek 	struct fsdriver_dentry fsdentry;
157*da21d850SDavid van Moolenbroek 	static char buf[GETDENTS_BUF];
158*da21d850SDavid van Moolenbroek 	char name[NAME_MAX + 1];
159*da21d850SDavid van Moolenbroek 	struct node_data *node_data;
160*da21d850SDavid van Moolenbroek 	unsigned int type;
161*da21d850SDavid van Moolenbroek 	off_t pos;
162*da21d850SDavid van Moolenbroek 	node_t index;
163*da21d850SDavid van Moolenbroek 	ssize_t r;
164*da21d850SDavid van Moolenbroek 
165*da21d850SDavid van Moolenbroek 	if (ino_nr != ROOT_INO_NR)
166*da21d850SDavid van Moolenbroek 		return EINVAL;
167*da21d850SDavid van Moolenbroek 
168*da21d850SDavid van Moolenbroek 	fsdriver_dentry_init(&fsdentry, data, bytes, buf, sizeof(buf));
169*da21d850SDavid van Moolenbroek 
170*da21d850SDavid van Moolenbroek 	for (;;) {
171*da21d850SDavid van Moolenbroek 		pos = (*posp)++;
172*da21d850SDavid van Moolenbroek 
173*da21d850SDavid van Moolenbroek 		if (pos < 2) {
174*da21d850SDavid van Moolenbroek 			strlcpy(name, (pos == 0) ? "." : "..", sizeof(name));
175*da21d850SDavid van Moolenbroek 			ino_nr = ROOT_INO_NR;
176*da21d850SDavid van Moolenbroek 			type = DT_DIR;
177*da21d850SDavid van Moolenbroek 		} else {
178*da21d850SDavid van Moolenbroek 			if (pos - 2 >= get_max_node())
179*da21d850SDavid van Moolenbroek 				break; /* EOF */
180*da21d850SDavid van Moolenbroek 			index = (node_t)(pos - 2);
181*da21d850SDavid van Moolenbroek 
182*da21d850SDavid van Moolenbroek 			if ((node_data = get_node(index)) == NULL)
183*da21d850SDavid van Moolenbroek 				continue; /* index not in use */
184*da21d850SDavid van Moolenbroek 
185*da21d850SDavid van Moolenbroek 			if (make_name(name, sizeof(name), index) != OK)
186*da21d850SDavid van Moolenbroek 				continue; /* could not generate name string */
187*da21d850SDavid van Moolenbroek 			ino_nr = BASE_INO_NR + index;
188*da21d850SDavid van Moolenbroek 			type = IFTODT(node_data->mode);
189*da21d850SDavid van Moolenbroek 		}
190*da21d850SDavid van Moolenbroek 
191*da21d850SDavid van Moolenbroek 		if ((r = fsdriver_dentry_add(&fsdentry, ino_nr, name,
192*da21d850SDavid van Moolenbroek 		    strlen(name), type)) < 0)
193*da21d850SDavid van Moolenbroek 			return r;
194*da21d850SDavid van Moolenbroek 		if (r == 0)
195*da21d850SDavid van Moolenbroek 			break; /* result buffer full */
196*da21d850SDavid van Moolenbroek 	}
197*da21d850SDavid van Moolenbroek 
198*da21d850SDavid van Moolenbroek 	return fsdriver_dentry_finish(&fsdentry);
199*da21d850SDavid van Moolenbroek }
200*da21d850SDavid van Moolenbroek 
201*da21d850SDavid van Moolenbroek /*
202*da21d850SDavid van Moolenbroek  * Return a pointer to the node data structure for the given inode number, or
203*da21d850SDavid van Moolenbroek  * NULL if no node exists for the given inode number.
204*da21d850SDavid van Moolenbroek  */
205*da21d850SDavid van Moolenbroek static struct node_data *
get_data(ino_t ino_nr)206*da21d850SDavid van Moolenbroek get_data(ino_t ino_nr)
207*da21d850SDavid van Moolenbroek {
208*da21d850SDavid van Moolenbroek 	node_t index;
209*da21d850SDavid van Moolenbroek 
210*da21d850SDavid van Moolenbroek 	if (ino_nr == ROOT_INO_NR)
211*da21d850SDavid van Moolenbroek 		return &root_data;
212*da21d850SDavid van Moolenbroek 
213*da21d850SDavid van Moolenbroek 	if (ino_nr < BASE_INO_NR || ino_nr >= BASE_INO_NR + get_max_node())
214*da21d850SDavid van Moolenbroek 		return NULL;
215*da21d850SDavid van Moolenbroek 
216*da21d850SDavid van Moolenbroek 	index = (node_t)(ino_nr - BASE_INO_NR);
217*da21d850SDavid van Moolenbroek 
218*da21d850SDavid van Moolenbroek 	return get_node(index);
219*da21d850SDavid van Moolenbroek }
220*da21d850SDavid van Moolenbroek 
221*da21d850SDavid van Moolenbroek /*
222*da21d850SDavid van Moolenbroek  * Change file ownership.
223*da21d850SDavid van Moolenbroek  */
224*da21d850SDavid van Moolenbroek static int
ptyfs_chown(ino_t ino_nr,uid_t uid,gid_t gid,mode_t * mode)225*da21d850SDavid van Moolenbroek ptyfs_chown(ino_t ino_nr, uid_t uid, gid_t gid, mode_t * mode)
226*da21d850SDavid van Moolenbroek {
227*da21d850SDavid van Moolenbroek 	struct node_data *data;
228*da21d850SDavid van Moolenbroek 
229*da21d850SDavid van Moolenbroek 	if ((data = get_data(ino_nr)) == NULL)
230*da21d850SDavid van Moolenbroek 		return EINVAL;
231*da21d850SDavid van Moolenbroek 
232*da21d850SDavid van Moolenbroek 	data->uid = uid;
233*da21d850SDavid van Moolenbroek 	data->gid = gid;
234*da21d850SDavid van Moolenbroek 	data->mode &= ~(S_ISUID | S_ISGID);
235*da21d850SDavid van Moolenbroek 
236*da21d850SDavid van Moolenbroek 	*mode = data->mode;
237*da21d850SDavid van Moolenbroek 
238*da21d850SDavid van Moolenbroek 	return OK;
239*da21d850SDavid van Moolenbroek }
240*da21d850SDavid van Moolenbroek 
241*da21d850SDavid van Moolenbroek /*
242*da21d850SDavid van Moolenbroek  * Change file mode.
243*da21d850SDavid van Moolenbroek  */
244*da21d850SDavid van Moolenbroek static int
ptyfs_chmod(ino_t ino_nr,mode_t * mode)245*da21d850SDavid van Moolenbroek ptyfs_chmod(ino_t ino_nr, mode_t * mode)
246*da21d850SDavid van Moolenbroek {
247*da21d850SDavid van Moolenbroek 	struct node_data *data;
248*da21d850SDavid van Moolenbroek 
249*da21d850SDavid van Moolenbroek 	if ((data = get_data(ino_nr)) == NULL)
250*da21d850SDavid van Moolenbroek 		return EINVAL;
251*da21d850SDavid van Moolenbroek 
252*da21d850SDavid van Moolenbroek 	data->mode = (data->mode & ~ALLPERMS) | (*mode & ALLPERMS);
253*da21d850SDavid van Moolenbroek 
254*da21d850SDavid van Moolenbroek 	*mode = data->mode;
255*da21d850SDavid van Moolenbroek 
256*da21d850SDavid van Moolenbroek 	return OK;
257*da21d850SDavid van Moolenbroek }
258*da21d850SDavid van Moolenbroek 
259*da21d850SDavid van Moolenbroek /*
260*da21d850SDavid van Moolenbroek  * Return node details.
261*da21d850SDavid van Moolenbroek  */
262*da21d850SDavid van Moolenbroek static int
ptyfs_stat(ino_t ino_nr,struct stat * buf)263*da21d850SDavid van Moolenbroek ptyfs_stat(ino_t ino_nr, struct stat * buf)
264*da21d850SDavid van Moolenbroek {
265*da21d850SDavid van Moolenbroek 	struct node_data *data;
266*da21d850SDavid van Moolenbroek 
267*da21d850SDavid van Moolenbroek 	if ((data = get_data(ino_nr)) == NULL)
268*da21d850SDavid van Moolenbroek 		return EINVAL;
269*da21d850SDavid van Moolenbroek 
270*da21d850SDavid van Moolenbroek 	buf->st_mode = data->mode;
271*da21d850SDavid van Moolenbroek 	buf->st_uid = data->uid;
272*da21d850SDavid van Moolenbroek 	buf->st_gid = data->gid;
273*da21d850SDavid van Moolenbroek 	buf->st_nlink = S_ISDIR(data->mode) ? 2 : 1;
274*da21d850SDavid van Moolenbroek 	buf->st_rdev = data->dev;
275*da21d850SDavid van Moolenbroek 	buf->st_atime = data->ctime;
276*da21d850SDavid van Moolenbroek 	buf->st_mtime = data->ctime;
277*da21d850SDavid van Moolenbroek 	buf->st_ctime = data->ctime;
278*da21d850SDavid van Moolenbroek 
279*da21d850SDavid van Moolenbroek 	return OK;
280*da21d850SDavid van Moolenbroek }
281*da21d850SDavid van Moolenbroek 
282*da21d850SDavid van Moolenbroek /*
283*da21d850SDavid van Moolenbroek  * Return file system statistics.
284*da21d850SDavid van Moolenbroek  */
285*da21d850SDavid van Moolenbroek static int
ptyfs_statvfs(struct statvfs * buf)286*da21d850SDavid van Moolenbroek ptyfs_statvfs(struct statvfs * buf)
287*da21d850SDavid van Moolenbroek {
288*da21d850SDavid van Moolenbroek 
289*da21d850SDavid van Moolenbroek 	buf->f_flag = ST_NOTRUNC;
290*da21d850SDavid van Moolenbroek 	buf->f_namemax = NAME_MAX;
291*da21d850SDavid van Moolenbroek 
292*da21d850SDavid van Moolenbroek 	return OK;
293*da21d850SDavid van Moolenbroek }
294*da21d850SDavid van Moolenbroek 
295*da21d850SDavid van Moolenbroek /*
296*da21d850SDavid van Moolenbroek  * Process non-filesystem messages, in particular slave node creation and
297*da21d850SDavid van Moolenbroek  * deletion requests from the PTY service.
298*da21d850SDavid van Moolenbroek  */
299*da21d850SDavid van Moolenbroek static void
ptyfs_other(const message * m_ptr,int ipc_status)300*da21d850SDavid van Moolenbroek ptyfs_other(const message * m_ptr, int ipc_status)
301*da21d850SDavid van Moolenbroek {
302*da21d850SDavid van Moolenbroek 	char label[DS_MAX_KEYLEN];
303*da21d850SDavid van Moolenbroek 	struct node_data data;
304*da21d850SDavid van Moolenbroek 	message m_reply;
305*da21d850SDavid van Moolenbroek 	int r;
306*da21d850SDavid van Moolenbroek 
307*da21d850SDavid van Moolenbroek 	/*
308*da21d850SDavid van Moolenbroek 	 * We only accept requests from the service with the label "pty".
309*da21d850SDavid van Moolenbroek 	 * More sophisticated access checks are part of future work.
310*da21d850SDavid van Moolenbroek 	 */
311*da21d850SDavid van Moolenbroek 	if ((r = ds_retrieve_label_name(label, m_ptr->m_source)) != OK) {
312*da21d850SDavid van Moolenbroek 		printf("PTYFS: unable to obtain label for %u (%d)\n",
313*da21d850SDavid van Moolenbroek 		    m_ptr->m_source, r);
314*da21d850SDavid van Moolenbroek 		return;
315*da21d850SDavid van Moolenbroek 	}
316*da21d850SDavid van Moolenbroek 
317*da21d850SDavid van Moolenbroek 	if (strcmp(label, "pty")) {
318*da21d850SDavid van Moolenbroek 		printf("PTYFS: unexpected request %x from %s/%u\n",
319*da21d850SDavid van Moolenbroek 		    m_ptr->m_type, label, m_ptr->m_source);
320*da21d850SDavid van Moolenbroek 		return;
321*da21d850SDavid van Moolenbroek 	}
322*da21d850SDavid van Moolenbroek 
323*da21d850SDavid van Moolenbroek 	/* Process the request from PTY. */
324*da21d850SDavid van Moolenbroek 	memset(&m_reply, 0, sizeof(m_reply));
325*da21d850SDavid van Moolenbroek 
326*da21d850SDavid van Moolenbroek 	switch (m_ptr->m_type) {
327*da21d850SDavid van Moolenbroek 	case PTYFS_SET:
328*da21d850SDavid van Moolenbroek 		memset(&data, 0, sizeof(data));
329*da21d850SDavid van Moolenbroek 		data.dev = m_ptr->m_pty_ptyfs_req.dev;
330*da21d850SDavid van Moolenbroek 		data.mode = m_ptr->m_pty_ptyfs_req.mode;
331*da21d850SDavid van Moolenbroek 		data.uid = m_ptr->m_pty_ptyfs_req.uid;
332*da21d850SDavid van Moolenbroek 		data.gid = m_ptr->m_pty_ptyfs_req.gid;
333*da21d850SDavid van Moolenbroek 		data.ctime = clock_time(NULL);
334*da21d850SDavid van Moolenbroek 
335*da21d850SDavid van Moolenbroek 		r = set_node(m_ptr->m_pty_ptyfs_req.index, &data);
336*da21d850SDavid van Moolenbroek 
337*da21d850SDavid van Moolenbroek 		break;
338*da21d850SDavid van Moolenbroek 
339*da21d850SDavid van Moolenbroek 	case PTYFS_CLEAR:
340*da21d850SDavid van Moolenbroek 		clear_node(m_ptr->m_pty_ptyfs_req.index);
341*da21d850SDavid van Moolenbroek 		r = OK;
342*da21d850SDavid van Moolenbroek 
343*da21d850SDavid van Moolenbroek 		break;
344*da21d850SDavid van Moolenbroek 
345*da21d850SDavid van Moolenbroek 	case PTYFS_NAME:
346*da21d850SDavid van Moolenbroek 		r = make_name(m_reply.m_ptyfs_pty_name.name,
347*da21d850SDavid van Moolenbroek 		    sizeof(m_reply.m_ptyfs_pty_name.name),
348*da21d850SDavid van Moolenbroek 		    m_ptr->m_pty_ptyfs_req.index);
349*da21d850SDavid van Moolenbroek 
350*da21d850SDavid van Moolenbroek 		break;
351*da21d850SDavid van Moolenbroek 
352*da21d850SDavid van Moolenbroek 	default:
353*da21d850SDavid van Moolenbroek 		printf("PTYFS: invalid request %x from PTY\n", m_ptr->m_type);
354*da21d850SDavid van Moolenbroek 		r = ENOSYS;
355*da21d850SDavid van Moolenbroek 	}
356*da21d850SDavid van Moolenbroek 
357*da21d850SDavid van Moolenbroek 	/*
358*da21d850SDavid van Moolenbroek 	 * Send a reply to the request.  In particular slave node addition
359*da21d850SDavid van Moolenbroek 	 * requests must be blocking for the PTY service, so as to avoid race
360*da21d850SDavid van Moolenbroek 	 * conditions between PTYFS creating the slave node and userland trying
361*da21d850SDavid van Moolenbroek 	 * to open it.
362*da21d850SDavid van Moolenbroek 	 */
363*da21d850SDavid van Moolenbroek 	m_reply.m_type = r;
364*da21d850SDavid van Moolenbroek 
365*da21d850SDavid van Moolenbroek 	if (IPC_STATUS_CALL(ipc_status) == SENDREC)
366*da21d850SDavid van Moolenbroek 		r = ipc_sendnb(m_ptr->m_source, &m_reply);
367*da21d850SDavid van Moolenbroek 	else
368*da21d850SDavid van Moolenbroek 		r = asynsend3(m_ptr->m_source, &m_reply, AMF_NOREPLY);
369*da21d850SDavid van Moolenbroek 
370*da21d850SDavid van Moolenbroek 	if (r != OK)
371*da21d850SDavid van Moolenbroek 		printf("PTYFS: unable to reply to PTY (%d)\n", r);
372*da21d850SDavid van Moolenbroek }
373*da21d850SDavid van Moolenbroek 
374*da21d850SDavid van Moolenbroek /*
375*da21d850SDavid van Moolenbroek  * Initialize the service.
376*da21d850SDavid van Moolenbroek  */
377*da21d850SDavid van Moolenbroek static int
ptyfs_init(int __unused type,sef_init_info_t * __unused info)378*da21d850SDavid van Moolenbroek ptyfs_init(int __unused type, sef_init_info_t * __unused info)
379*da21d850SDavid van Moolenbroek {
380*da21d850SDavid van Moolenbroek 
381*da21d850SDavid van Moolenbroek 	init_nodes();
382*da21d850SDavid van Moolenbroek 
383*da21d850SDavid van Moolenbroek 	root_data.ctime = clock_time(NULL);
384*da21d850SDavid van Moolenbroek 
385*da21d850SDavid van Moolenbroek 	return OK;
386*da21d850SDavid van Moolenbroek }
387*da21d850SDavid van Moolenbroek 
388*da21d850SDavid van Moolenbroek /*
389*da21d850SDavid van Moolenbroek  * Process an incoming signal.
390*da21d850SDavid van Moolenbroek  */
391*da21d850SDavid van Moolenbroek static void
ptyfs_signal(int sig)392*da21d850SDavid van Moolenbroek ptyfs_signal(int sig)
393*da21d850SDavid van Moolenbroek {
394*da21d850SDavid van Moolenbroek 
395*da21d850SDavid van Moolenbroek 	if (sig == SIGTERM)
396*da21d850SDavid van Moolenbroek 		fsdriver_terminate();
397*da21d850SDavid van Moolenbroek }
398*da21d850SDavid van Moolenbroek 
399*da21d850SDavid van Moolenbroek /*
400*da21d850SDavid van Moolenbroek  * Perform SEF initialization.
401*da21d850SDavid van Moolenbroek  */
402*da21d850SDavid van Moolenbroek static void
ptyfs_startup(void)403*da21d850SDavid van Moolenbroek ptyfs_startup(void)
404*da21d850SDavid van Moolenbroek {
405*da21d850SDavid van Moolenbroek 
406*da21d850SDavid van Moolenbroek 	sef_setcb_init_fresh(ptyfs_init);
407*da21d850SDavid van Moolenbroek 	sef_setcb_signal_handler(ptyfs_signal);
408*da21d850SDavid van Moolenbroek 	sef_startup();
409*da21d850SDavid van Moolenbroek }
410*da21d850SDavid van Moolenbroek 
411*da21d850SDavid van Moolenbroek static struct fsdriver ptyfs_table = {
412*da21d850SDavid van Moolenbroek 	.fdr_mount	= ptyfs_mount,
413*da21d850SDavid van Moolenbroek 	.fdr_lookup	= ptyfs_lookup,
414*da21d850SDavid van Moolenbroek 	.fdr_getdents	= ptyfs_getdents,
415*da21d850SDavid van Moolenbroek 	.fdr_stat	= ptyfs_stat,
416*da21d850SDavid van Moolenbroek 	.fdr_chown	= ptyfs_chown,
417*da21d850SDavid van Moolenbroek 	.fdr_chmod	= ptyfs_chmod,
418*da21d850SDavid van Moolenbroek 	.fdr_statvfs	= ptyfs_statvfs,
419*da21d850SDavid van Moolenbroek 	.fdr_other	= ptyfs_other
420*da21d850SDavid van Moolenbroek };
421*da21d850SDavid van Moolenbroek 
422*da21d850SDavid van Moolenbroek /*
423*da21d850SDavid van Moolenbroek  * The PTYFS service.
424*da21d850SDavid van Moolenbroek  */
425*da21d850SDavid van Moolenbroek int
main(void)426*da21d850SDavid van Moolenbroek main(void)
427*da21d850SDavid van Moolenbroek {
428*da21d850SDavid van Moolenbroek 
429*da21d850SDavid van Moolenbroek 	ptyfs_startup();
430*da21d850SDavid van Moolenbroek 
431*da21d850SDavid van Moolenbroek 	fsdriver_task(&ptyfs_table);
432*da21d850SDavid van Moolenbroek 
433*da21d850SDavid van Moolenbroek 	return 0;
434*da21d850SDavid van Moolenbroek }
435