MCPcopy Create free account
hub / github.com/DeusData/codebase-memory-mcp / cbm_language_from_shebang

Function cbm_language_from_shebang

src/discover/language.c:1029–1112  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1027}
1028
1029CBMLanguage cbm_language_from_shebang(const char *path) {
1030 if (!path) {
1031 return CBM_LANG_COUNT;
1032 }
1033
1034 FILE *f = cbm_fopen(path, "rb");
1035 if (!f) {
1036 return CBM_LANG_COUNT; /* fail closed on read error */
1037 }
1038
1039 /* Read only a bounded first line. */
1040 char buf[CBM_SZ_256];
1041 size_t n = fread(buf, SKIP_ONE, sizeof(buf) - SKIP_ONE, f);
1042
1043 /* Fail closed on any read error rather than parsing a partial buffer. */
1044 if (ferror(f)) {
1045 (void)fclose(f);
1046 return CBM_LANG_COUNT;
1047 }
1048
1049 /* If the bounded buffer filled without containing a newline, the first
1050 * line may extend past our bound. Probe a single extra byte to tell an
1051 * exact EOF (the whole file is <= 255 bytes) from a truncated longer
1052 * line: any surviving byte -- including a newline just beyond the bound --
1053 * means the first line was cut off, so fail closed. A probe read error
1054 * fails closed too. This keeps the read bounded (no unbounded line read
1055 * or allocation). */
1056 bool have_newline = (memchr(buf, '\n', n) != NULL);
1057 if (!have_newline && n == sizeof(buf) - SKIP_ONE) {
1058 int probe = fgetc(f);
1059 if (probe != EOF || ferror(f)) {
1060 (void)fclose(f);
1061 return CBM_LANG_COUNT;
1062 }
1063 }
1064 (void)fclose(f);
1065
1066 /* Must begin with "#!". */
1067 if (n < PAIR_LEN || buf[0] != '#' || buf[1] != '!') {
1068 return CBM_LANG_COUNT;
1069 }
1070
1071 /* Isolate the first line; reject an embedded NUL before the newline. */
1072 size_t line_len = 0;
1073 while (line_len < n && buf[line_len] != '\n') {
1074 if (buf[line_len] == '\0') {
1075 return CBM_LANG_COUNT; /* embedded NUL — treat as binary */
1076 }
1077 line_len++;
1078 }
1079 /* Trim a trailing CR so CRLF first lines parse. */
1080 if (line_len > 0 && buf[line_len - SKIP_ONE] == '\r') {
1081 line_len--;
1082 }
1083 buf[line_len] = '\0';
1084
1085 /* First token after "#!" is the interpreter (or env). */
1086 char *cursor = buf + PAIR_LEN;

Callers 1

detect_file_languageFunction · 0.85

Calls 4

cbm_fopenFunction · 0.85
shebang_next_tokenFunction · 0.85
interp_basenameFunction · 0.85
lang_for_interpreterFunction · 0.85

Tested by

no test coverage detected