1/* 2 * $Id: rend-unix.c,v 1.1 2009-06-30 02:31:09 steven Exp $ 3 * General unix rendezvous routines 4 * 5 * Copyright (C) 2003 Ron Pedde (ron@pedde.com) 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22#ifdef HAVE_CONFIG_H 23# include "config.h" 24#endif 25 26#include <errno.h> 27#include <restart.h> 28#include <signal.h> 29#include <stdio.h> 30#include <stdlib.h> 31#include <string.h> 32#include <unistd.h> 33 34#include "daapd.h" 35#include "err.h" 36#include "rend-unix.h" 37 38int rend_pipe_to[2]; 39int rend_pipe_from[2]; 40int rend_pid; 41 42#define RD_SIDE 0 43#define WR_SIDE 1 44 45/* 46 * rend_init 47 * 48 * Fork and set up message passing system 49 */ 50int rend_init(char *user) { 51 int err; 52 int fd; 53 54 if(pipe((int*)&rend_pipe_to) == -1) 55 return -1; 56 57 if(pipe((int*)&rend_pipe_from) == -1) { 58 err=errno; 59 close(rend_pipe_to[RD_SIDE]); 60 close(rend_pipe_to[WR_SIDE]); 61 errno=err; 62 return -1; 63 } 64 65 rend_pid=fork(); 66 if(rend_pid==-1) { 67 err=errno; 68 close(rend_pipe_to[RD_SIDE]); 69 close(rend_pipe_to[WR_SIDE]); 70 close(rend_pipe_from[RD_SIDE]); 71 close(rend_pipe_from[WR_SIDE]); 72 errno=err; 73 return -1; 74 } 75 76 if(rend_pid) { /* parent */ 77 close(rend_pipe_to[RD_SIDE]); 78 close(rend_pipe_from[WR_SIDE]); 79 return 0; 80 } 81 82 /* child */ 83 close(rend_pipe_to[WR_SIDE]); 84 close(rend_pipe_from[RD_SIDE]); 85 86 /* Depending on the backend, this might not get done on the 87 * rendezvous server-specific side 88 */ 89 signal(SIGTTOU, SIG_IGN); 90 signal(SIGTTIN, SIG_IGN); 91 signal(SIGTSTP, SIG_IGN); 92 93#ifdef SETPGRP_VOID 94 setpgrp(); 95#else 96 setpgrp(0,0); 97#endif 98 99#ifdef TIOCNOTTY 100 if ((fd = open("/dev/tty", O_RDWR)) >= 0) { 101 ioctl(fd, TIOCNOTTY, (char *) NULL); 102 close(fd); 103 } 104#endif 105 106 if((fd = open("/dev/null", O_RDWR, 0)) != -1) { 107 dup2(fd, STDIN_FILENO); 108 dup2(fd, STDOUT_FILENO); 109 dup2(fd, STDERR_FILENO); 110 if (fd > 2) 111 close(fd); 112 } 113 114 errno = 0; 115 116 chdir("/"); 117 umask(0); 118 119 /* something bad here... should really signal the parent, rather 120 * than just zombieizing 121 */ 122 rend_private_init(user); /* should only return when terminated */ 123 exit(0); 124} 125 126/* 127 * rend_running 128 * 129 * See if the rendezvous daemon is runnig 130 */ 131int rend_running(void) { 132 REND_MESSAGE msg; 133 int result; 134 135 DPRINTF(E_DBG,L_REND,"Status inquiry\n"); 136 memset((void*)&msg,0x00,sizeof(msg)); 137 msg.cmd=REND_MSG_TYPE_STATUS; 138 result=rend_send_message(&msg); 139 DPRINTF(E_DBG,L_REND,"Returning status %d\n",result); 140 return result; 141} 142 143/* 144 *rend_stop 145 * 146 * Stop the rendezvous server 147 */ 148int rend_stop(void) { 149 REND_MESSAGE msg; 150 151 msg.cmd=REND_MSG_TYPE_STOP; 152 return rend_send_message(&msg); 153} 154 155/* 156 * rend_register 157 * 158 * register a rendezvous name 159 */ 160int rend_register(char *name, char *type, int port) { 161 REND_MESSAGE msg; 162 163 if((strlen(name)+1 > MAX_NAME_LEN) || (strlen(type)+1 > MAX_NAME_LEN)) { 164 DPRINTF(E_FATAL,L_REND,"Registration failed: name or type too long\n"); 165 return -1; 166 } 167 168 memset((void*)&msg,0x00,sizeof(msg)); /* shut valgrind up */ 169 msg.cmd=REND_MSG_TYPE_REGISTER; 170 strcpy(msg.name,name); 171 strcpy(msg.type,type); 172 msg.port=port; 173 174 return rend_send_message(&msg); 175} 176 177/* 178 * rend_unregister 179 * 180 * Stop advertising a rendezvous name 181 */ 182int rend_unregister(char *name, char *type, int port) { 183 return -1; /* not implemented */ 184} 185 186/* 187 * rend_send_message 188 * 189 * Send a rendezvous message 190 */ 191int rend_send_message(REND_MESSAGE *pmsg) { 192 int retval; 193 194 if(r_write(rend_pipe_to[WR_SIDE],pmsg,sizeof(REND_MESSAGE)) == -1) 195 return -1; 196 197 if((retval=r_read(rend_pipe_from[RD_SIDE],&retval,sizeof(int)) == -1)) 198 return -1; 199 200 return retval; 201} 202 203/* 204 * rend_read_message 205 * 206 * read the message passed to the rend daemon 207 */ 208int rend_read_message(REND_MESSAGE *pmsg) { 209 return r_read(rend_pipe_to[RD_SIDE],pmsg,sizeof(REND_MESSAGE)); 210} 211 212/* 213 * rend_send_response 214 * 215 * Let the rendezvous daemon return a result 216 */ 217int rend_send_response(int value) { 218 return r_write(rend_pipe_from[WR_SIDE],&value,sizeof(int)); 219} 220