Saturday, November 8, 2014

Unix Prog: streams mechanism(2)

1. isastream
isastream system call is used to determine if a descriptor refers to a stream or not.

System Definition:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/stropts.h  
 ......  
 /* Test whether FILDES is associated with a STREAM-based file. */  
 extern int isastream (int __fildes) __THROW;  
 ......  

Example:
stream.c
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<fcntl.h>  
 #include<stropts.h>  
   
 int main(int argc, char* argv[])  
 {  
  int i, fd;  
  for(i = 1; i < argc; i++) {  
   if((fd = open(argv[i], O_RDONLY)) < 0) {  
    printf("%s: can't open\n", argv[i]);  
    continue;  
   }  
   
   if(isastream(fd) == 0) {  
    printf("%s: not a stream\n", argv[i]);  
   }  
   else {  
    printf("%s: streams device\n", argv[i]);  
   }  
  }  
   
  exit(0);  
 }  

shell:
 ubuntu@ip-172-31-23-227:~$ ./stream.out /dev/tty /dev/fb /dev/null /etc/mtab  
 /dev/tty: not a stream  
 /dev/fb: can't open  
 /dev/null: not a stream  
 /etc/mtab: not a stream  

2. isastream implementation
isastream merely use ioctl that is valid only on STREAM device. I_CANPUT ioctl command checks if the band specified by the third argument is writable.

 ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/bits/stropts.h  
 ......  
 /* Macros used as `request' argument to `ioctl'. */  
 #define __SID      ('S' << 8)  
   
 #define I_NREAD   (__SID | 1) /* Counts the number of data bytes in the data  
                   block in the first message. */  
 #define I_PUSH   (__SID | 2) /* Push STREAMS module onto top of the current  
                   STREAM, just below the STREAM head. */  
 #define I_POP    (__SID | 3) /* Remove STREAMS module from just below the  
                   STREAM head. */  
 ......  
 #define I_CANPUT  (__SID |34) /* Check if a certain band is writable. */  
 ......  

Example:
stream.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<fcntl.h>  
 #include<stropts.h>  
   
 int isastream(int fd)  
 {  
  printf("own isastream test: ");  
  return(ioctl(fd, I_CANPUT, 0) != -1);  
 }  
   
 int main(int argc, char* argv[])  
 {  
  int i, fd;  
  for(i = 1; i < argc; i++) {  
   if((fd = open(argv[i], O_RDONLY)) < 0) {  
    printf("%s: can't open\n", argv[i]);  
    continue;  
   }  
   
   if(isastream(fd) == 0) {  
    printf("%s: not a stream\n", argv[i]);  
   }  
   else {  
    printf("%s: streams device\n", argv[i]);  
   }  
  }  
   
  exit(0);  
 }  

shell:
 ubuntu@ip-172-31-23-227:~$ ./stream.out /dev/tty /dev/fb /dev/null /etc/mtab  
 own isastream test: /dev/tty: not a stream  
 /dev/fb: can't open  
 own isastream test: /dev/null: not a stream  
 own isastream test: /etc/mtab: not a stream  

3. Return the modules on the stream
module.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<fcntl.h>  
 #include<stropts.h>  
   
 int main(int argc, char *argv[])  
 {  
  int fd, i, nmods;  
  struct str_list list;  
   
  // Open the file descriptor  
  if((fd = open(argv[1], O_RDONLY)) < 0) {  
   printf("can't open %s", argv[1]);  
   exit(1);  
  }  
   
  if(isastream(fd) == 0) {  
   printf("%s is not a stream", argv[1]);  
   exit(2);  
  }  
   
  // Return the number of modules in the stream  
  // With second argument as : I_LIST, third argument 0  
  if((nmods = ioctl(fd, I_LIST, (void*) 0)) < 0) {  
   printf("I_LIST error for nmods");  
   exit(3);  
  }  
  printf("#modules = %d\n", nmods);  
   
  // Allocate struct str_mlist  
  list.sl_modlist = calloc(nmods, sizeof(struct str_mlist));  
  if(list.sl_modlist == NULL) {  
   printf("calloc error!\n");  
   exit(4);  
  }  
  list.sl_nmods = nmods;  
   
  if(ioctl(fd, I_LIST, &list) < 0) {  
   printf("I_LIST error for list");  
   exit(4);  
  }  
   
  // Print out all modules  
  for(i = 1; i <=nmods; i++)  
   printf(" %s: %s\n", (i == nmods) ? "driver" : "module", list.sl_modlist++->l_name);  
   
  exit(0);  
 }  

Definition:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/bits/stropts.h  
 ......  
 struct str_mlist  
  {  
   char l_name[FMNAMESZ + 1];  
  };  
   
 struct str_list  
  {  
   int sl_nmods;  
   struct str_mlist *sl_modlist;  
  };  
 ......  

No comments:

Post a Comment