1 /*	$NetBSD: write_buf.c,v 1.1.1.1 2009/06/23 10:09:01 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	write_buf 3
6 /* SUMMARY
7 /*	write buffer or bust
8 /* SYNOPSIS
9 /*	#include <iostuff.h>
10 /*
11 /*	ssize_t	write_buf(fd, buf, len, timeout)
12 /*	int	fd;
13 /*	const char *buf;
14 /*	ssize_t	len;
15 /*	int	timeout;
16 /* DESCRIPTION
17 /*	write_buf() writes a buffer to the named stream in as many
18 /*	fragments as needed, and returns the number of bytes written,
19 /*	which is always the number requested or an error indication.
20 /*
21 /*	Arguments:
22 /* .IP fd
23 /*	File descriptor in the range 0..FD_SETSIZE.
24 /* .IP buf
25 /*	Address of data to be written.
26 /* .IP len
27 /*	Amount of data to be written.
28 /* .IP timeout
29 /*	Bounds the time in seconds to wait until \fIfd\fD becomes writable.
30 /*	A value <= 0 means do not wait; this is useful only when \fIfd\fR
31 /*	uses blocking I/O.
32 /* DIAGNOSTICS
33 /*	write_buf() returns -1 in case of trouble. The global \fIerrno\fR
34 /*	variable reflects the nature of the problem.
35 /* LICENSE
36 /* .ad
37 /* .fi
38 /*	The Secure Mailer license must be distributed with this software.
39 /* AUTHOR(S)
40 /*	Wietse Venema
41 /*	IBM T.J. Watson Research
42 /*	P.O. Box 704
43 /*	Yorktown Heights, NY 10598, USA
44 /*--*/
45 
46 /* System library. */
47 
48 #include <sys_defs.h>
49 #include <unistd.h>
50 #include <errno.h>
51 #include <time.h>
52 
53 /* Utility library. */
54 
55 #include <msg.h>
56 #include <iostuff.h>
57 
58 /* write_buf - write buffer or bust */
59 
60 ssize_t write_buf(int fd, const char *buf, ssize_t len, int timeout)
61 {
62     const char *start = buf;
63     ssize_t count;
64     time_t  expire;
65     int     time_left = timeout;
66 
67     if (time_left > 0)
68 	expire = time((time_t *) 0) + time_left;
69 
70     while (len > 0) {
71 	if (time_left > 0 && write_wait(fd, time_left) < 0)
72 	    return (-1);
73 	if ((count = write(fd, buf, len)) < 0) {
74 	    if ((errno == EAGAIN && time_left > 0) || errno == EINTR)
75 		 /* void */ ;
76 	    else
77 		return (-1);
78 	} else {
79 	    buf += count;
80 	    len -= count;
81 	}
82 	if (len > 0 && time_left > 0) {
83 	    time_left = expire - time((time_t *) 0);
84 	    if (time_left <= 0) {
85 		errno = ETIMEDOUT;
86 		return (-1);
87 	    }
88 	}
89     }
90     return (buf - start);
91 }
92