Ejemplo n.º 1
0
/* If bidir, also copy data from printer (lp) to network (fd). */
int copy_stream(int fd, int lp)
{
	int result;
	Buffer_t networkToPrinterBuffer;
	initBuffer(&networkToPrinterBuffer, fd, lp, 1);

	if (bidir) {
		struct timeval now;
		struct timeval then;
		struct timeval timeout;
		struct timeval lastnetactivity;
		int timer = 0;
		Buffer_t printerToNetworkBuffer;
		initBuffer(&printerToNetworkBuffer, lp, fd, 0);
		fd_set readfds;
		fd_set writefds;

		if (timeoutparam > 0)
			gettimeofday(&lastnetactivity, 0);
		/* Finish when network sent EOF. */
		/* Although the printer to network stream may not be finished (does this matter?) */
		while (!networkToPrinterBuffer.eof_sent && !networkToPrinterBuffer.err) {
			FD_ZERO(&readfds);
			FD_ZERO(&writefds);
			prepBuffer(&networkToPrinterBuffer, &readfds, &writefds);
			prepBuffer(&printerToNetworkBuffer, &readfds, &writefds);

			int maxfd = lp > fd ? lp : fd;
			if (timer) {
				/* Delay after reading from the printer, so the */
				/* return stream cannot dominate. */
				/* Don't read from the printer until the timer expires. */
				gettimeofday(&now, 0);
				if ((now.tv_sec > then.tv_sec) || (now.tv_sec == then.tv_sec && now.tv_usec > then.tv_usec))
					timer = 0;
				else
					FD_CLR(lp, &readfds);
			}
			timeout.tv_sec = 0;
			timeout.tv_usec = 100000;
			result = select(maxfd + 1, &readfds, &writefds, 0, &timeout);
			if (result < 0)
				return (result);
			if (FD_ISSET(fd, &readfds)) {
				/* Read network data. */
				result = readBuffer(&networkToPrinterBuffer);
				if (result > 0)
					dolog(LOG_DEBUG,"read %d bytes from network\n",result);
				if (timeoutparam > 0)
					gettimeofday(&lastnetactivity, 0);
			}
			if (FD_ISSET(lp, &readfds)) {
				/* Read printer data, but pace it more slowly. */
				result = readBuffer(&printerToNetworkBuffer);
				if (result > 0) {
					dolog(LOG_DEBUG,"read %d bytes from printer\n",result);
					gettimeofday(&then, 0);
					// wait 100 msec before reading again.
					then.tv_usec += 100000;
					if (then.tv_usec > 1000000) {
						then.tv_usec -= 1000000;
						then.tv_sec++;
					}
					timer = 1;
				}
			}
			if (FD_ISSET(lp, &writefds)) {
				/* Write data to printer. */
				result = writeBuffer(&networkToPrinterBuffer);
				if (result > 0)
					dolog(LOG_DEBUG,"wrote %d bytes to printer\n",result);
			}
			if (FD_ISSET(fd, &writefds) || printerToNetworkBuffer.outfd == -1) {
				/* Write data to network. */
				result = writeBuffer(&printerToNetworkBuffer);
				/* If socket write error, discard further data from printer */
				if (result < 0) {
					printerToNetworkBuffer.outfd = -1;
					printerToNetworkBuffer.err = 0;
					result = 0;
					dolog(LOG_DEBUG,"network write error, discarding further printer data\n",result);
					if (timeoutparam > 0)
						gettimeofday(&lastnetactivity, 0);
				}
				else if (result > 0) {
					if (printerToNetworkBuffer.outfd == -1)
						dolog(LOG_DEBUG,"discarded %d bytes from printer\n",result);				
					else
						dolog(LOG_DEBUG,"wrote %d bytes to network\n",result);
				}
			}
			if (timeoutparam > 0) {
				gettimeofday(&now, 0);
				if ((now.tv_sec - lastnetactivity.tv_sec) >= timeoutparam) {
					networkToPrinterBuffer.eof_sent = 1;
					printerToNetworkBuffer.err = 1;
				}
			}
		}
		dolog(LOG_NOTICE,
		       "Finished job: %d/%d bytes sent to printer, %d/%d bytes sent to network\n",
		       networkToPrinterBuffer.totalout,networkToPrinterBuffer.totalin, printerToNetworkBuffer.totalout, printerToNetworkBuffer.totalin);
	} else {
		/* Unidirectional: simply read from network, and write to printer. */
		while (!networkToPrinterBuffer.eof_sent && !networkToPrinterBuffer.err) {
			result = readBuffer(&networkToPrinterBuffer);
			if (result > 0)
				dolog(LOG_DEBUG,"read %d bytes from network\n",result);
			result = writeBuffer(&networkToPrinterBuffer);
			if (result > 0)
				dolog(LOG_DEBUG,"wrote %d bytes to printer\n",result);
		}
		dolog(LOG_NOTICE, "Finished job: %d/%d bytes sent to printer\n", networkToPrinterBuffer.totalout, networkToPrinterBuffer.totalin);
	}
	return (networkToPrinterBuffer.err?-1:0);
}
Ejemplo n.º 2
0
/* If bidir, also copy data from printer (lp) to network (fd). */
int copy_stream(int fd, int lp)
{
	int result;
	Buffer_t networkToPrinterBuffer;
	initBuffer(&networkToPrinterBuffer, fd, lp, 1);

	if (bidir) {
		struct timeval now;
		struct timeval then;
		struct timeval timeout;
		int timer = 0;
		Buffer_t printerToNetworkBuffer;
		initBuffer(&printerToNetworkBuffer, lp, fd, 0);
		fd_set readfds;
		fd_set writefds;
		/* Initially read from both streams, don't write to either. */
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);
		FD_SET(lp, &readfds);
		FD_SET(fd, &readfds);
		/* Finish when no longer reading fd, and no longer writing to lp. */
		/* Although the printer to network stream may not be finished, that does not matter. */
		while ((FD_ISSET(fd, &readfds)) || (FD_ISSET(lp, &writefds))) {
			int maxfd = lp > fd ? lp : fd;
			if (timer) {
				/* Delay after reading from the printer, so the */
				/* return stream cannot dominate. */
				/* Don't read from the printer until the timer expires. */
				gettimeofday(&now, 0);
				if ((now.tv_sec > then.tv_sec) || (now.tv_sec == then.tv_sec && now.tv_usec > then.tv_usec)) {
					timer = 0;
				} else {
					timeout.tv_sec = then.tv_sec - now.tv_sec;
					timeout.tv_usec = then.tv_usec - now.tv_usec;
					if (timeout.tv_usec < 0) {
						timeout.tv_usec += 1000000;
						timeout.tv_sec--;
					}
					FD_CLR(lp, &readfds);
				}
			}
			if (timer) {
				result = select(maxfd + 1, &readfds, &writefds, 0, &timeout);
			} else {
				result = select(maxfd + 1, &readfds, &writefds, 0, 0);
			}
			if (result < 0)
				return (result);
			if (FD_ISSET(fd, &readfds)) {
				/* Read network data. */
				result = readBuffer(&networkToPrinterBuffer);
			}
			if (FD_ISSET(lp, &readfds)) {
				/* Read printer data, but pace it more slowly. */
				result = readBuffer(&printerToNetworkBuffer);
				if (result >= 0) {
					gettimeofday(&then, 0);
					// wait 100 msec before reading again.
					then.tv_usec += 100000;
					if (then.tv_usec > 1000000) {
						then.tv_usec -= 1000000;
						then.tv_sec++;
					}
					timer = 1;
				}
			}
			if (FD_ISSET(lp, &writefds)) {
				/* Write data to printer. */
				result = writeBuffer(&networkToPrinterBuffer);
			}
			if (FD_ISSET(fd, &writefds)) {
				/* Write data to network. */
				result = writeBuffer(&printerToNetworkBuffer);
				/* If socket write error, stop reading from printer */
				if (result < 0)
					networkToPrinterBuffer.eof = 1;
			}
			/* Prepare for next iteration. */
			FD_ZERO(&readfds);
			FD_ZERO(&writefds);
			prepBuffer(&networkToPrinterBuffer, &readfds, &writefds);
			prepBuffer(&printerToNetworkBuffer, &readfds, &writefds);
		}
		syslog(LOG_NOTICE,
		       "Finished job: %d bytes received, %d bytes sent\n",
		       networkToPrinterBuffer.totalout, printerToNetworkBuffer.totalout);
		return (0);
	} else {
		/* Unidirectional: simply read from network, and write to printer. */
		while ((result = readBuffer(&networkToPrinterBuffer)) > 0) {
			(void)writeBuffer(&networkToPrinterBuffer);
		}
		syslog(LOG_NOTICE, "Finished job: %d bytes received\n", networkToPrinterBuffer.totalout);
		return (result);
	}
}