home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Magazine / wwwoffle-2.1.tar.gz / wwwoffle-2.1 / io.c < prev    next >
C/C++ Source or Header  |  1998-02-08  |  10KB  |  504 lines

  1. /***************************************
  2.   $Header: /home/amb/wwwoffle/RCS/io.c 2.5 1998/01/02 19:20:08 amb Exp $
  3.  
  4.   WWWOFFLE - World Wide Web Offline Explorer - Version 2.0b.
  5.   Functions for file input and output.
  6.   ******************/ /******************
  7.   Written by Andrew M. Bishop
  8.  
  9.   This file Copyright 1996,97 Andrew M. Bishop
  10.   It may be distributed under the GNU Public License, version 2, or
  11.   any higher version.  See section COPYING of the GNU Public license
  12.   for conditions under which this file may be redistributed.
  13.   ***************************************/
  14.  
  15.  
  16. /*+ Under Linux, FreeBSD, NetBSD, SGI, Ultrix, AIX and AT&T stdarg is used +*/
  17. #if defined(__linux__) || \
  18.     defined(__FreeBSD__) || defined(__NetBSD__) || \
  19.     defined(__sgi__) || defined(__ultrix__) || \
  20.     defined(_AIX) || defined(_ATT4)
  21. #define USE_STD_ARG
  22. #endif
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <ctype.h>
  28.  
  29. #ifdef USE_STD_ARG
  30. #include <stdarg.h>
  31. #else
  32. #include <varargs.h>
  33. #endif
  34.  
  35. #include <sys/time.h>
  36. #include <sys/types.h>
  37. #include <fcntl.h>
  38. #include <unistd.h>
  39. #include <errno.h>
  40.  
  41. #include "wwwoffle.h"
  42. #include "misc.h"
  43.  
  44.  
  45. #define BUFSIZE 64
  46.  
  47. /*+ The buffer of data from each of the files. +*/
  48. static char **fdbuf=NULL;
  49.  
  50. /*+ The number of bytes of data buffered for each file. +*/
  51. static int *fdbytes=NULL;
  52.  
  53. /*+ The number of file buffers allocated. +*/
  54. static int nfdbuf=0;
  55.  
  56.  
  57. static int read_into_buffer(int fd);
  58. static int read_into_buffer_with_timeout(int fd);
  59. static int read_from_buffer(int fd,char *buffer,int n);
  60.  
  61.  
  62. /*++++++++++++++++++++++++++++++++++++++
  63.   Call fgets and realloc the buffer as needed to get a whole line.
  64.  
  65.   char *fgets_realloc Returns the modified buffer (NULL at the end of the file).
  66.  
  67.   char *buffer The current buffer.
  68.  
  69.   FILE *file The file to read from.
  70.   ++++++++++++++++++++++++++++++++++++++*/
  71.  
  72. char *fgets_realloc(char *buffer,FILE *file)
  73. {
  74.  int n=0;
  75.  char *buf;
  76.  
  77.  if(!buffer)
  78.     buffer=(char*)malloc((BUFSIZE+1));
  79.  
  80.  while((buf=fgets(&buffer[n],BUFSIZE,file)))
  81.    {
  82.     int s=strlen(buf);
  83.     n+=s;
  84.  
  85.     if(buffer[n-1]=='\n')
  86.        break;
  87.     else
  88.        buffer=(char*)realloc(buffer,n+(BUFSIZE+1));
  89.    }
  90.  
  91.  if(!buf)
  92.    {free(buffer);buffer=NULL;}
  93.  
  94.  return(buffer);
  95. }
  96.  
  97.  
  98. /*++++++++++++++++++++++++++++++++++++++
  99.   Initialise the buffer used for this file descriptor.
  100.  
  101.   int fd The file descriptor to initialise.
  102.   ++++++++++++++++++++++++++++++++++++++*/
  103.  
  104. void init_buffer(int fd)
  105. {
  106.  if(fd==-1)
  107.     return;
  108.  
  109.  if(fd>=nfdbuf)
  110.    {
  111.     fdbuf=(char**)realloc((void*)fdbuf,(fd+1)*sizeof(char**));
  112.     fdbytes=(int*)realloc((void*)fdbytes,(fd+1)*sizeof(int));
  113.  
  114.     for(;nfdbuf<=fd;nfdbuf++)
  115.       {
  116.        fdbuf[nfdbuf]=NULL;
  117.        fdbytes[nfdbuf]=0;
  118.       }
  119.    }
  120.  
  121.  if(!fdbuf[fd])
  122.     fdbuf[fd]=(char*)malloc(BUFSIZE);
  123.  
  124.  fdbytes[fd]=0;
  125. }
  126.  
  127.  
  128. /*++++++++++++++++++++++++++++++++++++++
  129.   Read data from a file descriptor.
  130.  
  131.   int read_data Returns the number of bytes read or 0 for end of file.
  132.  
  133.   int fd The file descriptor.
  134.  
  135.   char *buffer The buffer to put the data into.
  136.  
  137.   int n The number of bytes read.
  138.   ++++++++++++++++++++++++++++++++++++++*/
  139.  
  140. int read_data(int fd,char *buffer,int n)
  141. {
  142.  int nr;
  143.  
  144.  if(fdbytes[fd])
  145.     nr=read_from_buffer(fd,buffer,n);
  146.  else
  147.     nr=read(fd,buffer,n);
  148.  
  149.  return(nr);
  150. }
  151.  
  152.  
  153. /*++++++++++++++++++++++++++++++++++++++
  154.   Read data from a file descriptor, with a timeout.
  155.  
  156.   int read_or_timeout Returns the number of bytes read or -1 for a timeout.
  157.  
  158.   int fd The file descriptor.
  159.  
  160.   char *buffer The buffer to put the data into.
  161.  
  162.   int n The number of bytes read.
  163.   ++++++++++++++++++++++++++++++++++++++*/
  164.  
  165. int read_data_or_timeout(int fd,char *buffer,int n)
  166. {
  167.  int nr;
  168.  
  169.  if(fdbytes[fd])
  170.     nr=read_from_buffer(fd,buffer,n);
  171.  else
  172.    {
  173.     fd_set readfd;
  174.     struct timeval tv;
  175.  
  176.     FD_ZERO(&readfd);
  177.  
  178.     FD_SET(fd,&readfd);
  179.  
  180.     tv.tv_sec=SOCKET_TIMEOUT;
  181.     tv.tv_usec=0;
  182.  
  183.     if(select(fd+1,&readfd,NULL,NULL,&tv)<=0)
  184.        return(-1);
  185.  
  186.     nr=read(fd,buffer,n);
  187.    }
  188.  
  189.  return(nr);
  190. }
  191.  
  192.  
  193. /*++++++++++++++++++++++++++++++++++++++
  194.   Read a single line of data from a file descriptor.
  195.  
  196.   char *read_line Returns the modified string or NULL for the end of file.
  197.  
  198.   int fd The file descriptor.
  199.  
  200.   char *line The previously allocated line of data.
  201.  
  202.   This is a replacement for the previous fgets_realloc() function with file descriptors instead of stdio.
  203.   ++++++++++++++++++++++++++++++++++++++*/
  204.  
  205. char *read_line(int fd,char *line)
  206. {
  207.  int found=0,eof=0;
  208.  int n=0;
  209.  
  210.  if(!line)
  211.     line=(char*)malloc((BUFSIZE+1));
  212.  
  213.  do
  214.    {
  215.     int i;
  216.  
  217.     if(!fdbytes[fd])
  218.        if(read_into_buffer(fd)<=0)
  219.          {eof=1;break;}
  220.  
  221.     for(i=0;i<fdbytes[fd];i++)
  222.        if(fdbuf[fd][i]=='\n')
  223.          {
  224.           found=1;
  225.           n+=read_from_buffer(fd,&line[n],i+1);
  226.           line[n]=0;
  227.           break;
  228.          }
  229.  
  230.     if(!found)
  231.       {
  232.        n+=read_from_buffer(fd,&line[n],BUFSIZE);
  233.        line=(char*)realloc((void*)line,n+(BUFSIZE+1));
  234.       }
  235.    }
  236.  while(!found && !eof);
  237.  
  238.  if(eof)
  239.    {free(line);line=NULL;}
  240.  
  241.  return(line);
  242. }
  243.  
  244.  
  245. /*++++++++++++++++++++++++++++++++++++++
  246.   Read a single line of data from a file descriptor with a timeout.
  247.  
  248.   char *read_line Returns the modified string or NULL for the end of file or timeout.
  249.  
  250.   int fd The file descriptor.
  251.  
  252.   char *line The previously allocated line of data.
  253.  
  254.   This is a replacement for the previous fgets_realloc() function with file descriptors instead of stdio.
  255.   ++++++++++++++++++++++++++++++++++++++*/
  256.  
  257. char *read_line_or_timeout(int fd,char *line)
  258. {
  259.  int found=0,eof=0;
  260.  int n=0;
  261.  
  262.  if(!line)
  263.     line=(char*)malloc((BUFSIZE+1));
  264.  
  265.  do
  266.    {
  267.     int i;
  268.  
  269.     if(!fdbytes[fd])
  270.        if(read_into_buffer_with_timeout(fd)<=0)
  271.          {eof=1;break;}
  272.  
  273.     for(i=0;i<fdbytes[fd];i++)
  274.        if(fdbuf[fd][i]=='\n')
  275.          {
  276.           found=1;
  277.           n+=read_from_buffer(fd,&line[n],i+1);
  278.           line[n]=0;
  279.           break;
  280.          }
  281.  
  282.     if(!found)
  283.       {
  284.        n+=read_from_buffer(fd,&line[n],BUFSIZE);
  285.        line=(char*)realloc((void*)line,n+(BUFSIZE+1));
  286.       }
  287.    }
  288.  while(!found && !eof);
  289.  
  290.  if(eof)
  291.    {free(line);line=NULL;}
  292.  
  293.  return(line);
  294. }
  295.  
  296.  
  297. /*++++++++++++++++++++++++++++++++++++++
  298.   Read some data from a file descriptor and buffer it.
  299.  
  300.   int read_and_buffer Returns the number of bytes read.
  301.  
  302.   int fd The file descriptor to read from.
  303.   ++++++++++++++++++++++++++++++++++++++*/
  304.  
  305. static int read_into_buffer(int fd)
  306. {
  307.  int n;
  308.  
  309.  n=read(fd,fdbuf[fd]+fdbytes[fd],BUFSIZE-fdbytes[fd]);
  310.  fdbytes[fd]+=n;
  311.  
  312.  return(n);
  313. }
  314.  
  315.  
  316. /*++++++++++++++++++++++++++++++++++++++
  317.   Read some data from a file descriptor and buffer it with a timeout.
  318.  
  319.   int read_and_buffer Returns the number of bytes read.
  320.  
  321.   int fd The file descriptor to read from.
  322.   ++++++++++++++++++++++++++++++++++++++*/
  323.  
  324. static int read_into_buffer_with_timeout(int fd)
  325. {
  326.  int n;
  327.  fd_set readfd;
  328.  struct timeval tv;
  329.  
  330.  FD_ZERO(&readfd);
  331.  
  332.  FD_SET(fd,&readfd);
  333.  
  334.  tv.tv_sec=SOCKET_TIMEOUT;
  335.  tv.tv_usec=0;
  336.  
  337.  if(select(fd+1,&readfd,NULL,NULL,&tv)<=0)
  338.     return(-1);
  339.  
  340.  n=read(fd,fdbuf[fd]+fdbytes[fd],BUFSIZE-fdbytes[fd]);
  341.  fdbytes[fd]+=n;
  342.  
  343.  return(n);
  344. }
  345.  
  346.  
  347. /*++++++++++++++++++++++++++++++++++++++
  348.   Read some data from the buffer.
  349.  
  350.   int read_from_buffer Returns the number of bytes read.
  351.  
  352.   int fd The file descriptor buffer to read from.
  353.  
  354.   char *buffer The buffer to copy the data into.
  355.  
  356.   int n The maximum number of bytes to read.
  357.   ++++++++++++++++++++++++++++++++++++++*/
  358.  
  359. static int read_from_buffer(int fd,char *buffer,int n)
  360. {
  361.  if(n>=fdbytes[fd])
  362.    {
  363.     memcpy(buffer,fdbuf[fd],fdbytes[fd]);
  364.     n=fdbytes[fd];
  365.     fdbytes[fd]=0;
  366.    }
  367.  else
  368.    {
  369.     memcpy(buffer,fdbuf[fd],n);
  370.     fdbytes[fd]-=n;
  371.     memmove(fdbuf[fd],fdbuf[fd]+n,fdbytes[fd]);
  372.    }
  373.  
  374.  return(n);
  375. }
  376.  
  377.  
  378. /*++++++++++++++++++++++++++++++++++++++
  379.   A function to write binary data to a file descriptor instead of write().
  380.  
  381.   int write_data Returns the number of bytes written.
  382.  
  383.   int fd The file descriptor.
  384.  
  385.   const char *data The data.
  386.  
  387.   int n The number of bytes of data.
  388.   ++++++++++++++++++++++++++++++++++++++*/
  389.  
  390. int write_data(int fd,const char *data,int n)
  391. {
  392.  n=write(fd,data,n);
  393.  
  394.  return(n);
  395. }
  396.  
  397.  
  398. /*++++++++++++++++++++++++++++++++++++++
  399.   A function to write a simple string to a file descriptor like fputs does to a FILE*.
  400.  
  401.   int write_string Returns the number of bytes written.
  402.  
  403.   int fd The file descriptor.
  404.  
  405.   const char *str The string.
  406.   ++++++++++++++++++++++++++++++++++++++*/
  407.  
  408. int write_string(int fd,const char *str)
  409. {
  410.  int n=strlen(str);
  411.  
  412.  n=write(fd,str,n);
  413.  
  414.  return(n);
  415. }
  416.  
  417.  
  418. /*++++++++++++++++++++++++++++++++++++++
  419.   A function to write a formatted string to a file descriptor like fprintf does to a FILE*.
  420.  
  421.   int write_formatted Returns the number of bytes written.
  422.  
  423.   int fd The file descriptor.
  424.  
  425.   const char *fmt The format string.
  426.  
  427.   ... The other arguments.
  428.   ++++++++++++++++++++++++++++++++++++++*/
  429.  
  430. int write_formatted(int fd,const char *fmt,...)
  431. {
  432.  int i,n,width;
  433.  char *str,*strp;
  434.  va_list ap;
  435.  
  436.  /* Estimate the length of the string. */
  437.  
  438. #ifdef USE_STD_ARG
  439.  va_start(ap,fmt);
  440. #else
  441.  va_start(ap);
  442. #endif
  443.  
  444.  n=strlen(fmt);
  445.  
  446.  for(i=0;fmt[i];i++)
  447.     if(fmt[i]=='%')
  448.       {
  449.        i++;
  450.  
  451.        if(fmt[i]=='%')
  452.           continue;
  453.  
  454.        width=atoi(fmt+i);
  455.        if(width<0)
  456.           width=-width;
  457.  
  458.        while(!isalpha(fmt[i]))
  459.           i++;
  460.  
  461.        switch(fmt[i])
  462.          {
  463.          case 's':
  464.           strp=va_arg(ap,char*);
  465.           if(width && width>strlen(strp))
  466.              n+=width;
  467.           else
  468.              n+=strlen(strp);
  469.           break;
  470.  
  471.          default:
  472.           (void)va_arg(ap,void*);
  473.           if(width && width>16)
  474.              n+=width;
  475.           else
  476.              n+=16;
  477.          }
  478.       }
  479.  
  480.  va_end(ap);
  481.  
  482.  /* Allocate the string and vsprintf into it. */
  483.  
  484.  str=(char*)malloc(n);
  485.  
  486. #ifdef USE_STD_ARG
  487.  va_start(ap,fmt);
  488. #else
  489.  va_start(ap);
  490. #endif
  491.  
  492.  n=vsprintf(str,fmt,ap);
  493.  
  494.  va_end(ap);
  495.  
  496.  /* Write the string. */
  497.  
  498.  n=write(fd,str,n);
  499.  
  500.  free(str);
  501.  
  502.  return(n);
  503. }
  504.