Beispiel #1
0
void
fpcheck(void)
{
    register int fperrval;
    char *errdesc;

    if ((fperrval = iserr()) == 0)
	return;			/* no error */

    errdesc = (char *) 0;

    if (fperrval & INFNAN)
	errdesc = "arg is infinity or NAN";
    else if (fperrval & ZERODIV)
	errdesc = "division by zero";
    else if (fperrval & OVFLOW)
	errdesc = "overflow";
    else if (fperrval & UFLOW) {
	;			/* ignored */
    }

    if (errdesc)
	rt_error("%s", errdesc);
}
Beispiel #2
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;
}