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; }
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; }