- Modules can properly register processes in SER process table
[sip-router] / fifo_server.c
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  *    info@iptel.org
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  * History:
55  * --------
56  *  2003-03-29  destroy pkg mem introduced (jiri)
57  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
58  *  2003-01-29  new built-in fifo commands: arg and pwd (jiri)
59  *  2003-10-07  fifo security fixes: permissions, always delete old fifo,
60  *               reply fifo checks -- added fifo_check (andrei)
61  *  2003-10-13  added fifo_dir for reply fifos (andrei)
62  *  2003-10-30  DB interface exported via FIFO (bogdan)
63  *  2004-03-09  open_fifo_server split into init_ and start_ (andrei)
64  *  2004-04-29  added chown(sock_user, sock_group)  (andrei)
65  *  2004-06-06  updated to the new DB interface  & init_db_fifo (andrei)
66  *  2004-09-19  fifo is deleted on exit (destroy_fifo)  (andrei)
67  *  2005-03-02  meminfo fifo cmd added (andrei)
68  */
69
70
71 #include <limits.h>
72 #include <stdlib.h>
73 #include <sys/types.h>
74 #include <unistd.h>
75 #include <stdio.h>
76 #include <errno.h>
77 #include <sys/stat.h>
78 #include <fcntl.h>
79 #include <signal.h>
80 #include <string.h>
81 #include <time.h>
82 #include <stdarg.h>
83 #ifdef USE_TCP
84 #include <sys/socket.h>
85 #endif
86
87 #include "dprint.h"
88 #include "ut.h"
89 #include "error.h"
90 #include "config.h"
91 #include "globals.h"
92 #include "fifo_server.h"
93 #include "mem/mem.h"
94 #include "mem/shm_mem.h" /* shm_info() */
95 #include "sr_module.h"
96 #include "pt.h"
97 #include "db/db_fifo.h"
98
99 /* FIFO server vars */
100 char *fifo=0; /* FIFO name */
101 char* fifo_dir=DEFAULT_FIFO_DIR; /* dir where reply fifos are allowed */
102 char *fifo_db_url = 0;
103 pid_t fifo_pid;
104
105
106 /* file descriptors */
107 static int fifo_read=0;
108 static int fifo_write=0;
109 static FILE *fifo_stream=0;
110
111 /* list of fifo command */
112 static struct fifo_command *cmd_list=0;
113
114 /* up time */
115 static time_t up_since;
116 static char up_since_ctime[MAX_CTIME_LEN];
117
118 static struct fifo_command *lookup_fifo_cmd( char *name )
119 {
120         struct fifo_command *c;
121         for(c=cmd_list; c; c=c->next) {
122                 if (strcasecmp(c->name, name)==0) return c;
123         }
124         return 0;
125 }
126
127 int register_fifo_cmd(fifo_cmd f, char *cmd_name, void *param)
128 {
129         struct fifo_command *new_cmd;
130
131         if (lookup_fifo_cmd(cmd_name)) {
132                 LOG(L_ERR, "ERROR: register_fifo_cmd: attempt to register synonyms\n");
133                 return E_BUG;
134         }
135         new_cmd=pkg_malloc(sizeof(struct fifo_command));
136         if (new_cmd==0) {
137                 LOG(L_ERR, "ERROR: register_fifo_cmd: out of mem\n");
138                 return E_OUT_OF_MEM;
139         }
140         new_cmd->f=f;
141         new_cmd->name=cmd_name;
142         new_cmd->param=param;
143
144         new_cmd->next=cmd_list;
145         cmd_list=new_cmd;
146         
147         DBG("DEBUG: register_fifo_cmd: new command (%s) registered\n", cmd_name );
148
149         return 1;
150 }
151
152 void destroy_fifo()
153 {
154         struct fifo_command *c, *foo;
155
156         c=cmd_list;
157
158         while(c) {
159                 foo=c->next;
160                 pkg_free(c);
161                 c=foo;
162         }
163         if (fifo_stream){
164                         fclose(fifo_stream);
165                         fifo_stream=0;
166                 /* if  FIFO was created, delete it */
167                 if (fifo && strlen(fifo)){
168                         if (unlink(fifo)<0){
169                                 LOG(L_ERR, "WARNING: destroy_fifo: cannot delete fifo (%s):"
170                                                         " %s\n", fifo, strerror(errno));
171                         }
172                 }
173         }
174 }
175
176
177 int read_line( char *b, int max, FILE *stream, int *read )
178 {
179         int len;
180         int retry_cnt;
181
182         retry_cnt=0;
183
184 retry:
185         if (fgets(b, max, stream)==NULL) {
186                 LOG(L_ERR, "ERROR: fifo_server fgets failed: %s\n",
187                         strerror(errno));
188                 /* on Linux, fgets sometimes returns ESPIPE -- give
189                    it few more chances
190                 */
191                 if (errno==ESPIPE) {
192                         retry_cnt++;
193                         if (retry_cnt<4) goto retry;
194                 }
195                 /* interrupted by signal or ... */
196                 if ((errno==EINTR)||(errno==EAGAIN)) goto retry;
197                 kill(0, SIGTERM);
198         }
199         /* if we did not read whole line, our buffer is too small
200            and we cannot process the request; consume the remainder of 
201            request
202         */
203         len=strlen(b);
204         if (len && !(b[len-1]=='\n' || b[len-1]=='\r')) {
205                 LOG(L_ERR, "ERROR: read_line: request  line too long\n");
206                 return 0;
207         }
208         /* trim from right */
209         while(len) {
210                 if(b[len-1]=='\n' || b[len-1]=='\r'
211                                 || b[len-1]==' ' || b[len-1]=='\t' ) {
212                         len--;
213                         b[len]=0;
214                 } else break;
215         }
216         *read=len;
217         return 1;
218 }
219
220 static void consume_request( FILE *stream )
221 {
222         int len;
223         char buffer[MAX_CONSUME_BUFFER];
224
225         while(!read_line(buffer, MAX_CONSUME_BUFFER, stream, &len));
226
227 }
228
229 int read_eol( FILE *stream )
230 {
231         int len;
232         char buffer[MAX_CONSUME_BUFFER];
233         if (!read_line(buffer, MAX_CONSUME_BUFFER, stream, &len) || len!=0) {
234                 LOG(L_ERR, "ERROR: read_eol: EOL expected: %.10s...\n",
235                         buffer );
236                 return 0;
237         }
238         return 1;
239 }
240
241 /* read from input until empty line is encountered */   
242 int read_line_set(char *buf, int max_len, FILE *fifo, int *len)
243 {
244         int set_len;
245         char *c;
246         int line_len;
247
248         c=buf;set_len=0;
249         while(1) {
250                 if (!read_line(c,max_len,fifo,&line_len)) {
251                         LOG(L_ERR, "ERROR: fifo_server: line expected\n");
252                         return 0;
253                 }
254                 /* end encountered ... return */
255                 if (line_len==0 || (line_len==1 && c[0]=='.' )) {
256                         *len=set_len;
257                         return 1;
258                 }
259                 max_len-=line_len; c+=line_len; set_len+=line_len;
260                 if (max_len<CRLF_LEN) {
261                         LOG(L_ERR, "ERROR: fifo_server: no place for CRLF\n");
262                         return 0;
263                 }
264                 memcpy(c, CRLF, CRLF_LEN);
265                 max_len-=CRLF_LEN; c+=CRLF_LEN; set_len+=CRLF_LEN;
266         }
267 }
268
269
270 /* read from input until line with only dot in it is encountered */
271 int read_body(char *buf, int max_len, FILE *fifo, int *len)
272 {
273         int set_len;
274         char *c;
275         int line_len;
276
277         c=buf;set_len=0;
278         while(1) {
279                 if (!read_line(c,max_len,fifo,&line_len)) {
280                         LOG(L_ERR, "ERROR: fifo_server: line expected\n");
281                         return 0;
282                 }
283                 /* end encountered ... return */
284                 if (line_len==1 && *c=='.') {
285                         *len=set_len;
286                         return 1;
287                 }
288                 max_len-=line_len; c+=line_len; set_len+=line_len;
289                 if (max_len<CRLF_LEN) {
290                         LOG(L_ERR, "ERROR: fifo_server: no place for CRLF\n");
291                         return 0;
292                 }
293                 memcpy(c, CRLF, CRLF_LEN);
294                 max_len-=CRLF_LEN; c+=CRLF_LEN; set_len+=CRLF_LEN;
295         }
296 }
297
298 static char *trim_filename( char * file )
299 {
300         int prefix_len, fn_len;
301         char *new_fn;
302
303         /* we only allow files in "/tmp" -- any directory
304            changes are not welcome
305         */
306         if (strchr(file,'.') || strchr(file,'/')
307                                 || strchr(file, '\\')) {
308                 LOG(L_ERR, "ERROR: trim_filename: forbidden filename: %s\n"
309                         , file);
310                 return 0;
311         }
312         prefix_len=strlen(fifo_dir); fn_len=strlen(file);
313         new_fn=pkg_malloc(prefix_len+fn_len+1);
314         if (new_fn==0) {
315                 LOG(L_ERR, "ERROR: trim_filename: no mem\n");
316                 return 0;
317         }
318
319         memcpy(new_fn, fifo_dir, prefix_len);
320         memcpy(new_fn+prefix_len, file, fn_len );
321         new_fn[prefix_len+fn_len]=0;
322
323         return new_fn;
324 }
325
326
327
328 /* reply fifo security checks:
329  * checks if fd is a fifo, is not hardlinked and it's not a softlink
330  * opened file descriptor + file name (for soft link check)
331  * returns 0 if ok, <0 if not */
332 static int fifo_check(int fd, char* fname)
333 {
334         struct stat fst;
335         struct stat lst;
336         
337         if (fstat(fd, &fst)<0){
338                 LOG(L_ERR, "ERROR: fifo_check: fstat failed: %s\n",
339                                 strerror(errno));
340                 return -1;
341         }
342         /* check if fifo */
343         if (!S_ISFIFO(fst.st_mode)){
344                 LOG(L_ERR, "ERROR: fifo_check: %s is not a fifo\n", fname);
345                 return -1;
346         }
347         /* check if hard-linked */
348         if (fst.st_nlink>1){
349                 LOG(L_ERR, "ERROR: security: fifo_check: %s is hard-linked %d times\n",
350                                 fname, (unsigned)fst.st_nlink);
351                 return -1;
352         }
353         
354         /* lstat to check for soft links */
355         if (lstat(fname, &lst)<0){
356                 LOG(L_ERR, "ERROR: fifo_check: lstat failed: %s\n",
357                                 strerror(errno));
358                 return -1;
359         }
360         if (S_ISLNK(lst.st_mode)){
361                 LOG(L_ERR, "ERROR: security: fifo_check: %s is a soft link\n",
362                                 fname);
363                 return -1;
364         }
365         /* if this is not a symbolic link, check to see if the inode didn't
366          * change to avoid possible sym.link, rm sym.link & replace w/ fifo race
367          */
368         if ((lst.st_dev!=fst.st_dev)||(lst.st_ino!=fst.st_ino)){
369                 LOG(L_ERR, "ERROR: security: fifo_check: inode/dev number differ"
370                                 ": %d %d (%s)\n",
371                                  (int)fst.st_ino, (int)lst.st_ino, fname);
372                 return -1;
373         }
374         /* success */
375         return 0;
376 }
377
378
379
380 /* tell FIFO client what happened via reply pipe */
381 void fifo_reply( char *reply_fifo, char *reply_fmt, ... )
382 {
383         FILE *file_handle;
384         int r;
385         va_list ap;
386
387         file_handle=open_reply_pipe(reply_fifo);
388         if (file_handle==0) {
389                 LOG(L_ERR, "ERROR: fifo_reply: no reply pipe %s\n",
390                         reply_fifo);
391                 return;
392         }
393 retry:
394         va_start(ap, reply_fmt);
395         r=vfprintf(file_handle, reply_fmt, ap);
396         va_end(ap);
397         if (r<=0) {
398                 LOG(L_ERR, "ERROR: fifo_error: write error (%s): %s\n",
399                         fifo, strerror(errno));
400                 if ((errno==EINTR)||(errno==EAGAIN)||(errno==EWOULDBLOCK)) {
401                         goto retry;
402                 }
403         }
404         fclose(file_handle);
405 }
406
407 FILE *open_reply_pipe( char *pipe_name )
408 {
409
410         int fifofd;
411         FILE *file_handle;
412         int flags;
413
414         int retries=FIFO_REPLY_RETRIES;
415
416         if (!pipe_name || *pipe_name==0) {
417                 DBG("DEBUG: open_reply_pipe: no file to write to about missing cmd\n");
418                 return 0;
419         }
420
421 tryagain:
422         /* open non-blocking to make sure that a broken client will not 
423          * block the FIFO server forever */
424         fifofd=open( pipe_name, O_WRONLY | O_NONBLOCK );
425         if (fifofd==-1) {
426                 /* retry several times if client is not yet ready for getting
427                    feedback via a reply pipe
428                 */
429                 if (errno==ENXIO) {
430                         /* give up on the client - we can't afford server blocking */
431                         if (retries==0) {
432                                 LOG(L_ERR, "ERROR: open_reply_pipe: no client at %s\n",
433                                         pipe_name );
434                                 return 0;
435                         }
436                         /* don't be noisy on the very first try */
437                         if (retries!=FIFO_REPLY_RETRIES)
438                                 DBG("DEBUG: open_reply_pipe: retry countdown: %d\n", retries );
439                         sleep_us( FIFO_REPLY_WAIT );
440                         retries--;
441                         goto tryagain;
442                 }
443                 /* some other opening error */
444                 LOG(L_ERR, "ERROR: open_reply_pipe: open error (%s): %s\n",
445                         pipe_name, strerror(errno));
446                 return 0;
447         }
448         /* security checks: is this really a fifo?, is 
449          * it hardlinked? is it a soft link? */
450         if (fifo_check(fifofd, pipe_name)<0) goto error;
451         
452         /* we want server blocking for big writes */
453         if ( (flags=fcntl(fifofd, F_GETFL, 0))<0) {
454                 LOG(L_ERR, "ERROR: open_reply_pipe (%s): getfl failed: %s\n",
455                         pipe_name, strerror(errno));
456                 goto error;
457         }
458         flags&=~O_NONBLOCK;
459         if (fcntl(fifofd, F_SETFL, flags)<0) {
460                 LOG(L_ERR, "ERROR: open_reply_pipe (%s): setfl cntl failed: %s\n",
461                         pipe_name, strerror(errno));
462                 goto error;
463         }
464
465         /* create an I/O stream */      
466         file_handle=fdopen( fifofd, "w");
467         if (file_handle==NULL) {
468                 LOG(L_ERR, "ERROR: open_reply_pipe: open error (%s): %s\n",
469                         pipe_name, strerror(errno));
470                 goto error;
471         }
472         return file_handle;
473 error:
474         close(fifofd);
475         return 0;
476 }
477
478 static void fifo_server(FILE *fifo_stream)
479 {
480         char buf[MAX_FIFO_COMMAND];
481         int line_len;
482         char *file_sep, *command, *file;
483         struct fifo_command *f;
484
485         file_sep=command=file=0;
486
487         /* register a diagnostic FIFO command */
488         register_core_fifo();
489
490         while(1) {
491
492                 /* commands must look this way ':<command>:[filename]' */
493                 if (!read_line(buf, MAX_FIFO_COMMAND, fifo_stream, &line_len)) {
494                         /* line breaking must have failed -- consume the rest
495                            and proceed to a new request
496                         */
497                         LOG(L_ERR, "ERROR: fifo_server: command expected\n");
498                         goto consume;
499                 }
500                 if (line_len==0) {
501                         LOG(L_DBG, "INFO: fifo_server: command empty\n");
502                         continue;
503                 }
504                 if (line_len<3) {
505                         LOG(L_ERR, "ERROR: fifo_server: command must have at least 3 chars\n");
506                         goto consume;
507                 }
508                 if (*buf!=CMD_SEPARATOR) {
509                         LOG(L_ERR, "ERROR: fifo_server: command must begin with %c: %.*s\n", 
510                                 CMD_SEPARATOR, line_len, buf );
511                         goto consume;
512                 }
513                 command=buf+1;
514                 file_sep=strchr(command, CMD_SEPARATOR );
515                 if (file_sep==NULL) {
516                         LOG(L_ERR, "ERROR: fifo_server: file separator missing\n");
517                         goto consume;
518                 }
519                 if (file_sep==command) {
520                         LOG(L_ERR, "ERROR: fifo_server: empty command\n");
521                         goto consume;
522                 }
523                 if (*(file_sep+1)==0) file=NULL; 
524                 else {
525                         file=file_sep+1;
526                         file=trim_filename(file);
527                         if (file==0) {
528                                 LOG(L_ERR, "ERROR: fifo_server: trimming filename\n");
529                                 goto consume;
530                         }
531                 }
532                 /* make command zero-terminated */
533                 *file_sep=0;
534
535                 f=lookup_fifo_cmd( command );
536                 if (f==0) {
537                         LOG(L_ERR, "ERROR: fifo_server: command %s is not available\n",
538                                 command);
539                         fifo_reply(file, "500 command '%s' not available\n", command);
540                         goto consume;
541                 }
542                 if (f->f(fifo_stream, file)<0) {
543                         LOG(L_ERR, "ERROR: fifo_server: command (%s) "
544                                 "processing failed\n", command );
545                         goto consume;
546                 }
547
548 consume:
549                 if (file) { pkg_free(file); file=0;}
550                 consume_request(fifo_stream);
551                 DBG("**** done consume\n");
552         }
553 }
554
555 int init_fifo_server()
556 {
557         char *t;
558         struct stat filestat;
559         int n;
560         long opt;
561
562         if (fifo==NULL) {
563                 DBG("DBG: open_fifo_server: no fifo will be opened\n");
564                 /* everything is ok, we just do not want to start */
565                 return 1;
566         }
567         if (strlen(fifo)==0) {
568                 DBG("DBG: open_fifo_server: fifo disabled\n");
569                 return 1;
570         }
571         DBG("DBG: open_uac_fifo: opening fifo...\n");
572         n=stat(fifo, &filestat);
573         if (n==0){
574                 /* FIFO exist, delete it (safer) */
575                 if (unlink(fifo)<0){
576                         LOG(L_ERR, "ERROR: open_fifo_server: cannot delete old fifo (%s):"
577                                         " %s\n", fifo, strerror(errno));
578                         return -1;
579                 }
580         }else if (n<0 && errno!=ENOENT){
581                 LOG(L_DBG, "DEBUG: open_fifo_server: FIFO stat failed: %s\n",
582                         strerror(errno));
583         }
584                 /* create FIFO ... */
585                 if ((mkfifo(fifo, sock_mode)<0)) {
586                         LOG(L_ERR, "ERROR: open_fifo_server; can't create FIFO: "
587                                         "%s (mode=%d)\n",
588                                         strerror(errno), sock_mode);
589                         return -1;
590                 } 
591                 DBG("DEBUG: FIFO created @ %s\n", fifo );
592                 if ((chmod(fifo, sock_mode)<0)) {
593                         LOG(L_ERR, "ERROR: open_fifo_server; can't chmod FIFO: "
594                                         "%s (mode=%d)\n",
595                                         strerror(errno), sock_mode);
596                         return -1;
597                 }
598                 if ((sock_uid!=-1) || (sock_gid!=-1)){
599                         if (chown(fifo, sock_uid, sock_gid)<0){
600                         LOG(L_ERR, "ERROR: open_fifo_server: failed to change the"
601                                         " owner/group for %s  to %d.%d; %s[%d]\n",
602                                         fifo, sock_uid, sock_gid, strerror(errno), errno);
603                         return -1;
604                 }
605         }
606
607                 
608         DBG("DEBUG: fifo %s opened, mode=%d\n", fifo, sock_mode );
609         time(&up_since);
610         t=ctime(&up_since);
611         if (strlen(t)+1>=MAX_CTIME_LEN) {
612                 LOG(L_ERR, "ERROR: open_fifo_server: "
613                         "too long date %d\n", (int)strlen(t));
614                 return -1;
615         }
616         memcpy(up_since_ctime,t,strlen(t)+1);
617         /* open it non-blocking or else wait here until someone
618          * opens it for writing */
619         fifo_read=open(fifo, O_RDONLY|O_NONBLOCK, 0);
620         if (fifo_read<0) {
621                 LOG(L_ERR, "ERROR: init_fifo_server: fifo_read did not open: %s\n",
622                         strerror(errno));
623                 return -1;
624         }
625         fifo_stream=fdopen(fifo_read, "r");
626         if (fifo_stream==NULL) {
627                 LOG(L_ERR, "ERROR: init_fifo_server: fdopen failed: %s\n",
628                         strerror(errno));
629                 return -1;
630         }
631         /* make sure the read fifo will not close */
632         fifo_write=open(fifo, O_WRONLY|O_NONBLOCK, 0);
633         if (fifo_write<0) {
634                 LOG(L_ERR, "ERROR: init_fifo_server: fifo_write did not open: %s\n",
635                         strerror(errno));
636                 return -1;
637         }
638         /* set read fifo blocking mode */
639         if ((opt=fcntl(fifo_read, F_GETFL))==-1){
640                 LOG(L_ERR, "ERROR: init_fifo_server: fcntl(F_GETFL) failed: %s [%d]\n",
641                                 strerror(errno), errno);
642                 return -1;
643         }
644         if (fcntl(fifo_read, F_SETFL, opt & (~O_NONBLOCK))==-1){
645                 LOG(L_ERR, "ERROR: init_fifo_server: fcntl(F_SETFL) failed: %s [%d]\n",
646                                 strerror(errno), errno);
647                 return -1;
648         }
649         return 0;
650 }
651
652
653
654 int start_fifo_server()
655 {
656 #ifdef USE_TCP
657         int sockfd[2];
658 #endif
659         if (fifo_stream==0) return 1; /* no error, we just don't start it */
660 #ifdef USE_TCP
661         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
662                         LOG(L_ERR, "ERROR: open_fifo_server: socketpair failed: %s\n",
663                                 strerror(errno));
664                         return -1;
665         }
666 #endif
667         process_no++;
668         fifo_pid=fork();
669         if (fifo_pid<0) {
670                 LOG(L_ERR, "ERROR: open_fifo_server: failure to fork: %s\n",
671                         strerror(errno));
672                 return -1;
673         }
674         if (fifo_pid==0) { /* child == FIFO server */
675                 /* record pid twice to avoid the child using it, before
676                  * parent gets a chance to set it*/
677                 pt[process_no].pid=getpid();
678                 LOG(L_INFO, "INFO: fifo process starting: %d\n", getpid());
679                 /* call per-child module initialization too -- some
680                    FIFO commands may need it
681                 */
682 #ifdef USE_TCP
683                 close(sockfd[0]);
684                 unix_tcp_sock=sockfd[1];
685 #endif
686                 if (init_child(PROC_FIFO) < 0 ) {
687                         LOG(L_ERR, "ERROR: open_uac_fifo: init_child failed\n");
688                         return -1;
689                 }
690                 /* a real server doesn't die if writing to reply fifo fails */
691                 signal(SIGPIPE, SIG_IGN);
692                 LOG(L_INFO, "SER: open_uac_fifo: fifo server up at %s...\n",
693                         fifo);
694                 fifo_server( fifo_stream ); /* never returns */
695         }
696         /* dad process */
697         pt[process_no].pid=fifo_pid;
698         strncpy(pt[process_no].desc, "fifo server", MAX_PT_DESC );
699 #ifdef USE_TCP
700         close(sockfd[1]);
701         pt[process_no].unix_sock=sockfd[0];
702         pt[process_no].idx=-1; /* this is not "tcp" process*/
703 #endif
704         return 1;
705 }
706
707 static int print_version_cmd( FILE *stream, char *response_file )
708 {
709         if (response_file) {
710                 fifo_reply(response_file, "200 ok\n" SERVER_HDR CRLF );
711         } else {
712                 LOG(L_ERR, "ERROR: no file for %s\n", "print_version_cmd" );
713         }
714         return 1;
715 }
716
717 static int pwd_cmd( FILE *stream, char *response_file )
718 {
719         char *cwd_buf;
720         int max_len;
721
722         if (!response_file) {
723                 LOG(L_ERR, "ERROR: no file for %s\n", "pwd_cmd" );
724                 return 1;
725         }
726
727         max_len=pathmax();
728         cwd_buf=pkg_malloc(max_len);
729         if (!cwd_buf) {
730                 LOG(L_ERR, "ERROR: pwd_cmd: no cwd pkg mem\n");
731                 fifo_reply(response_file, "500 no memory\n");
732                 return 1;
733         }
734
735         if (getcwd(cwd_buf, max_len)) {
736                 fifo_reply(response_file, "200 ok\n%s\n", cwd_buf );
737         } else {
738                 fifo_reply(response_file, "500 getcwd failed\n" );
739         }
740
741         pkg_free(cwd_buf);
742         return 1;
743 }
744
745 static int arg_cmd( FILE *stream, char *response_file )
746 {
747         FILE *reply_pipe;
748         int p;
749
750         if (response_file==0 || *response_file==0 ) {
751                  LOG(L_ERR, "ERROR: ps_fifo_cmd: null file\n");
752                 return -1;
753         }
754         reply_pipe=open_reply_pipe(response_file);
755         if (reply_pipe==NULL) {
756                 LOG(L_ERR, "ERROR: ps_fifo_cmd: opening reply pipe (%s) failed\n",
757                         response_file );
758                 return -1;
759         }
760
761         fputs( "200 ok\n", reply_pipe);
762         for (p=0; p<my_argc;p++) 
763                         fprintf( reply_pipe, "%s\n", my_argv[p] );
764                         
765         fclose(reply_pipe);
766         return 1;
767 }
768
769         
770
771 /* diagnostic and hello-world FIFO command */
772 static int print_fifo_cmd( FILE *stream, char *response_file )
773 {
774         char text[MAX_PRINT_TEXT];
775         int text_len;
776         
777         /* expect one line which will be printed out */
778         if (response_file==0 || *response_file==0 ) { 
779                 LOG(L_ERR, "ERROR: print_fifo_cmd: null file\n");
780                 return -1;
781         }
782         if (!read_line(text, MAX_PRINT_TEXT, stream, &text_len)) {
783                 fifo_reply(response_file, 
784                         "500 print_fifo_cmd: too big text");
785                 return -1;
786         }
787         /* now the work begins */
788         if (response_file) {
789                 fifo_reply(response_file, "200 ok\n%s\n", text );
790         } else {
791                 LOG(L_INFO, "INFO: print_fifo_cmd: %.*s\n", 
792                         text_len, text );
793         }
794         return 1;
795 }
796
797 static int uptime_fifo_cmd( FILE *stream, char *response_file )
798 {
799         time_t now;
800
801         if (response_file==0 || *response_file==0 ) { 
802                 LOG(L_ERR, "ERROR: uptime_fifo_cmd: null file\n");
803                 return -1;
804         }
805
806         time(&now);
807         fifo_reply( response_file, "200 ok\n"
808                 "Now: %sUp Since: %sUp time: %.0f [sec]\n",
809                 ctime(&now), up_since_ctime, difftime(now, up_since) );
810
811         return 1;
812 }
813
814 static int kill_fifo_cmd( FILE *stream, char *response_file )
815 {
816         if (response_file==0 || *response_file==0 ) { 
817                 LOG(L_ERR, "ERROR: uptime_fifo_cmd: null file\n");
818                 return -1;
819         }
820         fifo_reply(response_file, "200 killing now..." );
821         kill(0, SIGTERM);
822         return 1;
823 }
824
825 static int which_fifo_cmd(FILE *stream, char *response_file )
826 {
827         FILE *reply_pipe;
828         struct fifo_command *c;
829
830         if (response_file==0 || *response_file==0 ) {
831                  LOG(L_ERR, "ERROR: which_fifo_cmd: null file\n");
832                 return -1;
833         }
834
835         reply_pipe=open_reply_pipe(response_file);
836         if (reply_pipe==NULL) {
837                 LOG(L_ERR, "ERROR: which_fifo_cmd: opening reply pipe (%s) failed\n",
838                         response_file );
839                 return -1;
840         }
841         fputs( "200 ok\n", reply_pipe);
842         for(c=cmd_list; c; c=c->next) {
843                 fprintf( reply_pipe, "%s\n", c->name );
844         }
845
846         fclose(reply_pipe);
847         return 1;
848 }
849
850 static int ps_fifo_cmd(FILE *stream, char *response_file )
851 {
852         FILE *reply_pipe;
853         int p;
854
855         if (response_file==0 || *response_file==0 ) {
856                  LOG(L_ERR, "ERROR: ps_fifo_cmd: null file\n");
857                 return -1;
858         }
859         reply_pipe=open_reply_pipe(response_file);
860         if (reply_pipe==NULL) {
861                 LOG(L_ERR, "ERROR: ps_fifo_cmd: opening reply pipe (%s) failed\n",
862                         response_file );
863                 return -1;
864         }
865
866         fputs( "200 ok\n", reply_pipe);
867         for (p=0; p<process_count;p++) 
868                 fprintf( reply_pipe, "%d\t%d\t%s\n",
869                         p, pt[p].pid, pt[p].desc );
870
871         fclose(reply_pipe);
872         return 1;
873 }
874
875
876
877 static int meminfo_fifo_cmd( FILE *stream, char *response_file )
878 {
879         struct mem_info mi;
880         
881         if (response_file==0 || *response_file==0 ) { 
882                 LOG(L_ERR, "ERROR: meminfo_fifo_cmd: null file\n");
883                 return -1;
884         }
885         
886 #ifdef SHM_MEM
887         shm_info(&mi);
888         fifo_reply( response_file, "200 ok\n"
889                                         "total:%ld\n"
890                                         "free:%ld\n"
891                                         "used:%ld\n"
892                                         "max used:%ld\n"
893                                         "fragments:%ld\n",
894                                         mi.total_size, mi.free, mi.real_used,
895                                         mi.max_used, mi.total_frags);
896 #else
897         fifo_reply( response_file, "400 No shared memory support\n");
898 #endif
899
900         return 1;
901 }
902
903
904
905 int register_core_fifo()
906 {
907         if (register_fifo_cmd(print_fifo_cmd, FIFO_PRINT, 0)<0) {
908                 LOG(L_ERR, "ERROR: unable to register '%s' FIFO cmd\n", FIFO_PRINT);
909                 return -1;
910         }
911         if (register_fifo_cmd(uptime_fifo_cmd, FIFO_UPTIME, 0)<0) {
912                 LOG(L_ERR, "ERROR: unable to register '%s' FIFO cmd\n", FIFO_UPTIME);
913                 return -1;
914         }
915         if (register_fifo_cmd(print_version_cmd, FIFO_VERSION, 0)<0) {
916                 LOG(L_ERR, "ERROR: unable to register '%s' FIFO cmd\n",FIFO_VERSION);
917                 return -1;
918         }
919         if (register_fifo_cmd(pwd_cmd, FIFO_PWD, 0)<0) {
920                 LOG(L_ERR, "ERROR: unable to register '%s' FIFO cmd\n", FIFO_PWD);
921                 return -1;
922         }
923         if (register_fifo_cmd(arg_cmd, FIFO_ARG, 0)<0) {
924                 LOG(L_ERR, "ERROR: unable to register '%s' FIFO cmd\n", FIFO_ARG);
925                 return -1;
926         }
927         if (register_fifo_cmd(which_fifo_cmd, FIFO_WHICH, 0)<0) {
928                 LOG(L_ERR, "ERROR: unable to register '%s' FIFO cmd\n", FIFO_WHICH);
929                 return -1;
930         }
931         if (register_fifo_cmd(ps_fifo_cmd, FIFO_PS, 0)<0) {
932                 LOG(L_ERR, "ERROR: unable to register '%s' FIFO cmd\n", FIFO_PS);
933                 return -1;
934         }
935         if (register_fifo_cmd(kill_fifo_cmd, FIFO_KILL, 0)<0) {
936                 LOG(L_CRIT, "ERROR: unable to register '%s' FIFO cmd\n", FIFO_KILL);
937                 return -1;
938         }
939         if (register_fifo_cmd(meminfo_fifo_cmd, FIFO_MEMINFO, 0)<0) {
940                 LOG(L_CRIT, "ERROR: unable to register '%s' FIFO cmd\n", FIFO_MEMINFO);
941                 return -1;
942         }
943         if (fifo_db_url==0) {
944                 LOG(L_WARN,"WARNING: no fifo_db_url given - "
945                         "fifo DB commands disabled!\n");
946         } else if (init_db_fifo(fifo_db_url)<0){
947                 return -1;
948         }
949         return 1;
950 }