Guest
|
Posted: Mon Sep 05, 2005 1:10 pm Post subject: shout: a c program to shuffle playlists |
|
|
Written by me dr_elektrique
feel free to distribute.
Code: |
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
extern char ** environ;
// Returns true if fname ends in .mp3
int is_mp3 ( char * fname );
int main ( int argc, char ** argv ) {
DIR * dp;
FILE * fp;
struct dirent * ep;
pid_t pid;
pid_t gid;
puts ( "Generating New Playlist" );
dp = opendir ("./");
fp = fopen ( "/etc/icecast/shout.playlist", "w" );
if ( dp == NULL ) { puts ( "Failure: Can not open directory for reading." ); return 1; }
if ( fp == NULL ) { puts ( "Failure: Can not open playlist file for writing." ); return 2; }
// Here we generate the actual playlist. The program must ofcourse have access to
// the playlist file, so make sure its chowned appropriately and setuid setgid.
// I do not believe this is a great security risk since all the commands run are
// hardwired in and there are no buffers. I also made sure there aren't obvious
// format string vulns (related to the filenames) I could be wrong, If you think
// I am please correct me: dr_elektrique@informationleak.net
while ( ep = readdir ( dp ) ) {
if ( is_mp3 ( ep -> d_name ) ) {
fprintf ( fp, "%s/%s\n", getcwd ( NULL, 0 ) , ep -> d_name );
printf ( "%s/%s\n", getcwd ( NULL, 0 ) , ep -> d_name );
}
}
closedir ( dp );
fclose ( fp );
puts ( "Done.\n" );
puts ( "Restarting Shout." );
// The system call is non blocking, we should wait for it to terminate
// Of course ideally we should just fork and exec like below but I am
// lazy. Anyways we sleep a second to make sure any old shout process
// is really terminated.
system ( "killall shout" );
sleep ( 1 );
// This retrieves the main process' group id. Notice we haven't
// forked yet. This variable will retain it's value within the child
// process, whereas a call to getpgrp within the child would return
// the pid of this proccess.
gid = getpgrp ( );
pid = fork ( );
if ( pid == 0 ) {
// Now that we have forked before we load the daemon, we set the
// forked process' group pid to that of its parent, effectively
// making the two siblings. This way the parent (now sibling) process
// can terminate without having to wory about leaving shout orphaned.
setpgid ( 0, gid );
execlp ( "shout", "shout", "-z", NULL );
// This code shouldn't run under normal circumstances. Not even when
// shout terminates. If this code runs it means execlp failed,
// which would suck.
puts ( "Failure: execlp() did not work." );
exit ( 127 );
} else if ( pid < 0 ) puts ( "Failure: fork() did not work." );
puts ( "Done.\n" );
exit ( 0 );
return 0; }
int is_mp3 ( char * fname ) {
if ( strlen ( fname ) <= 4 ) return 0;
if ( * ( fname + strlen ( fname ) - 4 ) != '.' ) return 0;
if ( * ( fname + strlen ( fname ) - 3 ) != 'm' ) return 0;
if ( * ( fname + strlen ( fname ) - 2 ) != 'p' ) return 0;
if ( * ( fname + strlen ( fname ) - 1 ) != '3' ) return 0;
return 1; } |
|
|