Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/pty/pty.c
Context not available. | |||||
&pty_warningcnt, 0, | &pty_warningcnt, 0, | ||||
"Warnings that will be triggered upon legacy PTY allocation"); | "Warnings that will be triggered upon legacy PTY allocation"); | ||||
#define MAX_PTY_DEVICES 25600 | |||||
static int npty; | |||||
SYSCTL_INT(_kern, OID_AUTO, npty, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &npty, 0, | |||||
ed: I don't entirely see why we'd need this sysctl variable. The point is, the devices are created… | |||||
"Maximum number of pty devices"); | |||||
static int | static int | ||||
ptydev_fdopen(struct cdev *dev, int fflags, struct thread *td, struct file *fp) | ptydev_fdopen(struct cdev *dev, int fflags, struct thread *td, struct file *fp) | ||||
{ | { | ||||
Context not available. | |||||
.d_name = "ptydev", | .d_name = "ptydev", | ||||
}; | }; | ||||
static void | |||||
pty_clone(void *arg, struct ucred *cr, char *name, int namelen, | |||||
struct cdev **dev) | |||||
{ | |||||
/* Cloning is already satisfied. */ | |||||
if (*dev != NULL) | |||||
return; | |||||
/* Only catch /dev/ptyXX. */ | |||||
if (namelen != 5 || bcmp(name, "pty", 3) != 0) | |||||
return; | |||||
/* Only catch /dev/pty[l-sL-S]X. */ | |||||
if (!(name[3] >= 'l' && name[3] <= 's') && | |||||
!(name[3] >= 'L' && name[3] <= 'S')) | |||||
return; | |||||
/* Only catch /dev/pty[l-sL-S][0-9a-v]. */ | |||||
if (!(name[4] >= '0' && name[4] <= '9') && | |||||
!(name[4] >= 'a' && name[4] <= 'v')) | |||||
return; | |||||
/* Create the controller device node. */ | |||||
*dev = make_dev_credf(MAKEDEV_REF, &ptydev_cdevsw, 0, | |||||
NULL, UID_ROOT, GID_WHEEL, 0666, "%s", name); | |||||
} | |||||
static int | static int | ||||
ptmx_fdopen(struct cdev *dev __unused, int fflags, struct thread *td, | ptmx_fdopen(struct cdev *dev __unused, int fflags, struct thread *td, | ||||
struct file *fp) | struct file *fp) | ||||
Context not available. | |||||
.d_name = "ptmx", | .d_name = "ptmx", | ||||
}; | }; | ||||
static void | |||||
create_pty_devs(void) | |||||
{ | |||||
int i; | |||||
char namedev[6] = "ptyl0"; | |||||
edUnsubmitted Not Done Inline ActionsSo the point is: we originally used the naming scheme pty[pqrs][0-9a-v] and only later on added support for pty[l-o][0-9a-v] when that became insufficient. Please make sure that if npty is low, the first device you hand out is ptyp0. Otherwise you will break compatibility. See: https://svnweb.freebsd.org/base/head/etc/etc.i386/ttys?r1=199250&r2=203068 ed: So the point is: we originally used the naming scheme pty[pqrs][0-9a-v] and only later on added… | |||||
npty = 32; | |||||
TUNABLE_INT_FETCH("kern.npty", &npty); | |||||
/* | |||||
* Assert that the number of devices requested is less | |||||
* than the number of devices we can actually create with | |||||
* the current naming scheme. In case the kernel is not | |||||
* built with INVARIANTS support, just cap the maximum | |||||
* number of devices. | |||||
*/ | |||||
KASSERT(npty <= MAX_PTY_DEVICES, ("Can't create enough devices")); | |||||
if (npty > MAX_PTY_DEVICES) | |||||
npty = MAX_PTY_DEVICES; | |||||
for (i = 0; i < npty; ++i) { | |||||
make_dev_credf(MAKEDEV_REF, &ptydev_cdevsw, 0, | |||||
NULL, UID_ROOT, GID_WHEEL, 0666, "%s", namedev); | |||||
/* | |||||
* Increment the last char in the device name, | |||||
edUnsubmitted Not Done Inline ActionsInstead of coming up with complicated logic to compute the next device name, it's actually easier to recompute it entirely. namedev[3] = "pqrsPQRS"[i / 32]; ed: Instead of coming up with complicated logic to compute the next device name, it's actually… | |||||
*/ | |||||
namedev[4] += 1; | |||||
if (namedev[4] == ('9' + 1)) | |||||
namedev[4] = 'a'; | |||||
/* | |||||
* We exhausted the range [0-9a-v], let's increment | |||||
* the last but one char. | |||||
*/ | |||||
else if (namedev[4] == ('v' + 1)) { | |||||
namedev[3] += 1; | |||||
namedev[4] = '0'; | |||||
if (namedev[3] == ('s' + 1)) | |||||
namedev[3] = 'S'; | |||||
} | |||||
} | |||||
} | |||||
static int | static int | ||||
pty_modevent(module_t mod, int type, void *data) | pty_modevent(module_t mod, int type, void *data) | ||||
{ | { | ||||
switch(type) { | switch(type) { | ||||
case MOD_LOAD: | case MOD_LOAD: | ||||
EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000); | |||||
make_dev_credf(MAKEDEV_ETERNAL_KLD, &ptmx_cdevsw, 0, NULL, | make_dev_credf(MAKEDEV_ETERNAL_KLD, &ptmx_cdevsw, 0, NULL, | ||||
UID_ROOT, GID_WHEEL, 0666, "ptmx"); | UID_ROOT, GID_WHEEL, 0666, "ptmx"); | ||||
create_pty_devs(); | |||||
break; | break; | ||||
case MOD_SHUTDOWN: | case MOD_SHUTDOWN: | ||||
break; | break; | ||||
Context not available. |
I don't entirely see why we'd need this sysctl variable. The point is, the devices are created when you load the module. After the module has loaded, we never use this one again, meaning that the user still has no way to influence this, right?
The upper limit is also far too high. The naming scheme doesn't really allow you to create more.