/*
* Copyright ©2026 Naomi Alterman. All rights reserved. Permission is
* hereby granted to students registered for University of Washington
* CSE 333 for use solely during Spring Quarter 2026 for purposes of
* the course. No other use, copying, distribution, or modification
* is permitted without prior written consent. Copyrights for
* third-party components of this work must be honored. Instructors
* interested in reusing these course materials should contact the
* author.
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include "SocketUtil.h"
using std::cerr;
using std::endl;
#define BUFSIZE 256
// Prints usage information about this program and exits with EXIT_FAILURE.
void Usage(char* progname);
// Open a local file, open a socket to a remote process,
// and send the file to other process.
int main(int argc, char** argv) {
if (argc != 4) {
Usage(argv[0]);
}
// Attempt to open up the file
int file_fd = open(argv[3], O_RDONLY);
if (file_fd == -1) {
Usage(argv[0]);
}
unsigned short port = 0;
if (sscanf(argv[2], "%hu", &port) != 1) {
close(file_fd);
Usage(argv[0]);
}
// Get an appropriate sockaddr structure.
struct sockaddr_storage addr;
size_t addrlen;
if (!LookupName(argv[1], port, &addr, &addrlen)) {
close(file_fd);
Usage(argv[0]);
}
// Connect to the remote host.
int socket_fd;
if (!Connect(addr, addrlen, &socket_fd)) {
close(file_fd);
Usage(argv[0]);
}
// Read from the input file, writing to the network socket.
unsigned char readbuf[BUFSIZE];
while (1) {
int res = WrappedRead(file_fd, readbuf, BUFSIZE);
if (res == 0) // eof
break;
if (res < 0) { // error
close(socket_fd);
close(file_fd);
return EXIT_FAILURE;
}
int res2 = WrappedWrite(socket_fd, readbuf, res);
if (res2 != res) { // error
close(socket_fd);
close(file_fd);
return EXIT_FAILURE;
}
}
// Clean up.
close(socket_fd);
close(file_fd);
return EXIT_SUCCESS;
}
void Usage(char* progname) {
cerr << "usage: " << progname << " hostname port filename" << endl;
exit(EXIT_FAILURE);
}