• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #4991

17 Mar 2026 07:57AM UTC coverage: 69.756% (+0.4%) from 69.348%
#4991

push

travis-ci

web-flow
merge: from main to 3.0 branch #34807

14 of 16 new or added lines in 5 files covered. (87.5%)

3928 existing lines in 138 files now uncovered.

192146 of 275455 relevant lines covered (69.76%)

137208686.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

47.57
/source/os/src/osSystem.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#define ALLOW_FORBID_FUNC
17
#define _DEFAULT_SOURCE
18
#include "os.h"
19

20
#if defined(WINDOWS)
21
typedef void (*MainWindows)(int argc, char** argv);
22
MainWindows mainWindowsFunc = NULL;
23

24
SERVICE_STATUS        ServiceStatus;
25
SERVICE_STATUS_HANDLE hServiceStatusHandle;
26
void WINAPI           windowsServiceCtrlHandle(DWORD request) {
27
            switch (request) {
28
              case SERVICE_CONTROL_STOP:
29
              case SERVICE_CONTROL_SHUTDOWN:
30
      raise(SIGINT);
31
      ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
32
      if (!SetServiceStatus(hServiceStatusHandle, &ServiceStatus)) {
33
                  DWORD nError = GetLastError();
34
                  fprintf(stderr, "failed to send stopped status to windows service: %d", nError);
35
      }
36
      break;
37
              default:
38
      return;
39
  }
40
}
41
void WINAPI mainWindowsService(int argc, char** argv) {
42
  int ret = 0;
43
  ServiceStatus.dwServiceType = SERVICE_WIN32;
44
  ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
45
  ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
46
  ServiceStatus.dwWin32ExitCode = 0;
47
  ServiceStatus.dwCheckPoint = 0;
48
  ServiceStatus.dwWaitHint = 0;
49
  ServiceStatus.dwServiceSpecificExitCode = 0;
50
  hServiceStatusHandle = RegisterServiceCtrlHandler("taosd", &windowsServiceCtrlHandle);
51
  if (hServiceStatusHandle == 0) {
52
    DWORD nError = GetLastError();
53
    fprintf(stderr, "failed to register windows service ctrl handler: %d", nError);
54
  }
55

56
  ServiceStatus.dwCurrentState = SERVICE_RUNNING;
57
  if (SetServiceStatus(hServiceStatusHandle, &ServiceStatus)) {
58
    DWORD nError = GetLastError();
59
    fprintf(stderr, "failed to send running status to windows service: %d", nError);
60
  }
61
  if (mainWindowsFunc != NULL) mainWindowsFunc(argc, argv);
62
  ServiceStatus.dwCurrentState = SERVICE_STOPPED;
63
  if (!SetServiceStatus(hServiceStatusHandle, &ServiceStatus)) {
64
    DWORD nError = GetLastError();
65
    fprintf(stderr, "failed to send stopped status to windows service: %d", nError);
66
  }
67
}
68
void stratWindowsService(MainWindows mainWindows) {
69
  mainWindowsFunc = mainWindows;
70
  SERVICE_TABLE_ENTRY ServiceTable[2];
71
  ServiceTable[0].lpServiceName = "taosd";
72
  ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)mainWindowsService;
73
  ServiceTable[1].lpServiceName = NULL;
74
  ServiceTable[1].lpServiceProc = NULL;
75
  StartServiceCtrlDispatcher(ServiceTable);
76
}
77

78
#elif defined(_TD_DARWIN_64) || defined(TD_ASTRA)
79
#else
80
#include <dlfcn.h>
81
#include <termios.h>
82
#include <unistd.h>
83
#endif
84

85
#if !defined(WINDOWS) && !defined(TD_ASTRA)
86
struct termios oldtio;
87
#endif
88

89
typedef struct FILE TdCmd;
90

91
int32_t taosSetConsoleEcho(bool on) {
1,018✔
92
#if defined(WINDOWS)
93
  HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
94
  if (hStdin == INVALID_HANDLE_VALUE) {
95
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
96
    return terrno;
97
  }
98
  DWORD mode = 0;
99
  if (!GetConsoleMode(hStdin, &mode)) {
100
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
101
    return terrno;
102
  }
103
  if (on) {
104
    mode |= ENABLE_ECHO_INPUT;
105
  } else {
106
    mode &= ~ENABLE_ECHO_INPUT;
107
  }
108
  if (!SetConsoleMode(hStdin, mode)) {
109
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
110
    return terrno;
111
  }
112

113
  return 0;
114
#elif defined(TD_ASTRA)  // TD_ASTRA_TODO
115
  return 0;
116
#else
117
#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL)
118
  int            err;
119
  struct termios term;
814✔
120

121
  if (tcgetattr(STDIN_FILENO, &term) == -1) {
1,018✔
122
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
1,018✔
123
    return terrno;
1,018✔
124
  }
125

126
  if (on)
×
127
    term.c_lflag |= ECHOFLAGS;
×
128
  else
129
    term.c_lflag &= ~ECHOFLAGS;
×
130

131
  err = tcsetattr(STDIN_FILENO, TCSAFLUSH, &term);
×
132
  if (err == -1) {
×
133
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
134
    return terrno;
×
135
  }
136

137
  return 0;
×
138
#endif
139
}
140

141
int32_t taosSetTerminalMode() {
986✔
142
#if defined(WINDOWS) || defined(TD_ASTRA)  // TD_ASTRA_TODO
143
  return 0;
144
#else
145
  struct termios newtio;
986✔
146

147
  /* if (atexit() != 0) { */
148
  /*     fprintf(stderr, "Error register exit function!\n"); */
149
  /*     exit(EXIT_FAILURE); */
150
  /* } */
151

152
  (void)memcpy(&newtio, &oldtio, sizeof(oldtio));
986✔
153

154
  // Set new terminal attributes.
155
  newtio.c_iflag &= ~(IXON | IXOFF | ICRNL | INLCR | IGNCR | IMAXBEL | ISTRIP);
986✔
156
  newtio.c_iflag |= IGNBRK;
986✔
157

158
  // newtio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET);
159
  newtio.c_oflag |= OPOST;
986✔
160
  newtio.c_oflag |= ONLCR;
986✔
161
  newtio.c_oflag &= ~(OCRNL | ONLRET);
986✔
162

163
  newtio.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHOE | ECHONL | ECHOCTL | ECHOPRT | ECHOKE | ISIG);
986✔
164
  newtio.c_cc[VMIN] = 1;
986✔
165
  newtio.c_cc[VTIME] = 0;
986✔
166

167
  if (-1 == tcsetattr(0, TCSANOW, &newtio)) {
986✔
168
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
378✔
169
    (void)fprintf(stderr, "Fail to set terminal properties!\n");
378✔
170
    return terrno;
378✔
171
  }
172

173
  return 0;
608✔
174
#endif
175
}
176

177
int32_t taosGetOldTerminalMode() {
784✔
178
#if defined(WINDOWS) || defined(TD_ASTRA)  // TD_ASTRA_TODO
179
  return 0;
180
#else
181
  /* Make sure stdin is a terminal. */
182
  if (!isatty(STDIN_FILENO)) {
784✔
183
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
480✔
184
    return terrno;
480✔
185
  }
186

187
  // Get the parameter of current terminal
188
  if (-1 == tcgetattr(0, &oldtio)) {
304✔
189
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
190
    return terrno;
×
191
  }
192

193
  return 0;
304✔
194
#endif
195
}
196

197
int32_t taosResetTerminalMode() {
1,364✔
198
#if defined(WINDOWS) || defined(TD_ASTRA)  // TD_ASTRA_TODO
199
  return 0;
200
#else
201
  if (-1 == tcsetattr(0, TCSANOW, &oldtio)) {
1,364✔
202
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
1,060✔
203
    (void)fprintf(stderr, "Fail to reset the terminal properties!\n");
1,060✔
204
    return terrno;
1,060✔
205
  }
206
#endif
207
  return 0;
304✔
208
}
209

210
// 允许的命令白名单,用于防止命令注入
211
static bool isCommandAllowed(const char* cmd) {
968,654✔
212
  const char* allowedCmds[] = {"taos", "taosd", "taosdump", "taosBenchmark", "taosAdapter", "taosKeeper", NULL};
968,654✔
213
  for (const char** p = allowedCmds; *p != NULL; p++) {
6,780,578✔
214
    size_t cmdLen = strlen(*p);
5,811,924✔
215
    if (strncmp(cmd, *p, cmdLen) == 0) {
5,811,924✔
UNCOV
216
      char nextChar = cmd[cmdLen];
×
UNCOV
217
      if (nextChar == ' ' || nextChar == '\t' || nextChar == '\0') {
×
UNCOV
218
        return true;
×
219
      }
220
    }
221
  }
222
  return false;
968,654✔
223
}
224

225
// 移除危险字符,用于防止命令注入
UNCOV
226
static bool sanitizeCommand(const char* cmd) {
×
UNCOV
227
  const char* dangerousChars = ";|&`$()<>{}[]!*?~";
×
UNCOV
228
  for (const char* p = dangerousChars; *p; p++) {
×
UNCOV
229
    if (strchr(cmd, *p) != NULL) {
×
UNCOV
230
      return false;
×
231
    }
232
  }
UNCOV
233
  return true;
×
234
}
235

236
TdCmdPtr taosOpenCmd(const char* cmd) {
968,756✔
237
  if (cmd == NULL) {
968,756✔
238
    terrno = TSDB_CODE_INVALID_PARA;
102✔
239
    return NULL;
102✔
240
  }
241

242
  if (!isCommandAllowed(cmd)) {
968,654✔
243
    terrno = TSDB_CODE_INVALID_PARA;
968,654✔
244
    return NULL;
968,654✔
245
  }
246

UNCOV
247
  if (!sanitizeCommand(cmd)) {
×
UNCOV
248
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
249
    return NULL;
×
250
  }
251

252
#ifdef WINDOWS
253
  return (TdCmdPtr)_popen(cmd, "r");
254
#elif defined(TD_ASTRA)
255
  return NULL;
256
#else
UNCOV
257
  TdCmdPtr p = (TdCmdPtr)popen(cmd, "r");
×
UNCOV
258
  if (NULL == p) {
×
UNCOV
259
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
260
  }
UNCOV
261
  return p;
×
262
#endif
263
}
264

UNCOV
265
int64_t taosGetsCmd(TdCmdPtr pCmd, int32_t maxSize, char* __restrict buf) {
×
UNCOV
266
  if (pCmd == NULL || buf == NULL) {
×
UNCOV
267
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
268
    return terrno;
×
269
  }
UNCOV
270
  if (fgets(buf, maxSize, (FILE*)pCmd) == NULL) {
×
UNCOV
271
    if (feof((FILE*)pCmd)) {
×
UNCOV
272
      return 0;
×
273
    }
274

UNCOV
275
    terrno = TAOS_SYSTEM_ERROR(ferror((FILE*)pCmd));
×
UNCOV
276
    return terrno;
×
277
  }
278

UNCOV
279
  return strlen(buf);
×
280
}
281

UNCOV
282
int64_t taosGetLineCmd(TdCmdPtr pCmd, char** __restrict ptrBuf) {
×
UNCOV
283
  if (pCmd == NULL || ptrBuf == NULL) {
×
UNCOV
284
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
285
    return terrno;
×
286
  }
UNCOV
287
  if (*ptrBuf != NULL) {
×
UNCOV
288
    taosMemoryFreeClear(*ptrBuf);
×
289
  }
290

291
#ifdef WINDOWS
292
  *ptrBuf = taosMemoryMalloc(1024);
293
  if (*ptrBuf == NULL) return -1;
294
  if (fgets(*ptrBuf, 1023, (FILE*)pCmd) == NULL) {
295
    taosMemoryFreeClear(*ptrBuf);
296
    return -1;
297
  }
298
  (*ptrBuf)[1023] = 0;
299
  return strlen(*ptrBuf);
300
#elif defined(TD_ASTRA)
301
  size_t bufsize = 128;
302
  size_t pos = 0;
303
  int    c;
304
  if (*ptrBuf == NULL) {
305
    *ptrBuf = (char*)taosMemoryMalloc(bufsize);
306
    if (*ptrBuf == NULL) {
307
      return terrno;
308
    }
309
  }
310
  while ((c = fgetc((FILE*)pCmd)) != EOF) {
311
    if (pos + 1 >= bufsize) {
312
      size_t new_size = bufsize << 1;
313
      char*  new_line = (char*)taosMemoryRealloc(*ptrBuf, new_size);
314
      if (new_line == NULL) {
315
        return terrno;
316
      }
317
      *ptrBuf = new_line;
318
      bufsize = new_size;
319
    }
320
    (*ptrBuf)[pos++] = (char)c;
321
    if (c == '\n') {
322
      break;
323
    }
324
  }
325
  if (pos == 0 && c == EOF) {
326
    return TSDB_CODE_INVALID_PARA;
327
  }
328
  (*ptrBuf)[pos] = '\0';
329
  return (ssize_t)pos;
330
#else
UNCOV
331
  ssize_t len = 0;
×
UNCOV
332
  len = getline(ptrBuf, (size_t*)&len, (FILE*)pCmd);
×
UNCOV
333
  if (-1 == len) {
×
UNCOV
334
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
UNCOV
335
    return terrno;
×
336
  }
UNCOV
337
  return len;
×
338
#endif
339
}
340

UNCOV
341
int32_t taosEOFCmd(TdCmdPtr pCmd) {
×
UNCOV
342
  if (pCmd == NULL) {
×
UNCOV
343
    return 0;
×
344
  }
UNCOV
345
  return feof((FILE*)pCmd);
×
346
}
347

348
void taosCloseCmd(TdCmdPtr* ppCmd) {
204✔
349
  if (ppCmd == NULL || *ppCmd == NULL) {
204✔
350
    return;
204✔
351
  }
352
#ifdef WINDOWS
353
  _pclose((FILE*)(*ppCmd));
354
#elif defined(TD_ASTRA)  // TD_ASTRA_TODO
355
#else
UNCOV
356
  (void)pclose((FILE*)(*ppCmd));
×
357
#endif
UNCOV
358
  *ppCmd = NULL;
×
359
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc