#include <stdio.h>
#include <UNIX/os9def.h>
#include <errno.h>
#include <sg_codes.h>
#include <string.h>
#define _OPT_PROTOS
#include <modes.h>
#include <SPF/spf.h>

int writev(fd, v, n)
int fd;
struct iovec *v;
int n;
{
	int l, i, rv, nbytes = 0;
	char *buffer;

	char str[80];

	struct spf_popts sopts;
	u_int32 soptsz = sizeof(sopts);
	error_code rc;
	u_int8 ioasync;

	rc = _os_gs_popt(fd, &soptsz, &sopts);
	if (rc)
		return rc;
	ioasync = sopts.pd_ioasync;
	if (sopts.pd_ioasync == IO_SYNC)
	{
		sopts.pd_ioasync = IO_ASYNC;
		rc = _os_ss_popt(fd, soptsz, &sopts);
		if (rc)
			return rc;
	}


	if (n <= 0) {
		errno = EINVAL;
		return -1;
	}

	/* If we have only one part, write it directly */
	if (n == 1 && v[0].iov_len > 0)
	{
		nbytes = rv = v[0].iov_len;
		rc = _os_write(fd, v[0].iov_base, &rv);

		if (rv != v[0].iov_len)
		{
			l = sprintf(str, "writev1: sollte %d hat %d\n",v[0].iov_len, rv);
			writeln(1, str, l);
		}
		if (rc)
		{
			l = sprintf(str, "writev1: error %d\n",rc);
			writeln(1, str, l);
		}
	} else {
		/* Check parameters and find the total number of bytes to be written. */
		for (i = 0; i < n; i++) {
			if (v[i].iov_base == NULL	/* no base pointer */
			|| (rv = v[i].iov_len) < 0	/* negative size */
			|| (nbytes += rv) < 0) {	/* integer overflow */
				errno = EINVAL;
				return -1;
			}
		}

		if (nbytes) {
			if (nbytes > 2048)
			{
				/*
				 * Allocate a temporary buffer to hold the data.
				 * Don't use alloca because threads tend to have smaller stacks.
				 */
				if ((buffer = (char *)malloc(nbytes)) == NULL) {
					return -1;
				}
				/* Copy the data from memory specified by VECTOR to BUFFER */
				for (rv = 0, i = 0; i < n; i++) {
		       		memcpy(buffer + rv, v[i].iov_base, v[i].iov_len);
					rv += v[i].iov_len;
		    	}
				rv = nbytes;
				rc = _os_write(fd, buffer, &rv);
				free(buffer);
			} else {
				char stack_buffer[2048];
				/* Copy the data from memory specified by VECTOR to BUFFER */
				for (rv = 0, i = 0; i < n; i++) {
		       		memcpy(stack_buffer + rv, v[i].iov_base, v[i].iov_len);
					rv += v[i].iov_len;
		    	}
				rv = nbytes;
				rc = _os_write(fd, stack_buffer, &rv);
			}

			if (rv != nbytes)
			{
				l = sprintf(str, "writev2: sollte %d hat %d\n",nbytes, rv);
				writeln(1, str, l);
			}
			if (rc)
			{
				l = sprintf(str, "writev2: error %d\n",rc);
				writeln(1, str, l);
			}
		}
	}

	if (ioasync != sopts.pd_ioasync)
	{
		sopts.pd_ioasync = ioasync;
		_os_ss_popt(fd, soptsz, &sopts);
	}
	l = sprintf(str, "writev: (%d,...,%d)(%d)\n",fd, n, nbytes);
	writeln(1, str, l);
	return rv;
}

