#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <err.h>
#include <ctype.h>
#include <sys/types.h>
#include <string.h>
#include "../lpi.h"

int
main(int argc, char *argv[])
{
    int len;
    off_t offset;
    int fd, ap, j;
    long num;
    char *buf;
    ssize_t numRead, numWritten;

    if (argc < 3 || strcmp(argv[1], "--help") == 0) {
        fprintf(stderr,
            "%s file {r<length>|R<length>|w<string>|s<offset>}...\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    fd = open(argv[1], O_RDWR | O_CREAT,
                S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
                S_IROTH | S_IWOTH);                     /* rw-rw-rw- */
    if (fd == -1)
        err(EXIT_FAILURE, "open");

    for (ap = 2; ap < argc; ap++) {
        switch (argv[ap][0]) {
        case 'r':
        case 'R':
            if (toLong(&argv[ap][1], &num) != 0)
                continue;       /* invalid number */
            buf = (char *) malloc(num);
            if (buf == NULL)
                err(EXIT_FAILURE, "malloc");
            numRead = read(fd, buf, num);
            if (numRead == -1)
                err(EXIT_FAILURE, "read");
            if (numRead == 0)
                printf("%s: end-of-file\n", argv[ap]);
            else {
                printf("%s: ", argv[ap]);
                for (j = 0; j < numRead; j++) {
                    if (argv[ap][0] == 'r')
                        printf("%c", isprint(buf[j]) ? buf[j] : '?');
                    else
                        printf("%02x ", (unsigned int) buf[j]);
                }
                printf("\n");
            }
            free(buf);
            break;

        case 'w':
            numWritten = write(fd, &argv[ap][1], strlen(&argv[ap][1]));
            if (numWritten == -1)
                err(EXIT_FAILURE, "write");
            printf("%s: wrote %ld bytes\n", argv[ap], (long) numWritten);
            break;

        case 's':
            if (toLong(&argv[ap][1], &num) != 0)
                continue;   // invalid number
            if (lseek(fd, num, SEEK_SET) == -1)
                err(EXIT_FAILURE, "lseek");
            printf("%s: seek successed\n", argv[ap]);
            break;

        default:
            errx(EXIT_FAILURE,
                    "Arguments must start with [rRws]: %s\n", argv[ap]);
        }
    }

    exit(EXIT_SUCCESS);
}
