Beispiel #1
0
int main(int argc, char * argv[]) {
    signal(SIGINT, sigint_handler);

    bool israw = false;
    bool readstdin = false;
    char* code = NULL;
    bool usecolors = true;

    int ch;
    while ((ch = getopt(argc, argv, "nirc:t:sh")) != -1) {
        switch (ch) {
            case 'n': usecolors = false; break;
            case 'i': break;
            case 'r': israw = true; break;
            case 'c': code = optarg; break;
            case 't': recvTimeout = strtod(optarg, NULL); break;
            case 's': readstdin = true; break;
            case 'h': case '?': default:
                usage(argv[0]);
        }
    }

    if (optind != argc) usage(argv[0]);

    argc -= optind;
    argv += optind;

    CFMessagePortRef port = CFMessagePortCreateRemote(NULL, CFSTR("Hammerspoon"));

    if (!port) {
        fprintf(stderr, "error: can't access Hammerspoon; is it running with the ipc module loaded?\n");
        return 1;
    }

    CFMutableStringRef str = CFStringCreateMutable(NULL, 0);

    if (readstdin) {
        target_setprefix(str, israw);

        char buffer[BUFSIZ];
        while (fgets(buffer, BUFSIZ, stdin))
            CFStringAppendCString(str, buffer, kCFStringEncodingUTF8);

        if (ferror(stdin)) {
            perror("error reading from stdin.");
            exit(3);
        }

        target_send(port, str);
    }
    else if (code) {
        target_setprefix(str, israw);
        CFStringAppendCString(str, code, kCFStringEncodingUTF8);
        target_send(port, str);
    }
    else {
        if (usecolors)
            setupcolors();

        printf("%sHammerspoon interactive prompt.%s\n", COLOR_INITIAL, COLOR_RESET);

        while (1) {
            printf("\n%s", COLOR_INPUT);
            char* input = readline("> ");
            printf("%s", COLOR_RESET);
            if (!input) { printf("\n") ; exit(0); }
            add_history(input);

            if (!CFMessagePortIsValid(port)) {
                fprintf(stderr, "%sMessage port has become invalid.  Attempting to re-establish.%s\n", COLOR_INITIAL, COLOR_RESET);
                port = CFMessagePortCreateRemote(NULL, CFSTR("Hammerspoon"));
                if (!port) {
                    fprintf(stderr, "error: can't access Hammerspoon; is it running?\n");
                    exit(1);
                }

            }

            target_setprefix(str, israw);
            CFStringAppendCString(str, input, kCFStringEncodingUTF8);
            target_send(port, str);
            CFStringDelete(str, CFRangeMake(0, CFStringGetLength(str)));

            free(input);
        }
    }

    return 0;
}
Beispiel #2
0
int setoptions(Options *options, int argc, char **argv)
{
    opterr = 0;     /* we will print our own error messages */
    int option;
    while ((option = getopt(argc, argv, ":" OPTSTRING)) != -1) {
        switch(option) {
        case '1':
            options->displaymode = DISPLAY_ONE_PER_LINE;
            break;
        case 'A':
            /* maybe print ACLs?  or -a without "." and ".."? */
            break;
        case 'a':
            options->all = true;
            break;
        case 'B':
            options->bytes = true;
            break;
        case 'b':
            /* GNU ls uses this for ESCAPE_C, but we use -e = escape */
            options->bytes = true;
            break;
        case 'C':
            options->displaymode = DISPLAY_IN_COLUMNS;
            break;
        case 'c':
            options->timetype = TIME_CTIME;
            /* this interacts with other options see below */
            break;
        case 'D':
            options->dirsonly = true;
            break;
        case 'd':
            options->directory = true;
            break;
        case 'E':
            options->escape = ESCAPE_NONE;
            break;
        case 'e':
            options->escape = ESCAPE_C;
            break;
        case 'F':
            options->flags = FLAGS_NORMAL;
            break;
        case 'f':
            options->compare = NULL;
            break;
        case 'G':
            /* for compatibility with FreeBSD */
            options->color = true;
            break;
        case 'g':
            /* hopefully saner than legacy ls */
            options->group = true;
            break;
        case 'H':
            options->followdirlinkargs = ON;
            break;
        case 'I':
            options->timeformat = "%Y-%m-%d %H:%M:%S";
            break;
        case 'i':
            options->inode = true;
            break;
        case 'K':
            /* K = "kolor", somewhat mnemonic and unused in GNU ls */
            options->color = true;
            break;
        case 'k':
            options->blocksize = 1024;
            break;
        case 'L':
            options->targetinfo = ON;
            break;
        case 'l':
            options->longformat = true;
            options->modes = true;
            options->linkcount = true;
            options->owner = true;
            options->group = true;
            options->bytes = true;
            options->datetime = true;
            options->showlink = true;
            options->displaymode = DISPLAY_ONE_PER_LINE;
            options->dirtotals = true;
            break;
        case 'M':
            /* might change this to blocksize=1048576 later */
            options->modes = true;
            break;
        case 'm':
            /* conflicts with legacy ls "streams" mode */
            options->modes = true;
            break;
        case 'N':
            options->linkcount = true;
            break;
        case 'n':
            options->numeric = true;
            break;
        case 'O':
            options->flags = FLAGS_OLD;
            break;
        case 'o':
            options->owner = true;
            break;
        case 'P':
            options->targetinfo = OFF;
            break;
        case 'p':
            options->perms = true;
            break;
        case 'q':
            options->escape = ESCAPE_QUESTION;
            break;
        case 'R':
            options->recursive = true;
            break;
        case 'r':
            options->reverse = true;
            break;
        case 'S':
            options->sorttype = SORT_BY_SIZE;
            break;
        case 's':
            options->size = true;
            options->dirtotals = true;
            break;
        case 'T':
            options->datetime = true;
            break;
        case 't':
            options->sorttype = SORT_BY_TIME;
            break;
        case 'U':
            options->sorttype = SORT_UNSORTED;
            break;
        case 'u':
            options->timetype = TIME_ATIME;
            /* this interacts with other options see below */
            break;
        case 'V':
            options->showlinks = true;
            break;
        case 'v':
            options->sorttype = SORT_BY_VERSION;
            break;
        case 'x':
            options->displaymode = DISPLAY_IN_ROWS;
            break;
        case ':':
            error("Missing argument to -%c\n", optopt);
            usage();
            return -1;
        case '?':
            error("Unknown option -%c\n", optopt);
            usage();
            return -1;
        default:
            usage();
            return -1;
        }
    }

    /* compatibility: -c = -ct, -u = -ut (unless -T or -l) */
    if (options->compatible &&
       !options->datetime &&
        options->timetype != TIME_MTIME) {
        options->sorttype = SORT_BY_TIME;
    }

    switch (options->sorttype) {
    case SORT_BY_NAME:
        options->compare = &comparebyname;
        break;
    case SORT_BY_TIME:
        /* XXX make this cleaner */
        switch (options->timetype) {
        case TIME_MTIME:
            options->compare = &comparebymtime;
            break;
        case TIME_ATIME:
            options->compare = &comparebyatime;
            break;
        case TIME_CTIME:
            options->compare = &comparebyctime;
            break;
        default:
            errorf("Unknown time type\n");
            options->compare = &comparebyname;
            break;
        }
        break;
    case SORT_BY_SIZE:
        /* neither POSIX nor GNU seem to define "size"
           but based on experiments, it seems to be the st_size field */
        options->compare = &comparebysize;
        break;
    case SORT_BY_VERSION:
        options->compare = &comparebyversion;
        break;
    case SORT_UNSORTED:
        options->compare = NULL;
        /* don't reverse output if it's unsorted
         * (as per BSD and GNU) */
        if (options->compare == NULL) {
            options->reverse = 0;
        }
        break;
    }

    /* if -H was not given, set it based on other flags...*/
    if (options->followdirlinkargs == DEFAULT) {
        if (options->targetinfo != DEFAULT) {
            /* -L implies -H, -P implies not -H */
            options->followdirlinkargs = options->targetinfo;
        } else if (options->compatible && (options->flags || options->longformat)) {
            /* -F or -l imply not -H */
            options->followdirlinkargs = OFF;
        } else {
            /* if not -L, -P, -F, or -l, -H defaults to on */
            options->followdirlinkargs = ON;
        }
    }

    if (options->targetinfo == DEFAULT) {
        options->targetinfo = OFF;
    }

    if (options->targetinfo == ON) {
      options->showlink = false;
    }

    if (options->color) {
        Colors *colors = malloc(sizeof(*colors));
        if (!colors) {
            errorf("Out of memory?\n");
            goto error;
        }

        options->color = setupcolors(colors);
        options->colors = colors;
    }

    if (options->datetime && options->timeformat == NULL) {
        options->now = time(NULL);
        if (options->now == -1) {
            errorf("Cannot determine current time\n");
            /* non-fatal */
        }
    }

    if (options->group && !options->numeric) {
        options->groupnames = newmap();
        if (!options->groupnames) {
            errorf("Out of memory?\n");
            goto error;
        }
    }
    if (options->owner && !options->numeric) {
        options->usernames = newmap();
        if (!options->usernames) {
            errorf("Out of memory?\n");
            goto error;
        }
    }

    return optind;

error:
    freeoptions(options);
    return -1;
}