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