fifo_server.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. /*
  2. * $Id$
  3. *
  4. *
  5. * Copyright (C) 2001-2003 Fhg Fokus
  6. *
  7. * This file is part of ser, a free SIP server.
  8. *
  9. * ser is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version
  13. *
  14. * For a license to use the ser software under conditions
  15. * other than those described here, or to purchase support for this
  16. * software, please contact iptel.org by e-mail at the following addresses:
  17. * [email protected]
  18. *
  19. * ser is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  27. *
  28. * Fifo server is a very powerful tool used to access easily
  29. * ser's internals via textual interface, similarly to
  30. * how internals of many operating systems are accessible
  31. * via the proc file system. This might be used for
  32. * making ser do things for you (such as initiating new
  33. * transaction from webpages) or inspect server's health.
  34. *
  35. * FIFO server allows new functionality to be registered
  36. * with it -- thats what register_fifo_cmd is good for.
  37. * Remember, the initialization must take place before
  38. * forking; best in init_module functions. When a function
  39. * is registered, it can be always evoked by sending its
  40. * name prefixed by colon to the FIFO.
  41. *
  42. * There are few commands already implemented in core.
  43. * These are 'uptime' for looking at how long the server
  44. * is alive and 'print' for debugging purposes.
  45. *
  46. * Every command sent to FIFO must be sent atomically to
  47. * avoid intermixing with other commands and MUST be
  48. * terminated by empty line so that the server is to able
  49. * to find its end if it does not understand the command.
  50. *
  51. * File test/transaction.fifo illustrates example of use
  52. * of t_uac command (part of TM module).
  53. */
  54. #include <stdlib.h>
  55. #include <sys/types.h>
  56. #include <unistd.h>
  57. #include <stdio.h>
  58. #include <errno.h>
  59. #include <sys/types.h>
  60. #include <sys/stat.h>
  61. #include <fcntl.h>
  62. #include <signal.h>
  63. #include <string.h>
  64. #include <time.h>
  65. #include <stdarg.h>
  66. #include "dprint.h"
  67. #include "ut.h"
  68. #include "error.h"
  69. #include "config.h"
  70. #include "globals.h"
  71. #include "fifo_server.h"
  72. #include "mem/mem.h"
  73. #include "sr_module.h"
  74. #include "pt.h"
  75. /* FIFO server vars */
  76. char *fifo=0; /* FIFO name */
  77. int fifo_mode=S_IRUSR | S_IWUSR | S_IRGRP |
  78. S_IWGRP | S_IROTH | S_IWOTH;
  79. pid_t fifo_pid;
  80. /* file descriptors */
  81. static int fifo_read=0;
  82. static int fifo_write=0;
  83. static FILE *fifo_stream;
  84. /* list of fifo command */
  85. static struct fifo_command *cmd_list=0;
  86. /* up time */
  87. static time_t up_since;
  88. static char up_since_ctime[MAX_CTIME_LEN];
  89. static struct fifo_command *lookup_fifo_cmd( char *name )
  90. {
  91. struct fifo_command *c;
  92. for(c=cmd_list; c; c=c->next) {
  93. if (strcasecmp(c->name, name)==0) return c;
  94. }
  95. return 0;
  96. }
  97. int register_fifo_cmd(fifo_cmd f, char *cmd_name, void *param)
  98. {
  99. struct fifo_command *new_cmd;
  100. if (lookup_fifo_cmd(cmd_name)) {
  101. LOG(L_ERR, "ERROR: register_fifo_cmd: attempt to register synonyms\n");
  102. return E_BUG;
  103. }
  104. new_cmd=malloc(sizeof(struct fifo_command));
  105. if (new_cmd==0) {
  106. LOG(L_ERR, "ERROR: register_fifo_cmd: out of mem\n");
  107. return E_OUT_OF_MEM;
  108. }
  109. new_cmd->f=f;
  110. new_cmd->name=cmd_name;
  111. new_cmd->param=param;
  112. new_cmd->next=cmd_list;
  113. cmd_list=new_cmd;
  114. DBG("DEBUG: register_fifo_cmd: new command (%s) registered\n", cmd_name );
  115. return 1;
  116. }
  117. int read_line( char *b, int max, FILE *stream, int *read )
  118. {
  119. int len;
  120. int retry_cnt;
  121. retry_cnt=0;
  122. retry:
  123. if (fgets(b, max, stream)==NULL) {
  124. LOG(L_ERR, "ERROR: fifo_server fgets failed: %s\n",
  125. strerror(errno));
  126. /* on Linux, fgets sometimes returns ESPIPE -- give
  127. it few more chances
  128. */
  129. if (errno==ESPIPE) {
  130. retry_cnt++;
  131. if (retry_cnt<4) goto retry;
  132. }
  133. /* interrupted by signal or ... */
  134. if ((errno==EINTR)||(errno==EAGAIN)) goto retry;
  135. kill(0, SIGTERM);
  136. }
  137. /* if we did not read whole line, our buffer is too small
  138. and we cannot process the request; consume the remainder of
  139. request
  140. */
  141. len=strlen(b);
  142. if (len && !(b[len-1]=='\n' || b[len-1]=='\r')) {
  143. LOG(L_ERR, "ERROR: read_line: request line too long\n");
  144. return 0;
  145. }
  146. /* trim from right */
  147. while(len) {
  148. if(b[len-1]=='\n' || b[len-1]=='\r'
  149. || b[len-1]==' ' || b[len-1]=='\t' ) {
  150. len--;
  151. b[len]=0;
  152. } else break;
  153. }
  154. *read=len;
  155. return 1;
  156. }
  157. static void consume_request( FILE *stream )
  158. {
  159. int len;
  160. char buffer[MAX_CONSUME_BUFFER];
  161. while(!read_line(buffer, MAX_CONSUME_BUFFER, stream, &len));
  162. #ifdef _OBSOLETED
  163. int eol_count;
  164. eol_count=0;
  165. /* each request must be terminated by two EoLs */
  166. while(eol_count!=2) {
  167. /* read until EoL is encountered */
  168. while(!read_line(buffer, MAX_CONSUME_BUFFER, stream, &len));
  169. eol_count=len==0?eol_count+1:1;
  170. }
  171. #endif
  172. }
  173. int read_eol( FILE *stream )
  174. {
  175. int len;
  176. char buffer[MAX_CONSUME_BUFFER];
  177. if (!read_line(buffer, MAX_CONSUME_BUFFER, stream, &len) || len!=0) {
  178. LOG(L_ERR, "ERROR: read_eol: EOL expected: %.10s...\n",
  179. buffer );
  180. return 0;
  181. }
  182. return 1;
  183. }
  184. /* read from input until empty line is encountered */
  185. int read_line_set(char *buf, int max_len, FILE *fifo, int *len)
  186. {
  187. int set_len;
  188. char *c;
  189. int line_len;
  190. c=buf;set_len=0;
  191. while(1) {
  192. if (!read_line(c,max_len,fifo,&line_len)) {
  193. LOG(L_ERR, "ERROR: fifo_server: line expected\n");
  194. return 0;
  195. }
  196. /* end encountered ... return */
  197. if (line_len==0) {
  198. *len=set_len;
  199. return 1;
  200. }
  201. max_len-=line_len; c+=line_len; set_len+=line_len;
  202. if (max_len<CRLF_LEN) {
  203. LOG(L_ERR, "ERROR: fifo_server: no place for CRLF\n");
  204. return 0;
  205. }
  206. memcpy(c, CRLF, CRLF_LEN);
  207. max_len-=CRLF_LEN; c+=CRLF_LEN; set_len+=CRLF_LEN;
  208. }
  209. }
  210. /* read from input until line with only dot in it is encountered */
  211. int read_body(char *buf, int max_len, FILE *fifo, int *len)
  212. {
  213. int set_len;
  214. char *c;
  215. int line_len;
  216. c=buf;set_len=0;
  217. while(1) {
  218. if (!read_line(c,max_len,fifo,&line_len)) {
  219. LOG(L_ERR, "ERROR: fifo_server: line expected\n");
  220. return 0;
  221. }
  222. /* end encountered ... return */
  223. if (line_len==1 && *c=='.') {
  224. *len=set_len;
  225. return 1;
  226. }
  227. max_len-=line_len; c+=line_len; set_len+=line_len;
  228. if (max_len<CRLF_LEN) {
  229. LOG(L_ERR, "ERROR: fifo_server: no place for CRLF\n");
  230. return 0;
  231. }
  232. memcpy(c, CRLF, CRLF_LEN);
  233. max_len-=CRLF_LEN; c+=CRLF_LEN; set_len+=CRLF_LEN;
  234. }
  235. }
  236. static char *trim_filename( char * file )
  237. {
  238. int prefix_len, fn_len;
  239. char *new_fn;
  240. /* we only allow files in "/tmp" -- any directory
  241. changes are not welcome
  242. */
  243. if (strchr(file,'.') || strchr(file,'/')
  244. || strchr(file, '\\')) {
  245. LOG(L_ERR, "ERROR: trim_filename: forbidden filename: %s\n"
  246. , file);
  247. return 0;
  248. }
  249. prefix_len=strlen(FIFO_DIR); fn_len=strlen(file);
  250. new_fn=pkg_malloc(prefix_len+fn_len+1);
  251. if (new_fn==0) {
  252. LOG(L_ERR, "ERROR: trim_filename: no mem\n");
  253. return 0;
  254. }
  255. memcpy(new_fn, FIFO_DIR, prefix_len);
  256. memcpy(new_fn+prefix_len, file, fn_len );
  257. new_fn[prefix_len+fn_len]=0;
  258. return new_fn;
  259. }
  260. /* tell FIFO client what happened via reply pipe */
  261. void fifo_reply( char *reply_fifo, char *reply_fmt, ... )
  262. {
  263. FILE *file_handle;
  264. int r;
  265. va_list ap;
  266. file_handle=open_reply_pipe(reply_fifo);
  267. if (file_handle==0) {
  268. LOG(L_ERR, "ERROR: fifo_reply: no reply pipe %s\n",
  269. reply_fifo);
  270. return;
  271. }
  272. retry:
  273. va_start(ap, reply_fmt);
  274. r=vfprintf(file_handle, reply_fmt, ap);
  275. va_end(ap);
  276. if (r<=0) {
  277. LOG(L_ERR, "ERROR: fifo_error: write error (%s): %s\n",
  278. fifo, strerror(errno));
  279. if ((errno==EINTR)||(errno==EAGAIN)||(errno==EWOULDBLOCK)) {
  280. goto retry;
  281. }
  282. }
  283. fclose(file_handle);
  284. }
  285. FILE *open_reply_pipe( char *pipe_name )
  286. {
  287. int fifofd;
  288. FILE *file_handle;
  289. int flags;
  290. int retries=FIFO_REPLY_RETRIES;
  291. if (!pipe_name || *pipe_name==0) {
  292. DBG("DEBUG: open_reply_pipe: no file to write to about missing cmd\n");
  293. return 0;
  294. }
  295. tryagain:
  296. /* open non-blocking to make sure that a broken client will not
  297. * block the FIFO server forever */
  298. fifofd=open( pipe_name, O_WRONLY | O_NONBLOCK );
  299. if (fifofd==-1) {
  300. /* retry several times if client is not yet ready for getting
  301. feedback via a reply pipe
  302. */
  303. if (errno==ENXIO) {
  304. /* give up on the client - we can't afford server blocking */
  305. if (retries==0) {
  306. LOG(L_ERR, "ERROR: open_reply_pipe: no client at %s\n",
  307. pipe_name );
  308. return 0;
  309. }
  310. /* don't be noisy on the very first try */
  311. if (retries!=FIFO_REPLY_RETRIES)
  312. DBG("DEBUG: open_reply_pipe: retry countdown: %d\n", retries );
  313. sleep_us( FIFO_REPLY_WAIT );
  314. retries--;
  315. goto tryagain;
  316. }
  317. /* some other opening error */
  318. LOG(L_ERR, "ERROR: open_reply_pipe: open error (%s): %s\n",
  319. pipe_name, strerror(errno));
  320. return 0;
  321. }
  322. /* we want server blocking for big writes */
  323. if ( (flags=fcntl(fifofd, F_GETFL, 0))<0) {
  324. LOG(L_ERR, "ERROR: open_reply_pipe (%s): getfl failed: %s\n",
  325. pipe_name, strerror(errno));
  326. goto error;
  327. }
  328. flags&=~O_NONBLOCK;
  329. if (fcntl(fifofd, F_SETFL, flags)<0) {
  330. LOG(L_ERR, "ERROR: open_reply_pipe (%s): setfl cntl failed: %s\n",
  331. pipe_name, strerror(errno));
  332. goto error;
  333. }
  334. /* create an I/O stream */
  335. file_handle=fdopen( fifofd, "w");
  336. if (file_handle==NULL) {
  337. LOG(L_ERR, "ERROR: open_reply_pipe: open error (%s): %s\n",
  338. pipe_name, strerror(errno));
  339. goto error;
  340. }
  341. return file_handle;
  342. error:
  343. close(fifofd);
  344. return 0;
  345. }
  346. static void fifo_server(FILE *fifo_stream)
  347. {
  348. char buf[MAX_FIFO_COMMAND];
  349. int line_len;
  350. char *file_sep, *command, *file;
  351. struct fifo_command *f;
  352. file_sep=command=file=0;
  353. while(1) {
  354. /* commands must look this way ':<command>:[filename]' */
  355. if (!read_line(buf, MAX_FIFO_COMMAND, fifo_stream, &line_len)) {
  356. /* line breaking must have failed -- consume the rest
  357. and proceed to a new request
  358. */
  359. LOG(L_ERR, "ERROR: fifo_server: command expected\n");
  360. goto consume;
  361. }
  362. if (line_len==0) {
  363. LOG(L_INFO, "INFO: fifo_server: command empty\n");
  364. continue;
  365. }
  366. if (line_len<3) {
  367. LOG(L_ERR, "ERROR: fifo_server: command must have at least 3 chars\n");
  368. goto consume;
  369. }
  370. if (*buf!=CMD_SEPARATOR) {
  371. LOG(L_ERR, "ERROR: fifo_server: command must begin with %c: %.*s\n",
  372. CMD_SEPARATOR, line_len, buf );
  373. goto consume;
  374. }
  375. command=buf+1;
  376. file_sep=strchr(command, CMD_SEPARATOR );
  377. if (file_sep==NULL) {
  378. LOG(L_ERR, "ERROR: fifo_server: file separator missing\n");
  379. goto consume;
  380. }
  381. if (file_sep==command) {
  382. LOG(L_ERR, "ERROR: fifo_server: empty command\n");
  383. goto consume;
  384. }
  385. if (*(file_sep+1)==0) file=NULL;
  386. else {
  387. file=file_sep+1;
  388. file=trim_filename(file);
  389. if (file==0) {
  390. LOG(L_ERR, "ERROR: fifo_server: trimming filename\n");
  391. goto consume;
  392. }
  393. }
  394. /* make command zero-terminated */
  395. *file_sep=0;
  396. f=lookup_fifo_cmd( command );
  397. if (f==0) {
  398. LOG(L_ERR, "ERROR: fifo_server: command %s is not available\n",
  399. command);
  400. fifo_reply(file, "500 command '%s' not available\n", command);
  401. goto consume;
  402. }
  403. if (f->f(fifo_stream, file)<0) {
  404. LOG(L_ERR, "ERROR: fifo_server: command (%s) "
  405. "processing failed\n", command );
  406. goto consume;
  407. }
  408. consume:
  409. if (file) { pkg_free(file); file=0;}
  410. consume_request(fifo_stream);
  411. }
  412. }
  413. int open_fifo_server()
  414. {
  415. char *t;
  416. struct stat filestat;
  417. #ifdef USE_TCP
  418. int sockfd[2];
  419. #endif
  420. if (fifo==NULL) {
  421. DBG("TM: open_uac_fifo: no fifo will be opened\n");
  422. /* everything is ok, we just do not want to start */
  423. return 1;
  424. }
  425. if (strlen(fifo)==0) {
  426. DBG("TM: open_uac_fifo: fifo disabled\n");
  427. return 1;
  428. }
  429. DBG("TM: open_uac_fifo: opening fifo...\n");
  430. if (stat(fifo, &filestat)==-1) { /* FIFO doesn't exist yet ... */
  431. LOG(L_DBG, "DEBUG: open_fifo_server: FIFO stat failed: %s\n",
  432. strerror(errno));
  433. if ((mkfifo(fifo, fifo_mode)<0)) {
  434. LOG(L_ERR, "ERROR: open_fifo_server; can't create FIFO: "
  435. "%s (mode=%d)\n",
  436. strerror(errno), fifo_mode);
  437. return -1;
  438. }
  439. DBG("DEBUG: FIFO created @ %s\n", fifo );
  440. if ((chmod(fifo, fifo_mode)<0)) {
  441. LOG(L_ERR, "ERROR: open_fifo_server; can't chmod FIFO: "
  442. "%s (mode=%d)\n",
  443. strerror(errno), fifo_mode);
  444. return -1;
  445. }
  446. } else { /* file can be stat-ed, check if it is really a FIFO */
  447. if (!(S_ISFIFO(filestat.st_mode))) {
  448. LOG(L_ERR, "ERROR: open_fifo_server: "
  449. "the file is not a FIFO: %s\n",
  450. fifo );
  451. return -1;
  452. }
  453. }
  454. DBG("DEBUG: fifo %s opened, mode=%d\n", fifo, fifo_mode );
  455. time(&up_since);
  456. t=ctime(&up_since);
  457. if (strlen(t)+1>=MAX_CTIME_LEN) {
  458. LOG(L_ERR, "ERROR: open_fifo_server: "
  459. "too long date %d\n", (int)strlen(t));
  460. return -1;
  461. }
  462. memcpy(up_since_ctime,t,strlen(t)+1);
  463. #ifdef USE_TCP
  464. if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd)<0){
  465. LOG(L_ERR, "ERROR: open_fifo_server: socketpair failed: %s\n",
  466. strerror(errno));
  467. return -1;
  468. }
  469. #endif
  470. process_no++;
  471. fifo_pid=fork();
  472. if (fifo_pid<0) {
  473. LOG(L_ERR, "ERROR: open_fifo_server: failure to fork: %s\n",
  474. strerror(errno));
  475. return -1;
  476. }
  477. if (fifo_pid==0) { /* child == FIFO server */
  478. LOG(L_INFO, "INFO: fifo process starting: %d\n", getpid());
  479. /* call per-child module initialization too -- some
  480. FIFO commands may need it
  481. */
  482. #ifdef USE_TCP
  483. close(sockfd[0]);
  484. unix_tcp_sock=sockfd[1];
  485. #endif
  486. if (init_child(process_no) < 0 ) {
  487. LOG(L_ERR, "ERROR: open_uac_fifo: init_child failed\n");
  488. return -1;
  489. }
  490. fifo_read=open(fifo, O_RDONLY, 0);
  491. if (fifo_read<0) {
  492. LOG(L_ERR, "ERROR: open_uac_fifo: fifo_read did not open: %s\n",
  493. strerror(errno));
  494. return -1;
  495. }
  496. fifo_stream=fdopen(fifo_read, "r" );
  497. if (fifo_stream==NULL) {
  498. LOG(L_ERR, "SER: open_uac_fifo: fdopen failed: %s\n",
  499. strerror(errno));
  500. return -1;
  501. }
  502. /* a real server doesn't die if writing to reply fifo fails */
  503. signal(SIGPIPE, SIG_IGN);
  504. LOG(L_INFO, "SER: open_uac_fifo: fifo server up at %s...\n",
  505. fifo);
  506. fifo_server( fifo_stream ); /* never retruns */
  507. }
  508. /* dad process */
  509. pt[process_no].pid=fifo_pid;
  510. strncpy(pt[process_no].desc, "fifo server", MAX_PT_DESC );
  511. #ifdef USE_TCP
  512. close(sockfd[1]);
  513. pt[process_no].unix_sock=sockfd[0];
  514. pt[process_no].idx=-1; /* this is not "tcp" process*/
  515. #endif
  516. /* make sure the read fifo will not close */
  517. fifo_write=open(fifo, O_WRONLY, 0);
  518. if (fifo_write<0) {
  519. LOG(L_ERR, "SER: open_uac_fifo: fifo_write did not open: %s\n",
  520. strerror(errno));
  521. return -1;
  522. }
  523. return 1;
  524. }
  525. static int print_version_cmd( FILE *stream, char *response_file )
  526. {
  527. if (response_file) {
  528. fifo_reply(response_file, "200 ok\n" SERVER_HDR CRLF );
  529. } else {
  530. LOG(L_ERR, "ERROR: no file for print_version_cmd\n");
  531. }
  532. return 1;
  533. }
  534. /* diagnostic and hello-world FIFO command */
  535. static int print_fifo_cmd( FILE *stream, char *response_file )
  536. {
  537. char text[MAX_PRINT_TEXT];
  538. int text_len;
  539. /* expect one line which will be printed out */
  540. if (response_file==0 || *response_file==0 ) {
  541. LOG(L_ERR, "ERROR: print_fifo_cmd: null file\n");
  542. return -1;
  543. }
  544. if (!read_line(text, MAX_PRINT_TEXT, stream, &text_len)) {
  545. fifo_reply(response_file,
  546. "500 print_fifo_cmd: too big text");
  547. return -1;
  548. }
  549. /* now the work begins */
  550. if (response_file) {
  551. fifo_reply(response_file, "200 ok\n%s\n", text );
  552. } else {
  553. LOG(L_INFO, "INFO: print_fifo_cmd: %.*s\n",
  554. text_len, text );
  555. }
  556. return 1;
  557. }
  558. static int uptime_fifo_cmd( FILE *stream, char *response_file )
  559. {
  560. time_t now;
  561. if (response_file==0 || *response_file==0 ) {
  562. LOG(L_ERR, "ERROR: uptime_fifo_cmd: null file\n");
  563. return -1;
  564. }
  565. time(&now);
  566. fifo_reply( response_file, "200 ok\n"
  567. "Now: %sUp Since: %sUp time: %.0f [sec]\n",
  568. ctime(&now), up_since_ctime, difftime(now, up_since) );
  569. return 1;
  570. }
  571. static int which_fifo_cmd(FILE *stream, char *response_file )
  572. {
  573. FILE *reply_pipe;
  574. struct fifo_command *c;
  575. if (response_file==0 || *response_file==0 ) {
  576. LOG(L_ERR, "ERROR: which_fifo_cmd: null file\n");
  577. return -1;
  578. }
  579. reply_pipe=open_reply_pipe(response_file);
  580. if (reply_pipe==NULL) {
  581. LOG(L_ERR, "ERROR: which_fifo_cmd: opening reply pipe (%s) failed\n",
  582. response_file );
  583. return -1;
  584. }
  585. fputs( "200 ok\n", reply_pipe);
  586. for(c=cmd_list; c; c=c->next) {
  587. fprintf( reply_pipe, "%s\n", c->name );
  588. }
  589. fclose(reply_pipe);
  590. return 1;
  591. }
  592. static int ps_fifo_cmd(FILE *stream, char *response_file )
  593. {
  594. FILE *reply_pipe;
  595. int p;
  596. if (response_file==0 || *response_file==0 ) {
  597. LOG(L_ERR, "ERROR: ps_fifo_cmd: null file\n");
  598. return -1;
  599. }
  600. reply_pipe=open_reply_pipe(response_file);
  601. if (reply_pipe==NULL) {
  602. LOG(L_ERR, "ERROR: ps_fifo_cmd: opening reply pipe (%s) failed\n",
  603. response_file );
  604. return -1;
  605. }
  606. fputs( "200 ok\n", reply_pipe);
  607. for (p=0; p<process_count();p++)
  608. fprintf( reply_pipe, "%d\t%d\t%s\n",
  609. p, pt[p].pid, pt[p].desc );
  610. fclose(reply_pipe);
  611. return 1;
  612. }
  613. int register_core_fifo()
  614. {
  615. if (register_fifo_cmd(print_fifo_cmd, FIFO_PRINT, 0)<0) {
  616. LOG(L_CRIT, "unable to register '%s' FIFO cmd\n", FIFO_PRINT);
  617. return -1;
  618. }
  619. if (register_fifo_cmd(uptime_fifo_cmd, FIFO_UPTIME, 0)<0) {
  620. LOG(L_CRIT, "unable to register '%s' FIFO cmd\n", FIFO_UPTIME);
  621. return -1;
  622. }
  623. if (register_fifo_cmd(print_version_cmd, FIFO_VERSION, 0)<0) {
  624. LOG(L_CRIT, "unable to register '%s' FIFO cmd\n", FIFO_VERSION);
  625. return -1;
  626. }
  627. if (register_fifo_cmd(which_fifo_cmd, FIFO_WHICH, 0)<0) {
  628. LOG(L_CRIT, "unable to register '%s' FIFO cmd\n", FIFO_WHICH);
  629. return -1;
  630. }
  631. if (register_fifo_cmd(ps_fifo_cmd, FIFO_PS, 0)<0) {
  632. LOG(L_CRIT, "unable to register '%s' FIFO cmd\n", FIFO_PS);
  633. return -1;
  634. }
  635. return 1;
  636. }