int main( int argc, char * argv[] ) { socketdesc sd; /* socket descriptor index */ long n; /* number of bytes received */ char sendline[MSGSIZE]; /* send buffer */ char recvline[MSGSIZE+1]; /* recieve buffer */ /* need an ip address.. localhost or 127.0.0.1 would work for our test case */ if (argc != 2 ) { fprintf( stderr, "echo <ip address>\n" ); exit(1); } initudp(); sd = openudp( FALSE, argv[1], 2007 ); if ( sd < 0 ) { fprintf( stderr, "error occured while connecting\n" ); exit(1); } while ( fgets( sendline, MSGSIZE, stdin ) != NULL ) { sendudp( sd, sendline, strlen(sendline), argv[1] ); n = recvudp( sd, recvline, MSGSIZE, NULL ); recvline[n] = '\0'; fputs(recvline, stdout); } closeudp( sd ); return 0; }
// Runs the interactive loop and all file transfers. // Returns: exit status int main(void) { // Used to control DNS resolution requests: struct addrinfo hints; memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; // Bind to an ephemeral network port: struct addrinfo *server = NULL; int sfd = openudp(0); if(sfd < 0) handle_error("bind()"); // Allocate (small) space to store user input: char *buf = malloc(1); size_t cap = 1; char *cmd; // First word of buf size_t len; // Length of cmd // Main input loop, which normally only breaks upon a GFO: do { // Keep prompting until the user brings us back something good: do { printf("%s", SHL_PS1); readin(&buf, &cap); } while(homog(buf, ' ')); // Cleave off the command (first word): cmd = strtok(buf, " "); len = strlen(cmd); if(strncmp(cmd, CMD_CON, len) == 0) { // Read the arguments: const char *hostname = strtok(NULL, " "); const char *tmp = strtok(NULL, " "); in_port_t port = PORT_UNPRIVILEGED; if(tmp) port = atoi(tmp); // Ensure a hostname or IP has been provided: if(!hostname) { usage(CMD_CON, "hostname", "port"); continue; } // Avoid leaking any existing address: if(server) { freeaddrinfo(server); server = NULL; } // Try to resolve the requested hostname: if(getaddrinfo(hostname, NULL, &hints, &server)) { fprintf(stderr, "Unable to resolve hostname\n"); freeaddrinfo(server); server = NULL; continue; } ((struct sockaddr_in *)server->ai_addr)->sin_port = htons(port); } else if(strncmp(cmd, CMD_GET, len) == 0 || strncmp(cmd, CMD_PUT, len) == 0) { bool putting = strncmp(cmd, CMD_PUT, 1) == 0; // Ensure we're already connected to a server: if(!server) { noconn(cmd); continue; } // Make sure we were given a path argument: char *pathname = strtok(NULL, ""); if(!pathname) { usage(putting ? CMD_PUT : CMD_GET, "pathname", NULL); continue; } // Since basename() might modify pathname, copy it: char filename[strlen(pathname)+1]; memcpy(filename, pathname, sizeof filename); int fd; if(putting) { // Try opening the file for reading: if((fd = open(pathname, O_RDONLY)) < 0) { fprintf(stderr, "local: Unable to read specified file\n"); continue; } // Send a request and record the port used to acknowledge: struct sockaddr_in dest_addr; sendreq(sfd, basename(filename), OPC_WRQ, server->ai_addr); uint8_t *rmtack = recvpkta(sfd, &dest_addr); if(iserr(rmtack)) { fprintf(stderr, "remote: %s\n", strerr(rmtack)); free(rmtack); continue; } free(rmtack); // Transmit the file: sendfile(sfd, fd, &dest_addr); } else // getting { // Try opening a file of that name for writing: if((fd = open(basename(filename), O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) { fprintf(stderr, "local: Unable to create the new file\n"); continue; } // Send a request and await the incoming file: sendreq(sfd, pathname, OPC_RRQ, server->ai_addr); const char *res = recvfile(sfd, fd); if(res) { fprintf(stderr, "remote: %s\n", res); close(fd); fd = -1; unlink(basename(filename)); } } if(fd >= 0) close(fd); } else if(strncmp(cmd, CMD_HLP, len) == 0) { printf("Commands may be abbreviated. Commands are:\n\n"); printf("%s\t\tconnect to remote tftp\n", CMD_CON); printf("%s\t\tsend file\n", CMD_PUT); printf("%s\t\treceive file\n", CMD_GET); printf("%s\t\texit tftp\n", CMD_GFO); printf("%s\t\tprint help information\n", CMD_HLP); } else if(strncmp(cmd, CMD_GFO, len) != 0) { fprintf(stderr, "%s: unknown directive\n", cmd); fprintf(stderr, "Try ? for help.\n"); } } while(strncmp(cmd, CMD_GFO, len) != 0); free(buf); if(server) freeaddrinfo(server); return 0; }