merge new-rend-branch
This commit is contained in:
parent
41021a3a94
commit
10f7ca1790
|
@ -29,7 +29,7 @@ endif
|
||||||
mt_daapd_SOURCES = main.c daapd.h rend.h uici.c uici.h webserver.c \
|
mt_daapd_SOURCES = main.c daapd.h rend.h uici.c uici.h webserver.c \
|
||||||
webserver.h configfile.c configfile.h err.c err.h restart.c restart.h \
|
webserver.h configfile.c configfile.h err.c err.h restart.c restart.h \
|
||||||
daap-proto.c daap-proto.h daap.c daap.h db-memory.c db-memory.h \
|
daap-proto.c daap-proto.h daap.c daap.h db-memory.c db-memory.h \
|
||||||
mp3-scanner.h mp3-scanner.c playlist.c playlist.h \
|
mp3-scanner.h mp3-scanner.c playlist.c playlist.h rend-unix.c rend-unix.h \
|
||||||
lexer.l parser.y $(RENDSRC) $(STRCASESTR) $(STRSEP)
|
lexer.l parser.y $(RENDSRC) $(STRCASESTR) $(STRSEP)
|
||||||
|
|
||||||
EXTRA_DIST = mdns/mDNS.c mdns/mDNSClientAPI.h mdns/mDNSDebug.h mdns/mDNSPosix.c \
|
EXTRA_DIST = mdns/mDNS.c mdns/mDNSClientAPI.h mdns/mDNSDebug.h mdns/mDNSPosix.c \
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
@ -51,7 +52,9 @@ void config_emit_ispage(WS_CONNINFO *pwsc, void *value, char *arg);
|
||||||
void config_emit_session_count(WS_CONNINFO *pwsc, void *value, char *arg);
|
void config_emit_session_count(WS_CONNINFO *pwsc, void *value, char *arg);
|
||||||
void config_emit_service_status(WS_CONNINFO *pwsc, void *value, char *arg);
|
void config_emit_service_status(WS_CONNINFO *pwsc, void *value, char *arg);
|
||||||
void config_emit_user(WS_CONNINFO *pwsc, void *value, char *arg);
|
void config_emit_user(WS_CONNINFO *pwsc, void *value, char *arg);
|
||||||
|
void config_emit_readonly(WS_CONNINFO *pwsc, void *value, char *arg);
|
||||||
void config_subst_stream(WS_CONNINFO *pwsc, int fd_src);
|
void config_subst_stream(WS_CONNINFO *pwsc, int fd_src);
|
||||||
|
int config_file_is_readonly(void);
|
||||||
int config_mutex_lock(void);
|
int config_mutex_lock(void);
|
||||||
int config_mutex_unlock(void);
|
int config_mutex_unlock(void);
|
||||||
|
|
||||||
|
@ -89,6 +92,7 @@ CONFIGELEMENT config_elements[] = {
|
||||||
{ 0,0,0,CONFIG_TYPE_SPECIAL,"session-count",(void*)NULL,config_emit_session_count },
|
{ 0,0,0,CONFIG_TYPE_SPECIAL,"session-count",(void*)NULL,config_emit_session_count },
|
||||||
{ 0,0,0,CONFIG_TYPE_SPECIAL,"service-status",(void*)NULL,config_emit_service_status },
|
{ 0,0,0,CONFIG_TYPE_SPECIAL,"service-status",(void*)NULL,config_emit_service_status },
|
||||||
{ 0,0,0,CONFIG_TYPE_SPECIAL,"user",(void*)NULL,config_emit_user },
|
{ 0,0,0,CONFIG_TYPE_SPECIAL,"user",(void*)NULL,config_emit_user },
|
||||||
|
{ 0,0,0,CONFIG_TYPE_SPECIAL,"readonly",(void*)NULL,config_emit_readonly },
|
||||||
{ -1,1,0,CONFIG_TYPE_STRING,NULL,NULL,NULL }
|
{ -1,1,0,CONFIG_TYPE_STRING,NULL,NULL,NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -240,7 +244,7 @@ void config_close(void) {
|
||||||
pce=config_elements;
|
pce=config_elements;
|
||||||
err=0;
|
err=0;
|
||||||
while((pce->config_element != -1)) {
|
while((pce->config_element != -1)) {
|
||||||
if((pce->config_element) && (pce->type == CONFIG_TYPE_STRING))
|
if((pce->config_element) && (pce->type == CONFIG_TYPE_STRING) && (*((char**)pce->var)))
|
||||||
free(*((char**)pce->var));
|
free(*((char**)pce->var));
|
||||||
pce++;
|
pce++;
|
||||||
}
|
}
|
||||||
|
@ -250,7 +254,32 @@ void config_close(void) {
|
||||||
* config_write
|
* config_write
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int config_write(CONFIG *pconfig) {
|
int config_write(WS_CONNINFO *pwsc) {
|
||||||
|
FILE *configfile;
|
||||||
|
char ctime_buf[27];
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
configfile=fopen(config.configfile,"w");
|
||||||
|
if(!configfile)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
now=time(NULL);
|
||||||
|
ctime_r(&now,ctime_buf);
|
||||||
|
fprintf(configfile,"#\n# mt-daapd.conf\n#\n");
|
||||||
|
fprintf(configfile,"# Edited: %s",ctime_buf);
|
||||||
|
fprintf(configfile,"# By: %s\n",ws_getvar(pwsc,"HTTP_USER"));
|
||||||
|
fprintf(configfile,"#\n");
|
||||||
|
|
||||||
|
fprintf(configfile,"web_root\t%s\n",ws_getvar(pwsc,"web_root"));
|
||||||
|
fprintf(configfile,"port\t\t%s\n",ws_getvar(pwsc,"port"));
|
||||||
|
fprintf(configfile,"admin_pw\t%s\n",ws_getvar(pwsc,"admin_pw"));
|
||||||
|
fprintf(configfile,"mp3_dir\t\t%s\n",ws_getvar(pwsc,"mp3_dir"));
|
||||||
|
fprintf(configfile,"servername\t%s\n",ws_getvar(pwsc,"servername"));
|
||||||
|
fprintf(configfile,"runas\t\t%s\n",ws_getvar(pwsc,"runas"));
|
||||||
|
fprintf(configfile,"playlist\t%s\n",ws_getvar(pwsc,"playlist"));
|
||||||
|
fprintf(configfile,"password\t%s\n",ws_getvar(pwsc,"password"));
|
||||||
|
|
||||||
|
fclose(configfile);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,22 +406,30 @@ void config_handler(WS_CONNINFO *pwsc) {
|
||||||
|
|
||||||
if(strcasecmp(pwsc->uri,"/config-update.html")==0) {
|
if(strcasecmp(pwsc->uri,"/config-update.html")==0) {
|
||||||
/* we need to update stuff */
|
/* we need to update stuff */
|
||||||
pw=ws_getvar(pwsc,"adminpw");
|
pw=ws_getvar(pwsc,"admin_pw");
|
||||||
if(pw) {
|
if(pw) {
|
||||||
if(config.adminpassword)
|
if(config.adminpassword)
|
||||||
free(config.adminpassword);
|
free(config.adminpassword);
|
||||||
config.adminpassword=strdup(pw);
|
config.adminpassword=strdup(pw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pw=ws_getvar(pwsc,"password");
|
||||||
|
if(pw) {
|
||||||
|
if(config.readpassword)
|
||||||
|
free(config.readpassword);
|
||||||
|
config.readpassword=strdup(pw);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!config_file_is_readonly()) {
|
||||||
|
DPRINTF(ERR_INFO,"Updating config file\n");
|
||||||
|
config_write(pwsc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pw=ws_getvar(pwsc,"action");
|
pw=ws_getvar(pwsc,"action");
|
||||||
if(pw) {
|
if(pw) {
|
||||||
if(strcasecmp(pw,"stopmdns")==0) {
|
/* ignore stopmdns and startmdns */
|
||||||
DPRINTF(ERR_INFO,"Stopping rendezvous daemon\n");
|
if (strcasecmp(pw,"stopdaap")==0) {
|
||||||
kill(config.rend_pid,SIGINT);
|
|
||||||
wait(&status);
|
|
||||||
} else if (strcasecmp(pw,"startmdns")==0) {
|
|
||||||
rend_init(&config.rend_pid,config.servername, config.port);
|
|
||||||
} else if (strcasecmp(pw,"stopdaap")==0) {
|
|
||||||
config.stop=1;
|
config.stop=1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,7 +463,8 @@ int config_auth(char *user, char *password) {
|
||||||
* write a simple string value to the connection
|
* write a simple string value to the connection
|
||||||
*/
|
*/
|
||||||
void config_emit_string(WS_CONNINFO *pwsc, void *value, char *arg) {
|
void config_emit_string(WS_CONNINFO *pwsc, void *value, char *arg) {
|
||||||
ws_writefd(pwsc,"%s",*((char**)value));
|
if(*((char**)value))
|
||||||
|
ws_writefd(pwsc,"%s",*((char**)value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -464,10 +502,8 @@ void config_emit_service_status(WS_CONNINFO *pwsc, void *value, char *arg) {
|
||||||
|
|
||||||
ws_writefd(pwsc,"<TR><TD>Rendezvous</TD>");
|
ws_writefd(pwsc,"<TR><TD>Rendezvous</TD>");
|
||||||
if(config.use_mdns) {
|
if(config.use_mdns) {
|
||||||
mdns_running=1;
|
mdns_running=!rend_running();
|
||||||
err=waitpid(config.rend_pid,&status,WNOHANG);
|
|
||||||
if(err == -1)
|
|
||||||
mdns_running=0;
|
|
||||||
if(mdns_running) {
|
if(mdns_running) {
|
||||||
html="<a href=\"config-update.html?action=stopmdns\">Stop MDNS responder</a>";
|
html="<a href=\"config-update.html?action=stopmdns\">Stop MDNS responder</a>";
|
||||||
} else {
|
} else {
|
||||||
|
@ -622,6 +658,33 @@ void config_emit_user(WS_CONNINFO *pwsc, void *value, char *arg) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* config_file_is_readonly
|
||||||
|
*
|
||||||
|
* See if the configfile is writable or not
|
||||||
|
*/
|
||||||
|
int config_file_is_readonly(void) {
|
||||||
|
FILE *fin;
|
||||||
|
|
||||||
|
fin=fopen(config.configfile,"r+");
|
||||||
|
if(!fin) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fin);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* config_emit_readonly
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void config_emit_readonly(WS_CONNINFO *pwsc, void *value, char *arg) {
|
||||||
|
if(config_file_is_readonly()) {
|
||||||
|
ws_writefd(pwsc,"READONLY");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* config_emit_include
|
* config_emit_include
|
||||||
*
|
*
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "webserver.h"
|
#include "webserver.h"
|
||||||
|
|
||||||
extern int config_read(char *file);
|
extern int config_read(char *file);
|
||||||
extern int config_write(CONFIG *pconfig);
|
extern int config_write(WS_CONNINFO *pwsc);
|
||||||
extern int config_auth(char *user, char *password);
|
extern int config_auth(char *user, char *password);
|
||||||
extern void config_handler(WS_CONNINFO *pwsc);
|
extern void config_handler(WS_CONNINFO *pwsc);
|
||||||
extern void config_set_status(WS_CONNINFO *pwsc, int session, char *fmt, ...);
|
extern void config_set_status(WS_CONNINFO *pwsc, int session, char *fmt, ...);
|
||||||
|
|
|
@ -30,7 +30,6 @@ typedef struct tag_songentry {
|
||||||
} SONGENTRY;
|
} SONGENTRY;
|
||||||
|
|
||||||
typedef struct tag_config {
|
typedef struct tag_config {
|
||||||
pid_t rend_pid;
|
|
||||||
int use_mdns;
|
int use_mdns;
|
||||||
int stop;
|
int stop;
|
||||||
char *configfile;
|
char *configfile;
|
||||||
|
@ -48,4 +47,7 @@ typedef struct tag_config {
|
||||||
|
|
||||||
extern CONFIG config;
|
extern CONFIG config;
|
||||||
|
|
||||||
|
/* Forwards */
|
||||||
|
extern drop_privs(char *user);
|
||||||
|
|
||||||
#endif /* _DAAPD_H_ */
|
#endif /* _DAAPD_H_ */
|
||||||
|
|
67
src/main.c
67
src/main.c
|
@ -373,6 +373,39 @@ void usage(char *program) {
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* drop_privs
|
||||||
|
*
|
||||||
|
* drop privs to a specific user
|
||||||
|
*/
|
||||||
|
int drop_privs(char *user) {
|
||||||
|
int err;
|
||||||
|
struct passwd *pw=NULL;
|
||||||
|
|
||||||
|
/* drop privs */
|
||||||
|
if(getuid() == (uid_t)0) {
|
||||||
|
pw=getpwnam(config.runas);
|
||||||
|
if(pw) {
|
||||||
|
if(initgroups(user,pw->pw_gid) != 0 ||
|
||||||
|
setgid(pw->pw_gid) != 0 ||
|
||||||
|
setuid(pw->pw_uid) != 0) {
|
||||||
|
err=errno;
|
||||||
|
fprintf(stderr,"Couldn't change to %s, gid=%d, uid=%d\n",
|
||||||
|
user,pw->pw_gid, pw->pw_uid);
|
||||||
|
errno=err;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err=errno;
|
||||||
|
fprintf(stderr,"Couldn't lookup user %s\n",user);
|
||||||
|
errno=err;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
int option;
|
int option;
|
||||||
char *configfile=DEFAULT_CONFIGFILE;
|
char *configfile=DEFAULT_CONFIGFILE;
|
||||||
|
@ -384,7 +417,6 @@ int main(int argc, char *argv[]) {
|
||||||
int parseonly=0;
|
int parseonly=0;
|
||||||
int foreground=0;
|
int foreground=0;
|
||||||
config.use_mdns=1;
|
config.use_mdns=1;
|
||||||
struct passwd *pw=NULL;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
char *optval="d:c:mpf";
|
char *optval="d:c:mpf";
|
||||||
|
@ -443,26 +475,18 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
if((config.use_mdns) && (!parseonly)) {
|
if((config.use_mdns) && (!parseonly)) {
|
||||||
fprintf(stderr,"Starting rendezvous daemon\n");
|
fprintf(stderr,"Starting rendezvous daemon\n");
|
||||||
rend_init(&config.rend_pid,config.servername, config.port, config.runas);
|
if(rend_init(config.runas)) {
|
||||||
}
|
perror("rend_init");
|
||||||
|
|
||||||
/* drop privs */
|
|
||||||
if(getuid() == (uid_t)0) {
|
|
||||||
pw=getpwnam(config.runas);
|
|
||||||
if(pw) {
|
|
||||||
if(initgroups(config.runas,pw->pw_gid) != 0 ||
|
|
||||||
setgid(pw->pw_gid) != 0 ||
|
|
||||||
setuid(pw->pw_uid) != 0) {
|
|
||||||
fprintf(stderr,"Couldn't change to %s, gid=%d, uid=%d\n",
|
|
||||||
config.runas,pw->pw_gid, pw->pw_uid);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr,"Couldn't lookup user %s\n",config.runas);
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drop privs here
|
||||||
|
if(drop_privs(config.runas)) {
|
||||||
|
perror("drop_privs");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTF(ERR_DEBUG,"Initializing database\n");
|
DPRINTF(ERR_DEBUG,"Initializing database\n");
|
||||||
|
|
||||||
/* Initialize the database before starting */
|
/* Initialize the database before starting */
|
||||||
|
@ -512,6 +536,12 @@ int main(int argc, char *argv[]) {
|
||||||
ws_registerhandler(server,"^/logout$",daap_handler,daap_auth,0);
|
ws_registerhandler(server,"^/logout$",daap_handler,daap_auth,0);
|
||||||
ws_registerhandler(server,"^/databases/.*",daap_handler,daap_auth,0);
|
ws_registerhandler(server,"^/databases/.*",daap_handler,daap_auth,0);
|
||||||
|
|
||||||
|
if(config.use_mdns) { /* register services */
|
||||||
|
DPRINTF(ERR_DEBUG,"Registering rendezvous names\n");
|
||||||
|
rend_register(config.servername,"_daap._tcp",config.port);
|
||||||
|
rend_register(config.servername,"_http._tcp",config.port);
|
||||||
|
}
|
||||||
|
|
||||||
config.stop=0;
|
config.stop=0;
|
||||||
|
|
||||||
while(!config.stop)
|
while(!config.stop)
|
||||||
|
@ -519,8 +549,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
if(config.use_mdns) {
|
if(config.use_mdns) {
|
||||||
if(foreground) fprintf(stderr,"Killing rendezvous daemon\n");
|
if(foreground) fprintf(stderr,"Killing rendezvous daemon\n");
|
||||||
kill(config.rend_pid,SIGINT);
|
rend_stop();
|
||||||
wait(&status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(foreground) fprintf(stderr,"Stopping webserver\n");
|
if(foreground) fprintf(stderr,"Stopping webserver\n");
|
||||||
|
|
|
@ -261,7 +261,7 @@ int scan_init(char *path) {
|
||||||
int scan_foreground(char *path) {
|
int scan_foreground(char *path) {
|
||||||
MP3FILE mp3file;
|
MP3FILE mp3file;
|
||||||
DIR *current_dir;
|
DIR *current_dir;
|
||||||
struct dirent de;
|
char de[sizeof(struct dirent) + MAXNAMLEN + 1]; /* overcommit for solaris */
|
||||||
struct dirent *pde;
|
struct dirent *pde;
|
||||||
int err;
|
int err;
|
||||||
char mp3_path[PATH_MAX];
|
char mp3_path[PATH_MAX];
|
||||||
|
@ -276,9 +276,9 @@ int scan_foreground(char *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
pde=&de;
|
pde=(struct dirent *)&de;
|
||||||
|
|
||||||
err=readdir_r(current_dir,&de,&pde);
|
err=readdir_r(current_dir,(struct dirent *)de,&pde);
|
||||||
if(err == -1) {
|
if(err == -1) {
|
||||||
DPRINTF(ERR_DEBUG,"Error on readdir_r: %s\n",strerror(errno));
|
DPRINTF(ERR_DEBUG,"Error on readdir_r: %s\n",strerror(errno));
|
||||||
err=errno;
|
err=errno;
|
||||||
|
@ -290,28 +290,28 @@ int scan_foreground(char *path) {
|
||||||
if(!pde)
|
if(!pde)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(de.d_name[0] == '.') /* skip hidden and directories */
|
if(pde->d_name[0] == '.') /* skip hidden and directories */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
sprintf(mp3_path,"%s/%s",path,de.d_name);
|
sprintf(mp3_path,"%s/%s",path,pde->d_name);
|
||||||
DPRINTF(ERR_DEBUG,"Found %s\n",mp3_path);
|
DPRINTF(ERR_DEBUG,"Found %s\n",mp3_path);
|
||||||
if(stat(mp3_path,&sb)) {
|
if(stat(mp3_path,&sb)) {
|
||||||
DPRINTF(ERR_WARN,"Error statting: %s\n",strerror(errno));
|
DPRINTF(ERR_WARN,"Error statting: %s\n",strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sb.st_mode & S_IFDIR) { /* dir -- recurse */
|
if(sb.st_mode & S_IFDIR) { /* dir -- recurse */
|
||||||
DPRINTF(ERR_DEBUG,"Found dir %s... recursing\n",de.d_name);
|
DPRINTF(ERR_DEBUG,"Found dir %s... recursing\n",pde->d_name);
|
||||||
scan_foreground(mp3_path);
|
scan_foreground(mp3_path);
|
||||||
} else {
|
} else {
|
||||||
DPRINTF(ERR_DEBUG,"Processing file\n");
|
DPRINTF(ERR_DEBUG,"Processing file\n");
|
||||||
/* process the file */
|
/* process the file */
|
||||||
if(strlen(de.d_name) > 4) {
|
if(strlen(pde->d_name) > 4) {
|
||||||
if(strcasecmp(".m3u",(char*)&de.d_name[strlen(de.d_name) - 4]) == 0) {
|
if(strcasecmp(".m3u",(char*)&pde->d_name[strlen(pde->d_name) - 4]) == 0) {
|
||||||
/* we found an m3u file */
|
/* we found an m3u file */
|
||||||
|
|
||||||
DPRINTF(ERR_DEBUG,"Found m3u: %s\n",de.d_name);
|
DPRINTF(ERR_DEBUG,"Found m3u: %s\n",pde->d_name);
|
||||||
strcpy(m3u_path,de.d_name);
|
strcpy(m3u_path,pde->d_name);
|
||||||
m3u_path[strlen(de.d_name) - 4] = '\0';
|
m3u_path[strlen(pde->d_name) - 4] = '\0';
|
||||||
playlistid=sb.st_ino;
|
playlistid=sb.st_ino;
|
||||||
fd=open(mp3_path,O_RDONLY);
|
fd=open(mp3_path,O_RDONLY);
|
||||||
if(fd != -1) {
|
if(fd != -1) {
|
||||||
|
@ -344,13 +344,13 @@ int scan_foreground(char *path) {
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
} else if(strcasecmp(".mp3",(char*)&de.d_name[strlen(de.d_name) - 4]) == 0) {
|
} else if(strcasecmp(".mp3",(char*)&pde->d_name[strlen(pde->d_name) - 4]) == 0) {
|
||||||
/* we found an mp3 file */
|
/* we found an mp3 file */
|
||||||
DPRINTF(ERR_DEBUG,"Found mp3: %s\n",de.d_name);
|
DPRINTF(ERR_DEBUG,"Found mp3: %s\n",pde->d_name);
|
||||||
|
|
||||||
memset((void*)&mp3file,0,sizeof(mp3file));
|
memset((void*)&mp3file,0,sizeof(mp3file));
|
||||||
mp3file.path=mp3_path;
|
mp3file.path=mp3_path;
|
||||||
mp3file.fname=de.d_name;
|
mp3file.fname=pde->d_name;
|
||||||
|
|
||||||
#ifdef MAC /* wtf is this about? */
|
#ifdef MAC /* wtf is this about? */
|
||||||
mp3file.mtime=sb.st_mtimespec.tv_sec;
|
mp3file.mtime=sb.st_mtimespec.tv_sec;
|
||||||
|
@ -371,7 +371,7 @@ int scan_foreground(char *path) {
|
||||||
db_add(&mp3file);
|
db_add(&mp3file);
|
||||||
pl_eval(&mp3file);
|
pl_eval(&mp3file);
|
||||||
} else {
|
} else {
|
||||||
DPRINTF(ERR_INFO,"Skipping %s\n",de.d_name);
|
DPRINTF(ERR_INFO,"Skipping %s\n",pde->d_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
scan_freetags(&mp3file);
|
scan_freetags(&mp3file);
|
||||||
|
|
144
src/rend-howl.c
144
src/rend-howl.c
|
@ -26,9 +26,17 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <rendezvous/rendezvous.h>
|
#include <rendezvous/rendezvous.h>
|
||||||
#include <salt/log.h>
|
#include <salt/log.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#include "err.h"
|
#include "err.h"
|
||||||
|
#include "rend-unix.h"
|
||||||
|
|
||||||
|
pthread_t rend_tid;
|
||||||
|
sw_rendezvous rend_handle;
|
||||||
|
|
||||||
|
/* Forwards */
|
||||||
|
void *rend_pipe_monitor(void* arg);
|
||||||
|
void rend_callback(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rend_howl_reply
|
* rend_howl_reply
|
||||||
|
@ -53,57 +61,113 @@ static sw_result rend_howl_reply(sw_rendezvous_publish_handler handler,
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* public interface
|
* rend_private_init
|
||||||
|
*
|
||||||
|
* Initialize howl and start runloop
|
||||||
*/
|
*/
|
||||||
int rend_init(pid_t *pid, char *name, int port, char *user) {
|
int rend_private_init(char *user) {
|
||||||
sw_rendezvous rendezvous;
|
|
||||||
sw_result result;
|
sw_result result;
|
||||||
sw_rendezvous_publish_id daap_id;
|
|
||||||
sw_rendezvous_publish_id http_id;
|
|
||||||
struct passwd *pw=NULL;
|
|
||||||
|
|
||||||
/* drop privs */
|
|
||||||
if(getuid() == (uid_t)0) {
|
|
||||||
pw=getpwnam(user);
|
|
||||||
if(pw) {
|
|
||||||
if(initgroups(user,pw->pw_gid) != 0 ||
|
|
||||||
setgid(pw->pw_gid) != 0 ||
|
|
||||||
setuid(pw->pw_uid) != 0) {
|
|
||||||
fprintf(stderr,"Couldn't change to %s, gid=%d, uid=%d\n",
|
|
||||||
user,pw->pw_gid, pw->pw_uid);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr,"Couldn't lookup user %s\n",user);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(sw_rendezvous_init(&rendezvous) != SW_OKAY) {
|
DPRINTF(ERR_DEBUG,"Starting rendezvous services\n");
|
||||||
|
|
||||||
|
if(sw_rendezvous_init(&rend_handle) != SW_OKAY) {
|
||||||
DPRINTF(ERR_WARN,"Error initializing rendezvous\n");
|
DPRINTF(ERR_WARN,"Error initializing rendezvous\n");
|
||||||
errno=EINVAL;
|
errno=EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((result=sw_rendezvous_publish(rendezvous,name,"_daap._tcp",NULL,NULL,port,NULL,NULL,
|
if(drop_privs(user))
|
||||||
rend_howl_reply,NULL,&daap_id)) != SW_OKAY) {
|
|
||||||
DPRINTF(ERR_WARN,"Error registering DAAP server via mDNS: %d\n",result);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if((result=sw_rendezvous_publish(rendezvous,name,"_http._tcp",NULL,NULL,port,NULL,NULL,
|
DPRINTF(ERR_DEBUG,"Starting polling thread\n");
|
||||||
rend_howl_reply,NULL,&http_id)) != SW_OKAY) {
|
|
||||||
DPRINTF(ERR_WARN,"Error registering HTTP server via mDNS: %d\n",result);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pid=fork();
|
if(pthread_create(&rend_tid,NULL,rend_pipe_monitor,NULL)) {
|
||||||
if(*pid) {
|
DPRINTF(ERR_FATAL,"Could not start thread. Terminating\n");
|
||||||
return 0;
|
/* should kill parent, too */
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(ERR_DEBUG,"Registered rendezvous services\n");
|
DPRINTF(ERR_DEBUG,"Entering runloop\n");
|
||||||
sw_rendezvous_run(rendezvous);
|
|
||||||
|
sw_rendezvous_run(rend_handle);
|
||||||
|
|
||||||
|
DPRINTF(ERR_DEBUG,"Exiting runloop\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_pipe_monitor
|
||||||
|
*/
|
||||||
|
void *rend_pipe_monitor(void* arg) {
|
||||||
|
fd_set rset;
|
||||||
|
struct timeval tv;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
DPRINTF(ERR_DEBUG,"Waiting for data\n");
|
||||||
|
FD_ZERO(&rset);
|
||||||
|
FD_SET(rend_pipe_to[RD_SIDE],&rset);
|
||||||
|
|
||||||
|
/* sit in a select spin until there is data on the to fd */
|
||||||
|
while(((result=select(rend_pipe_to[RD_SIDE] + 1,&rset,NULL,NULL,NULL)) != -1) &&
|
||||||
|
errno != EINTR) {
|
||||||
|
if(FD_ISSET(rend_pipe_to[RD_SIDE],&rset)) {
|
||||||
|
DPRINTF(ERR_DEBUG,"Received a message from daap server\n");
|
||||||
|
rend_callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTF(ERR_DEBUG,"Select error!\n");
|
||||||
|
/* should really bail here */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_callback
|
||||||
|
*
|
||||||
|
* This gets called from the main thread when there is a
|
||||||
|
* message waiting to be processed.
|
||||||
|
*/
|
||||||
|
void rend_callback(void) {
|
||||||
|
REND_MESSAGE msg;
|
||||||
|
sw_rendezvous_publish_id rend_id;
|
||||||
|
sw_result result;
|
||||||
|
|
||||||
|
/* here, we've seen the message, now we have to process it */
|
||||||
|
|
||||||
|
if(rend_read_message(&msg) != sizeof(msg)) {
|
||||||
|
DPRINTF(ERR_FATAL,"Error reading rendezvous message\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(msg.cmd) {
|
||||||
|
case REND_MSG_TYPE_REGISTER:
|
||||||
|
DPRINTF(ERR_DEBUG,"Registering %s.%s (%d)\n",msg.type,msg.name,msg.port);
|
||||||
|
if((result=sw_rendezvous_publish(rend_handle,msg.name,msg.type,NULL,NULL,msg.port,NULL,0,
|
||||||
|
NULL,rend_howl_reply,NULL,&rend_id)) != SW_OKAY) {
|
||||||
|
DPRINTF(ERR_WARN,"Error registering name\n");
|
||||||
|
rend_send_response(-1);
|
||||||
|
} else {
|
||||||
|
rend_send_response(0); /* success */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REND_MSG_TYPE_UNREGISTER:
|
||||||
|
DPRINTF(ERR_WARN,"Unsupported function: UNREGISTER\n");
|
||||||
|
rend_send_response(-1); /* error */
|
||||||
|
break;
|
||||||
|
case REND_MSG_TYPE_STOP:
|
||||||
|
DPRINTF(ERR_DEBUG,"Stopping mDNS\n");
|
||||||
|
rend_send_response(0);
|
||||||
|
//sw_rendezvous_stop_publish(rend_handle);
|
||||||
|
sw_rendezvous_fina(rend_handle);
|
||||||
|
break;
|
||||||
|
case REND_MSG_TYPE_STATUS:
|
||||||
|
DPRINTF(ERR_DEBUG,"Status inquiry -- returning 0\n");
|
||||||
|
rend_send_response(0); /* success */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
160
src/rend-osx.c
160
src/rend-osx.c
|
@ -28,24 +28,42 @@
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#include <DNSServiceDiscovery/DNSServiceDiscovery.h>
|
#include <DNSServiceDiscovery/DNSServiceDiscovery.h>
|
||||||
|
|
||||||
|
#include "daapd.h"
|
||||||
#include "err.h"
|
#include "err.h"
|
||||||
|
#include "rend-unix.h"
|
||||||
|
|
||||||
CFRunLoopRef rend_runloop;
|
CFRunLoopRef rend_runloop;
|
||||||
|
CFRunLoopSourceRef rend_rls;
|
||||||
|
pthread_t rend_tid;
|
||||||
|
|
||||||
|
/* Forwards */
|
||||||
|
void *rend_pipe_monitor(void* arg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_stoprunloop
|
||||||
|
*/
|
||||||
static void rend_stoprunloop(void) {
|
static void rend_stoprunloop(void) {
|
||||||
CFRunLoopStop(rend_runloop);
|
CFRunLoopStop(rend_runloop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_sigint
|
||||||
|
*/
|
||||||
static void rend_sigint(int sigraised) {
|
static void rend_sigint(int sigraised) {
|
||||||
DPRINTF(ERR_INFO,"SIGINT\n");
|
DPRINTF(ERR_INFO,"SIGINT\n");
|
||||||
rend_stoprunloop();
|
rend_stoprunloop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_handler
|
||||||
|
*/
|
||||||
static void rend_handler(CFMachPortRef port, void *msg, CFIndex size, void *info) {
|
static void rend_handler(CFMachPortRef port, void *msg, CFIndex size, void *info) {
|
||||||
DNSServiceDiscovery_handleReply(msg);
|
DNSServiceDiscovery_handleReply(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_addtorunloop
|
||||||
|
*/
|
||||||
static int rend_addtorunloop(dns_service_discovery_ref client) {
|
static int rend_addtorunloop(dns_service_discovery_ref client) {
|
||||||
mach_port_t port=DNSServiceDiscoveryMachPort(client);
|
mach_port_t port=DNSServiceDiscoveryMachPort(client);
|
||||||
|
|
||||||
|
@ -66,6 +84,9 @@ static int rend_addtorunloop(dns_service_discovery_ref client) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_reply
|
||||||
|
*/
|
||||||
static void rend_reply(DNSServiceRegistrationReplyErrorType errorCode, void *context) {
|
static void rend_reply(DNSServiceRegistrationReplyErrorType errorCode, void *context) {
|
||||||
switch(errorCode) {
|
switch(errorCode) {
|
||||||
case kDNSServiceDiscoveryNoError:
|
case kDNSServiceDiscoveryNoError:
|
||||||
|
@ -81,62 +102,123 @@ static void rend_reply(DNSServiceRegistrationReplyErrorType errorCode, void *con
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* public interface
|
* rend_pipe_monitor
|
||||||
*/
|
*/
|
||||||
int rend_init(pid_t *pid, char *name, int port, char *user) {
|
void *rend_pipe_monitor(void* arg) {
|
||||||
dns_service_discovery_ref daap_ref=NULL;
|
fd_set rset;
|
||||||
dns_service_discovery_ref http_ref=NULL;
|
struct timeval tv;
|
||||||
unsigned short usPort=port;
|
int result;
|
||||||
struct passwd *pw=NULL;
|
|
||||||
|
|
||||||
*pid=fork();
|
|
||||||
if(*pid) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* drop privs */
|
while(1) {
|
||||||
if(getuid() == (uid_t)0) {
|
DPRINTF(ERR_DEBUG,"Waiting for data\n");
|
||||||
pw=getpwnam(user);
|
FD_ZERO(&rset);
|
||||||
if(pw) {
|
FD_SET(rend_pipe_to[RD_SIDE],&rset);
|
||||||
if(initgroups(user,pw->pw_gid) != 0 ||
|
|
||||||
setgid(pw->pw_gid) != 0 ||
|
/* sit in a select spin until there is data on the to fd */
|
||||||
setuid(pw->pw_uid) != 0) {
|
while(((result=select(rend_pipe_to[RD_SIDE] + 1,&rset,NULL,NULL,NULL)) != -1) &&
|
||||||
fprintf(stderr,"Couldn't change to %s, gid=%d, uid=%d\n",
|
errno != EINTR) {
|
||||||
user,pw->pw_gid, pw->pw_uid);
|
if(FD_ISSET(rend_pipe_to[RD_SIDE],&rset)) {
|
||||||
exit(EXIT_FAILURE);
|
DPRINTF(ERR_DEBUG,"Received a message from daap server\n");
|
||||||
|
CFRunLoopSourceSignal(rend_rls);
|
||||||
|
CFRunLoopWakeUp(rend_runloop);
|
||||||
|
sleep(1); /* force a reschedule, hopefully */
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
fprintf(stderr,"Couldn't lookup user %s\n",user);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DPRINTF(ERR_DEBUG,"Select error!\n");
|
||||||
|
/* should really bail here */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_callback
|
||||||
|
*
|
||||||
|
* This gets called from the main thread when there is a
|
||||||
|
* message waiting to be processed.
|
||||||
|
*/
|
||||||
|
void rend_callback(void *info) {
|
||||||
|
REND_MESSAGE msg;
|
||||||
|
unsigned short usPort;
|
||||||
|
dns_service_discovery_ref dns_ref=NULL;
|
||||||
|
|
||||||
|
/* here, we've seen the message, now we have to process it */
|
||||||
|
|
||||||
|
if(rend_read_message(&msg) != sizeof(msg)) {
|
||||||
|
DPRINTF(ERR_FATAL,"Error reading rendezvous message\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch(msg.cmd) {
|
||||||
|
case REND_MSG_TYPE_REGISTER:
|
||||||
|
DPRINTF(ERR_DEBUG,"Registering %s.%s (%d)\n",msg.type,msg.name,msg.port);
|
||||||
|
usPort=msg.port;
|
||||||
|
dns_ref=DNSServiceRegistrationCreate(msg.name,msg.type,"",usPort,"",rend_reply,nil);
|
||||||
|
if(rend_addtorunloop(dns_ref)) {
|
||||||
|
DPRINTF(ERR_WARN,"Add to runloop failed\n");
|
||||||
|
rend_send_response(-1);
|
||||||
|
} else {
|
||||||
|
rend_send_response(0); /* success */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REND_MSG_TYPE_UNREGISTER:
|
||||||
|
DPRINTF(ERR_WARN,"Unsupported function: UNREGISTER\n");
|
||||||
|
rend_send_response(-1); /* error */
|
||||||
|
break;
|
||||||
|
case REND_MSG_TYPE_STOP:
|
||||||
|
DPRINTF(ERR_DEBUG,"Stopping mDNS\n");
|
||||||
|
rend_send_response(0);
|
||||||
|
rend_stoprunloop();
|
||||||
|
break;
|
||||||
|
case REND_MSG_TYPE_STATUS:
|
||||||
|
DPRINTF(ERR_DEBUG,"Status inquiry -- returning 0\n");
|
||||||
|
rend_send_response(0); /* success */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
signal(SIGINT, rend_sigint); // SIGINT is what you get for a Ctrl-C
|
/*
|
||||||
|
* rend_private_init
|
||||||
|
*
|
||||||
|
* start up the rendezvous services
|
||||||
|
*/
|
||||||
|
int rend_private_init(char *user) {
|
||||||
|
CFRunLoopSourceContext context;
|
||||||
|
|
||||||
|
if(drop_privs(user)) /* shouldn't be running as root anyway */
|
||||||
DPRINTF(ERR_DEBUG,"Registering services\n");
|
|
||||||
|
|
||||||
daap_ref=DNSServiceRegistrationCreate(name,"_daap._tcp","",usPort,"",rend_reply,nil);
|
|
||||||
http_ref=DNSServiceRegistrationCreate(name,"_http._tcp","",port,"",rend_reply,nil);
|
|
||||||
|
|
||||||
if(rend_addtorunloop(daap_ref)|| rend_addtorunloop(http_ref)) {
|
|
||||||
DPRINTF(ERR_WARN,"Add to runloop failed\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
/* need a sigint handler */
|
||||||
|
DPRINTF(ERR_DEBUG,"Starting rendezvous services\n");
|
||||||
|
|
||||||
|
memset((void*)&context,0,sizeof(context));
|
||||||
|
context.perform = rend_callback;
|
||||||
|
|
||||||
rend_runloop = CFRunLoopGetCurrent();
|
rend_runloop = CFRunLoopGetCurrent();
|
||||||
|
rend_rls = CFRunLoopSourceCreate(NULL,0,&context);
|
||||||
|
CFRunLoopAddSource(CFRunLoopGetCurrent(),rend_rls,kCFRunLoopDefaultMode);
|
||||||
|
|
||||||
|
DPRINTF(ERR_DEBUG,"Starting polling thread\n");
|
||||||
|
|
||||||
|
if(pthread_create(&rend_tid,NULL,rend_pipe_monitor,NULL)) {
|
||||||
|
DPRINTF(ERR_FATAL,"Could not start thread. Terminating\n");
|
||||||
|
/* should kill parent, too */
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTF(ERR_DEBUG,"Registered rendezvous services\n");
|
DPRINTF(ERR_DEBUG,"Starting runloop\n");
|
||||||
|
|
||||||
CFRunLoopRun();
|
CFRunLoopRun();
|
||||||
|
|
||||||
DPRINTF(ERR_DEBUG,"Exiting runloop\n");
|
DPRINTF(ERR_DEBUG,"Exiting runloop\n");
|
||||||
|
|
||||||
DNSServiceDiscoveryDeallocate(daap_ref);
|
CFRelease(rend_rls);
|
||||||
DNSServiceDiscoveryDeallocate(http_ref);
|
pthread_cancel(rend_tid);
|
||||||
|
close(rend_pipe_to[RD_SIDE]);
|
||||||
exit(0);
|
close(rend_pipe_from[WR_SIDE]);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,12 @@
|
||||||
Change History (most recent first):
|
Change History (most recent first):
|
||||||
|
|
||||||
$Log$
|
$Log$
|
||||||
|
Revision 1.10 2004/01/20 04:41:20 rpedde
|
||||||
|
merge new-rend-branch
|
||||||
|
|
||||||
|
Revision 1.9.2.1 2004/01/16 20:51:01 rpedde
|
||||||
|
Convert rend-posix to message-based system
|
||||||
|
|
||||||
Revision 1.9 2004/01/04 05:02:23 rpedde
|
Revision 1.9 2004/01/04 05:02:23 rpedde
|
||||||
fix segfault on dropping privs
|
fix segfault on dropping privs
|
||||||
|
|
||||||
|
@ -143,6 +149,8 @@
|
||||||
|
|
||||||
#define __IN_ERR__
|
#define __IN_ERR__
|
||||||
#include "err.h"
|
#include "err.h"
|
||||||
|
#include "rend.h"
|
||||||
|
#include "rend-unix.h"
|
||||||
|
|
||||||
#pragma mark ***** Globals
|
#pragma mark ***** Globals
|
||||||
|
|
||||||
|
@ -549,55 +557,73 @@ static void DeregisterOurServices(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark **** Main
|
/*
|
||||||
|
* rend_callback
|
||||||
|
*
|
||||||
|
* This is borrowed from the OSX rend client
|
||||||
|
*/
|
||||||
|
void rend_callback(void) {
|
||||||
|
REND_MESSAGE msg;
|
||||||
|
int result;
|
||||||
|
|
||||||
int rend_init(pid_t *pid,char *name, int port, char *user) {
|
DPRINTF(ERR_DEBUG,"Processing rendezvous message\n");
|
||||||
|
|
||||||
|
/* here, we've seen the message, now we have to process it */
|
||||||
|
|
||||||
|
if((result=rend_read_message(&msg)) != sizeof(msg)) {
|
||||||
|
DPRINTF(ERR_DEBUG,"Expected %d, got %d\n",sizeof(msg),result);
|
||||||
|
DPRINTF(ERR_FATAL,"Error reading rendezvous message: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(msg.cmd) {
|
||||||
|
case REND_MSG_TYPE_REGISTER:
|
||||||
|
DPRINTF(ERR_DEBUG,"Registering %s.%s (%d)\n",msg.type,msg.name,msg.port);
|
||||||
|
RegisterOneService(msg.name,msg.type,NULL,0,msg.port);
|
||||||
|
rend_send_response(0); /* success */
|
||||||
|
break;
|
||||||
|
case REND_MSG_TYPE_UNREGISTER:
|
||||||
|
rend_send_response(1); /* error */
|
||||||
|
break;
|
||||||
|
case REND_MSG_TYPE_STOP:
|
||||||
|
DPRINTF(ERR_INFO,"Stopping mDNS\n");
|
||||||
|
gStopNow = mDNStrue;
|
||||||
|
rend_send_response(0);
|
||||||
|
break;
|
||||||
|
case REND_MSG_TYPE_STATUS:
|
||||||
|
rend_send_response(1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark **** rend_private_init
|
||||||
|
|
||||||
|
int rend_private_init(char *user) {
|
||||||
mStatus status;
|
mStatus status;
|
||||||
mDNSBool result;
|
mDNSBool result;
|
||||||
struct passwd *pw=NULL;
|
|
||||||
|
|
||||||
status = mDNS_Init(&mDNSStorage, &PlatformStorage,
|
status = mDNS_Init(&mDNSStorage, &PlatformStorage,
|
||||||
mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
|
mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
|
||||||
mDNS_Init_AdvertiseLocalAddresses,
|
mDNS_Init_AdvertiseLocalAddresses,
|
||||||
mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
|
mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
|
||||||
|
|
||||||
if (status != mStatus_NoError) {
|
if (status != mStatus_NoError) {
|
||||||
DPRINTF(ERR_FATAL,"mDNS Error %d\n",status);
|
DPRINTF(ERR_FATAL,"mDNS Error %d\n",status);
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
*pid=fork();
|
if(drop_privs(user))
|
||||||
if(*pid) {
|
return -1;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* drop privs */
|
|
||||||
if(getuid() == (uid_t)0) {
|
|
||||||
pw=getpwnam(user);
|
|
||||||
if(pw) {
|
|
||||||
if(initgroups(user,pw->pw_gid) != 0 ||
|
|
||||||
setgid(pw->pw_gid) != 0 ||
|
|
||||||
setuid(pw->pw_uid) != 0) {
|
|
||||||
fprintf(stderr,"Couldn't change to %s, gid=%d, uid=%d\n",
|
|
||||||
user,pw->pw_gid, pw->pw_uid);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr,"Couldn't lookup user %s\n",user);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DPRINTF(ERR_DEBUG,"Registering tcp service\n");
|
|
||||||
RegisterOneService(name,"_http._tcp",NULL,0,port);
|
|
||||||
RegisterOneService(name,"_daap._tcp",NULL,0,port);
|
|
||||||
|
|
||||||
signal(SIGINT, HandleSigInt); // SIGINT is what you get for a Ctrl-C
|
signal(SIGINT, HandleSigInt); // SIGINT is what you get for a Ctrl-C
|
||||||
signal(SIGQUIT, HandleSigQuit); // SIGQUIT is what you get for a Ctrl-\ (indeed)
|
signal(SIGQUIT, HandleSigQuit); // SIGQUIT is what you get for a Ctrl-\ (indeed)
|
||||||
|
|
||||||
while (!gStopNow) {
|
while (!gStopNow) {
|
||||||
int nfds = 0;
|
int nfds = 1;
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
int result;
|
int result;
|
||||||
|
@ -606,6 +632,7 @@ int rend_init(pid_t *pid,char *name, int port, char *user) {
|
||||||
// This example client has no file descriptors of its own,
|
// This example client has no file descriptors of its own,
|
||||||
// but a real application would call FD_SET to add them to the set here
|
// but a real application would call FD_SET to add them to the set here
|
||||||
FD_ZERO(&readfds);
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(rend_pipe_to[RD_SIDE],&readfds);
|
||||||
|
|
||||||
// 2. Set up the timeout.
|
// 2. Set up the timeout.
|
||||||
// This example client has no other work it needs to be doing,
|
// This example client has no other work it needs to be doing,
|
||||||
|
@ -632,6 +659,9 @@ int rend_init(pid_t *pid,char *name, int port, char *user) {
|
||||||
// 6. This example client has no other work it needs to be doing,
|
// 6. This example client has no other work it needs to be doing,
|
||||||
// but a real client would do its work here
|
// but a real client would do its work here
|
||||||
// ... (do work) ...
|
// ... (do work) ...
|
||||||
|
if(FD_ISSET(rend_pipe_to[RD_SIDE],&readfds)) {
|
||||||
|
rend_callback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,3 +681,4 @@ int rend_init(pid_t *pid,char *name, int port, char *user) {
|
||||||
exit(result);
|
exit(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* General unix rendezvous routines
|
||||||
|
*
|
||||||
|
* Copyright (C) 2003 Ron Pedde (ron@pedde.com)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "daapd.h"
|
||||||
|
#include "err.h"
|
||||||
|
#include "rend-unix.h"
|
||||||
|
|
||||||
|
int rend_pipe_to[2];
|
||||||
|
int rend_pipe_from[2];
|
||||||
|
int rend_pid;
|
||||||
|
|
||||||
|
#define RD_SIDE 0
|
||||||
|
#define WR_SIDE 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_init
|
||||||
|
*
|
||||||
|
* Fork and set up message passing system
|
||||||
|
*/
|
||||||
|
int rend_init(char *user) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if(pipe((int*)&rend_pipe_to) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(pipe((int*)&rend_pipe_from) == -1) {
|
||||||
|
err=errno;
|
||||||
|
close(rend_pipe_to[RD_SIDE]);
|
||||||
|
close(rend_pipe_to[WR_SIDE]);
|
||||||
|
errno=err;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rend_pid=fork();
|
||||||
|
if(rend_pid==-1) {
|
||||||
|
err=errno;
|
||||||
|
close(rend_pipe_to[RD_SIDE]);
|
||||||
|
close(rend_pipe_to[WR_SIDE]);
|
||||||
|
close(rend_pipe_from[RD_SIDE]);
|
||||||
|
close(rend_pipe_from[WR_SIDE]);
|
||||||
|
errno=err;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rend_pid) { /* parent */
|
||||||
|
close(rend_pipe_to[RD_SIDE]);
|
||||||
|
close(rend_pipe_from[WR_SIDE]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* child */
|
||||||
|
close(rend_pipe_to[WR_SIDE]);
|
||||||
|
close(rend_pipe_from[RD_SIDE]);
|
||||||
|
|
||||||
|
/* something bad here... should really signal the parent, rather
|
||||||
|
* than just zombieizing
|
||||||
|
*/
|
||||||
|
rend_private_init(user); /* should only return when terminated */
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_running
|
||||||
|
*
|
||||||
|
* See if the rendezvous daemon is runnig
|
||||||
|
*/
|
||||||
|
int rend_running(void) {
|
||||||
|
REND_MESSAGE msg;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
DPRINTF(ERR_DEBUG,"Status inquiry\n");
|
||||||
|
msg.cmd=REND_MSG_TYPE_STATUS;
|
||||||
|
result=rend_send_message(&msg);
|
||||||
|
DPRINTF(ERR_DEBUG,"Returning status %d\n",result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*rend_stop
|
||||||
|
*
|
||||||
|
* Stop the rendezvous server
|
||||||
|
*/
|
||||||
|
int rend_stop(void) {
|
||||||
|
REND_MESSAGE msg;
|
||||||
|
|
||||||
|
msg.cmd=REND_MSG_TYPE_STOP;
|
||||||
|
return rend_send_message(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_register
|
||||||
|
*
|
||||||
|
* register a rendezvous name
|
||||||
|
*/
|
||||||
|
int rend_register(char *name, char *type, int port) {
|
||||||
|
REND_MESSAGE msg;
|
||||||
|
|
||||||
|
if((strlen(name)+1 > MAX_NAME_LEN) || (strlen(type)+1 > MAX_NAME_LEN)) {
|
||||||
|
DPRINTF(ERR_FATAL,"Registration failed: name or type too long\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.cmd=REND_MSG_TYPE_REGISTER;
|
||||||
|
strcpy(msg.name,name);
|
||||||
|
strcpy(msg.type,type);
|
||||||
|
msg.port=port;
|
||||||
|
|
||||||
|
return rend_send_message(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_unregister
|
||||||
|
*
|
||||||
|
* Stop advertising a rendezvous name
|
||||||
|
*/
|
||||||
|
int rend_unregister(char *name, char *type, int port) {
|
||||||
|
return -1; /* not implemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_send_message
|
||||||
|
*
|
||||||
|
* Send a rendezvous message
|
||||||
|
*/
|
||||||
|
int rend_send_message(REND_MESSAGE *pmsg) {
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if(r_write(rend_pipe_to[WR_SIDE],pmsg,sizeof(REND_MESSAGE)) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if((retval=r_read(rend_pipe_from[RD_SIDE],&retval,sizeof(int)) == -1))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_read_message
|
||||||
|
*
|
||||||
|
* read the message passed to the rend daemon
|
||||||
|
*/
|
||||||
|
int rend_read_message(REND_MESSAGE *pmsg) {
|
||||||
|
return r_read(rend_pipe_to[RD_SIDE],pmsg,sizeof(REND_MESSAGE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rend_send_response
|
||||||
|
*
|
||||||
|
* Let the rendezvous daemon return a result
|
||||||
|
*/
|
||||||
|
int rend_send_response(int value) {
|
||||||
|
return r_write(rend_pipe_from[WR_SIDE],&value,sizeof(int));
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* General unix rendezvous routines
|
||||||
|
*
|
||||||
|
* Copyright (C) 2003 Ron Pedde (ron@pedde.com)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _REND_UNIX_H_
|
||||||
|
#define _REND_UNIX_H_
|
||||||
|
|
||||||
|
#define MAX_NAME_LEN 256
|
||||||
|
|
||||||
|
typedef struct tag_rend_message {
|
||||||
|
int cmd;
|
||||||
|
int port;
|
||||||
|
char name[MAX_NAME_LEN];
|
||||||
|
char type[MAX_NAME_LEN];
|
||||||
|
} REND_MESSAGE;
|
||||||
|
|
||||||
|
#define REND_MSG_TYPE_REGISTER 0
|
||||||
|
#define REND_MSG_TYPE_UNREGISTER 1
|
||||||
|
#define REND_MSG_TYPE_STOP 2
|
||||||
|
#define REND_MSG_TYPE_STATUS 3
|
||||||
|
|
||||||
|
#define RD_SIDE 0
|
||||||
|
#define WR_SIDE 1
|
||||||
|
|
||||||
|
extern int rend_pipe_to[2];
|
||||||
|
extern int rend_pipe_from[2];
|
||||||
|
|
||||||
|
extern int rend_send_message(REND_MESSAGE *pmsg);
|
||||||
|
extern int rend_send_response(int value);
|
||||||
|
extern int rend_private_init(char *user);
|
||||||
|
extern int rend_read_message(REND_MESSAGE *pmsg);
|
||||||
|
|
||||||
|
#endif /* _REND_UNIX_H_ */
|
||||||
|
|
|
@ -22,6 +22,10 @@
|
||||||
#ifndef _REND_H_
|
#ifndef _REND_H_
|
||||||
#define _REND_H_
|
#define _REND_H_
|
||||||
|
|
||||||
int rend_init(pid_t *pid, char *name, int port, char *user);
|
extern int rend_init(char *user);
|
||||||
|
extern int rend_running(void);
|
||||||
|
extern int rend_stop(void);
|
||||||
|
extern int rend_register(char *name, char *type, int port);
|
||||||
|
extern int rend_unregister(char *name, char *type, int port);
|
||||||
|
|
||||||
#endif /* _REND_H_ */
|
#endif /* _REND_H_ */
|
||||||
|
|
Loading…
Reference in New Issue