The I_LIST ioctl(2) supports the strconf(1) and strchg(1) commands that are used to query or change the configuration of a stream. Only root or an owner of a STREAMS device can alter the configuration of that stream.
strchg(1) does the following:
Pushes one or more modules on the stream
Pops the topmost module off the stream
Pops all the modules off the stream
Pops all modules up to but not including a specified module
strconf(1) does the following:
Checks if the specified module is present on the stream.
Prints the topmost module of the stream.
Prints a list of all modules and the topmost driver on the stream. If the stream contains a multiplexing driver, the strchg and strconf commands will not recognize any modules below that driver.
The I_LIST ioctl(2) (illustrated in Example 4-1) performs two functions. When the third argument of the ioctl(2) call is NULL
if ((mods = ioctl(s, I_LIST, 0)) < 0) { |
struct str_mlist { char l_name[FMNAMESZ+1]; /*space for holding a module name*/ }; struct str_list { int sl_nmods; /*#of modules for which space is allocated*/ struct str_mlist *sl_modlist; /*addr of buf for names*/ }; |
Here sl_nmods is the number of modules in the sl_modlist array that the user has allocated. Each element in the array must be at least FMNAMESZ+1 bytes long. The array is FMNAMESZ+1 so the extra byte can hold the NULL character at the end of the string. FMNAMESZ is defined by <sys/conf.h>.
The amount of space to allocate for module names is indicated by the number of modules in the STREAM. This is not completely reliable because another module might be pushed onto the stream after the application invokes the I_LIST ioctl(2) with the NULL argument and before it invokes the I_LIST ioctl(2) with the structure argument.
The I_LIST call with arg pointing to the str_list structure returns the number of entries that have been filled into the sl_modlist array (the number represents the number of modules including the driver). If there is not enough space in the sl_modlist array (see note) or sl_nmods is less than 1, the I_LIST call fails and errno is set to EINVAL. If arg or the sl_modlist array points outside the allocated address space, EFAULT is returned.
#include <stdio.h> #include <string.h> #include <stropts.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/socket.h> main(int argc, const char **argv) { int s, i; unsigned int mods; struct str_list mod_list;struct str_mlist *mlist; /* Get a socket... */ if ((s = socket(AF_INET, SOCK_STREAM, 0)) <= 0) { perror("socket: "); exit(1); } /* Determine the number of modules in the stream */ if ((mods = ioctl(s, I_LIST, 0)) < 0) { perror("I_LIST ioctl"); } if (mods == 0) { printf("No modules\n"); exit(1); } else { printf("%d modules\n", mods); } /* Allocate memory for all of the module names */ mlist = (struct str_mlist *) calloc(mods, sizeof (struct str_mlist)); if (mlist == 0) { perror("malloc failure"); exit(1); } mod_list.sl_modlist = mlist; mod_list.sl_nmods = mods; /* Do the ioctl and get the module names... */ if (ioctl(s, I_LIST, &mod_list) < 0) { exit(1); } /* Print out the name of the modules... */ for (i = 0; i < mods; i++) { printf("s: %s\n", mod_list.sl_modlist[i].l_name); } /* Free the calloc'd structures... */ free(mlist); return(0); }