Friday May 27, 2005 Playing with STREAMS module from the User-Land
In my previous STREAMS blog entry, we discussed, how to construct a do-nothing STREAMS module. Now we will come back to the user-land and see how we can play with STREAMS modules. We will learn, how to
Suppose that you have an open file descriptor fd and would like to know what STREAMS modules and drivers live behind the scene in the kernel in the STREAM representing the file.
The article by Rajesh Ramchandani on the Sun Developer Network provides an excellent example with the full source code of the printmod() function. It uses the I_LIST> ioctl which returns a list of modules in the struct str_mlist structure.
The next thing we are going to try is pushing our new module onto the STREAM. The following simple function should do the trick:
int pushmod(int fd, char *modname)
{
int rc;
if ((rc = ioctl(fd, I_PUSH, modname)) < 0) {
perror("I_PUSH");
fprintf(stderr, "pushmod(%d, %s) failed\n", fd, modname);
}
return rc;
}
The function takes a file descriptor and the module name and pushes the module on top of the stream. It returns 0 on success and -1 on failure. We can extend it a bit to put a whole list of modules. Suppose that the module list is a string with commas separating module names:
/* Push list of modules separated by commas */
int pushlist(int fd, char *s)
{
char *comma = strchr(s, ',');
int rc = 0;
if (comma == NULL)
return (pushmod(fd, s));
*comma = '\0';
if (((rc = pushmod(fd, s)) >= 0) && *(comma+1) != '\0') {
*comma = ',';
rc = pushlist(fd, comma + 1);
}
return (rc);
}
The following example demonstrates how it can be used in practice:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stropts.h>
#include <strings.h>
void main(int argc, char *argv[])
{
if (argc == 1)
return;
if (pushlist(0, argv[1]) < 0)
exit(1);
exit(0);
}
We can name this program as pushmod.c and try it (assuming that you have installed the nullmodmodule from the previous example:
$ cc pushmod.c -o pushmod
$ strconf
ttcompat
ldterm
ptem
pts
$ ./pushmod nullmod,nullmod,nullmod
nullmod
nullmod
nullmod
ttcompat
ldterm
ptem
pts
Finally, you may remove the module from the top of the stream using a simple call
if ((rc = ioctl(fd1, I_POP, 0)) < 0) {
perror("I_POP");
Now you know how to manipulate the content of the STREAM. You may want to play with it a bit and see what happens if you insert and remove some interesting modules.
NOTE: It is quite likely that your terminal window will become unusable as a result of your experiments. Many modules assume certain context and the are designed to play in concert with others, so your terminal may misbehave if it is incorrectly configured.