static boolean loadPathKinds (xcmdPath *const path, const langType language) { enum pcoprocError r; FILE* pp = NULL; char * argv[3]; int status; vString * opt; char file_kind = getLanguageFileKind (language)->letter; opt = vStringNewInit(XCMD_LIST_KIND_OPTION); vStringCatS (opt, "="); vStringCatS (opt, getLanguageName(language)); argv[2] = NULL; argv[1] = vStringValue (opt); argv[0] = vStringValue (path->path); errno = 0; if (getuid() == 0 || geteuid() == 0) { verbose ("all xcmd feature is disabled when running ctags in root privilege\n"); vStringDelete (opt); return FALSE; } if (! isSafeExecutable (argv [0])) { vStringDelete (opt); return FALSE; } verbose ("loading path kinds of %s from [%s %s]\n", getLanguageName(language), argv[0], argv[1]); r = pcoprocOpen (vStringValue (path->path), argv, &pp, NULL); switch (r) { case PCOPROC_ERROR_WPIPE: error (WARNING | PERROR, "failed to make pipe to write to command: [%s %s]", argv[0], argv[1]); break; case PCOPROC_ERROR_RPIPE: error (WARNING | PERROR, "failed to make pipe to read from command: [%s %s]", argv[0], argv[1]); break; case PCOPROC_ERROR_FORK: error (WARNING | PERROR, "failed to do fork: [%s %s]", argv[0], argv[1]); break; case PCOPROC_SUCCESSFUL: break; } if (pp) { vString* vline = vStringNew(); while (readLineWithNoSeek (vline, pp)) { char* line; char kind_letter; vStringStripNewline (vline); line = vStringValue (vline); if (!loadPathKind (path, line, argv)) break; kind_letter = path->kinds [path->n_kinds - 1].letter; if (kind_letter == file_kind) error (FATAL, "Kind letter \'%c\' returned from xcmd %s of %s language is reserved in ctags main", kind_letter, vStringValue (path->path), getLanguageName (language)); } vStringDelete (vline); status = pcoprocClose (pp); /* TODO: Decode status */ verbose(" status: %d\n", status); if (status != 0) { if (status > 0 && WIFEXITED (status) && (WEXITSTATUS (status) == path->not_available_status)) verbose ("xcmd: the %s backend is not available\n", argv[0]); else error (WARNING, "xcmd exits abnormally status(%d): [%s %s]", status, argv[0], argv[1]); vStringDelete (opt); return FALSE; } } else { error (WARNING | PERROR, "cannot make pipe to xcmd: [%s %s]", argv[0], argv[1]); } vStringDelete (opt); return path->kinds == NULL? FALSE: TRUE; }
static boolean loadPathKinds (xcmdPath *const path, const langType language) { enum pcoproc_error r; FILE* pp = NULL; char * argv[3]; int status; vString * opt; opt = vStringNewInit(XCMD_LIST_KIND_OPTION); vStringCatS (opt, "="); vStringCatS (opt, getLanguageName(language)); argv[2] = NULL; argv[1] = vStringValue (opt); argv[0] = vStringValue (path->path); errno = 0; verbose ("loading path kinds of %s from [%s %s]\n", getLanguageName(language), argv[0], argv[1]); r = pcoproc_open (vStringValue (path->path), argv, &pp, NULL); switch (r) { case PCOPROC_ERROR_WPIPE: error (WARNING | PERROR, "failed to make pipe to write to command: [%s %s]", argv[0], argv[1]); break; case PCOPROC_ERROR_RPIPE: error (WARNING | PERROR, "failed to make pipe to read from command: [%s %s]", argv[0], argv[1]); break; case PCOPROC_ERROR_FORK: error (WARNING | PERROR, "failed to do fork: [%s %s]", argv[0], argv[1]); break; case PCOPROC_SUCCESSFUL: break; } if (pp) { vString* vline = vStringNew(); while (readLineWithNoSeek (vline, pp)) { char* line; vStringStripNewline (vline); line = vStringValue (vline); if (!loadPathKind (path, line, argv)) break; } vStringDelete (vline); status = pcoproc_close (pp); /* TODO: Decode status */ verbose(" status: %d\n", status); if (status != 0) { if (status > 0 && WIFEXITED (status) && (WEXITSTATUS (status) == XCMD_NOT_AVAILABLE_STATUS)) notice ("xcmd recognizes %s is not available", argv[0]); else error (WARNING, "xcmd exits abnormally status(%d): [%s %s]", status, argv[0], argv[1]); vStringDelete (opt); return FALSE; } } else { error (WARNING | PERROR, "cannot make pipe to xcmd: [%s %s]", argv[0], argv[1]); } vStringDelete (opt); return path->kinds == NULL? FALSE: TRUE; }