#include #include #include #include #include #include void die(const char *fmt, ...) { va_list ap; fputs("mplay: ", stderr); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); if (*fmt && fmt[strlen(fmt)-1] == ':') { perror(NULL); } else { fputc('\n', stderr); } exit(1); } int main(int argc, char **argv) { char *path, *bin; char *tok, *sep, *end; char **arg, *fmt; struct dirent *ent; DIR *dir; if (argc < 2) die("mplay [-d] [-f FMT] ... FILE[.FMT]"); path = strdup(getenv("PATH")); if (!path) die("PATH not set"); fmt = NULL; for (arg = argv; arg[1]; arg++) { if (!strcmp(arg[1], "-f")) { fmt = arg[2]; arg++; } else { break; } } arg[0] = argv[0]; if (fmt == NULL) { fmt = strrchr(argv[argc - 1], '.'); if (!fmt) die("no file extension"); fmt += 1; } tok = path; do { sep = strchr(tok, ':'); end = sep ? sep : tok + strlen(tok); *end = '\0'; dir = opendir(tok); while (dir && (ent = readdir(dir))) { if (!strncmp(ent->d_name, "mplay.", 6) && !strcmp(ent->d_name + 6, fmt)) { bin = malloc(strlen(tok) + strlen(ent->d_name) + 2); if (!bin) die("malloc:"); strcpy(bin, tok); strcat(bin, "/"); strcat(bin, ent->d_name); closedir(dir); execv(bin, arg); die("execv %s:", bin); } } if (dir) closedir(dir); tok = sep + 1; } while (sep); die("no handler"); }