io.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #include <sys/time.h>
  2. #include <stdarg.h>
  3. #include <stdio.h>
  4. #include <malloc.h>
  5. #include "../common/log.h"
  6. #include "../common/utils.h"
  7. #include "smtpap.h"
  8. #include "io.h"
  9. /* connection timeout */
  10. extern struct timeval *conn_toutp;
  11. /* printf-like function used to send messages to a socket */
  12. int sendmessage(int s, char *buf, size_t buflen, const char *format, ...)
  13. {
  14. int retval = 0;
  15. va_list ap;
  16. if (!buf)
  17. return -1;
  18. va_start(ap,format);
  19. retval = vsnprintf(buf,buflen, format, ap);
  20. va_end(ap);
  21. if (retval < 0)
  22. {
  23. log(LOG_DEBUG,"sendmessage() : could not print to buffer");
  24. return -1;
  25. }
  26. log(LOG_DEBUG,"sendmessage() : printed this to buffer : %s",buf);
  27. retval = write_tout(s,buf,(size_t)retval, conn_toutp);
  28. if (retval < 0)
  29. {
  30. log(LOG_DEBUG,"sendmessage() : could not send");
  31. return -1;
  32. }
  33. return retval;
  34. }
  35. /* receive a response from the recipient SMTP server into *op_in
  36. * Can handle multi-line responses. */
  37. int receive(int s, char **inbuf,size_t *inbuflen, int flags)
  38. {
  39. int inputlen = 0; /* running total length of the input */
  40. int inputerror = 0; /* has an error occured? */
  41. int retval = 0; /* used for saving function return values */
  42. /* for processing multi-line responses */
  43. int i=0;
  44. /* storing old values of *inbuf and *inbuflen */
  45. char *inbuf_old = NULL;
  46. size_t inbuflen_old=0;
  47. if ((!inbuf) || (!*inbuf) || (!inbuflen))
  48. return -1;
  49. /* saving old values in case we need to restore them */
  50. inbuf_old = *inbuf;
  51. inbuflen_old = *inbuflen;
  52. do
  53. {
  54. if (inputlen == *inbuflen-1) /* we need to increase the buffer size */
  55. {
  56. /* increase the size of the buffer */
  57. *inbuflen += 512;
  58. *inbuf = (char *)realloc(*inbuf,(size_t)*inbuflen);
  59. if (!*inbuf)
  60. {
  61. log(LOG_ERR,"Could not allocate memory.");
  62. *inbuf = inbuf_old;
  63. *inbuflen = inbuflen_old;
  64. inputerror = 1;
  65. break;
  66. }
  67. }
  68. retval=read_tout(s,*inbuf+inputlen,(size_t)(*inbuflen-inputlen-1),flags, conn_toutp); /* subtract 1 from inbuflen to leave space for \0 */
  69. if (retval <= 0)
  70. {
  71. log(LOG_ERR,"Error occured while receiving data.");
  72. inputerror = 1;
  73. break;
  74. }
  75. else
  76. {
  77. inputerror = 0;
  78. inputlen += retval;
  79. /* exit clause if we have received CRLF, otherwise we need to keep reading*/
  80. /* also keep on reading if it's a multi-line response */
  81. if (inputlen >= SMTPAP_CRLF_LEN)
  82. {
  83. if (!strncmp(*inbuf+inputlen-SMTPAP_CRLF_LEN,SMTPAP_CRLF,SMTPAP_CRLF_LEN)) /* entire line received */
  84. {
  85. /* now check wether we should expect more lines */
  86. /* find the <CRLF> sequence which occurs one before last */
  87. for(i=inputlen-SMTPAP_CRLF_LEN-1; i > 0; i--) /* move backwards, start just before the final CRLF */
  88. {
  89. if ((*inbuf)[i] == SMTPAP_LF) /* got a LF */
  90. {
  91. /* check for a CR preceding it */
  92. if ((*inbuf)[i-1] == SMTPAP_CR) /* got a CR */
  93. break;
  94. }
  95. }
  96. if (i==0) /* correct the offset if no CRLF found */
  97. i=-1;
  98. /* check the 4th character after the <CRLF> to see if it is - or <SP> */
  99. if ((*inbuf)[i+4] != '-') /* no more lines */
  100. break;
  101. }
  102. }
  103. }
  104. } while(1);
  105. if (!inputerror)
  106. {
  107. (*inbuf)[inputlen]=0; /* add the terminating NULL character */
  108. return inputlen;
  109. }
  110. return -1;
  111. }