STREAMS Programming Guide

I_LIST ioctl(2)

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:

strconf(1) does the following:

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) {
, the return value of the call indicates the number of modules, plus the driver, present on the Stream. For example, if there are two modules above the driver, 3 is returned. On failure, errno may be set to a value specified in streamio(7I). The second function of the I_LIST ioctl(2) is to copy the module names found on the Stream to the user-supplied buffer. The address of the buffer in user space and the size of the buffer are passed to the ioctl(2) through a structure str_list that is defined as:


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.


Example 4-1 I_LIST ioctl(2)

#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);
}