/*
* asynch.cpp
* Asynchronous communication
* ____ _
* | _ \ ___ __ _| |_ __ ___ ___
* | |_) / _ \/ _` | | '_ ` _ \/ __|
* | _ < __/ (_| | | | | | | \__ \
* |_| \_\___|\__,_|_|_| |_| |_|___/
*
* Permission to use, modify and distribute is granted via the
* Creative Commons - Attribution - Non Commercial - Share Alike 3.0 License
* http://creativecommons.org/licenses/by-nc-sa/3.0/
*
* Copyright (C) 2007-2012 Jason Mitchell, Randi Mitchell
* Contributions by Tim Callahan, Jonathan Hseu
* Based on Mordor (C) Brooke Paul, Brett J. Vickers, John P. Freeman
*
*/
#include "mud.h"
//*********************************************************************
// Async
//*********************************************************************
// Sample code:
//
// Async async;
// if(async.branch(player, CHILD_PRINT) == AsyncExternal) {
// bstring output = somethingArduous();
// printf("%s", output.c_str());
// exit(0);
// } else {
// player->print("Doing something long and arduous.\n");
// }
//
// Responses to asychronous communication are handled in Server::reapChildren().
// Create your own CHILD_XYZ type if you want to perform special handling. The
// CHILD_PRINT type simply prints the response back to the player.
Async::Async() {
}
//*********************************************************************
// branch
//*********************************************************************
AsyncResult Async::branch(const Player* player, childType type) {
bstring user = (player ? player->getName() : "Someone");
if(pipe(fds) == -1) {
printf("Error with pipe!\n");
abort();
}
int pid = fork();
if(!pid) {
// this is the child process
// Close the reading end, we'll only be writing
close(fds[0]);
// Remap stdout to fds[1] so cout will print to fds[1] and we can
// read it in from the mud
if(dup2(fds[1], STDOUT_FILENO) != STDOUT_FILENO) {
printf("Error with dup2.\n");
abort();
}
return(AsyncExternal);
} else {
// this is the parent process
// Close the writing end, we'll only be reading
close(fds[1]);
nonBlock(fds[0]);
printf("Watching Child %d for (%s) running with pid %d reading from fd %d.",
(int)type, user.c_str(), pid, fds[0]);
// Let the server know we're monitoring this child process
gServer->addChild(pid, type, fds[0], user);
return(AsyncLocal);
}
}
//********************************************************************
// runList
//********************************************************************
int Server::runList(Socket* sock, cmd* cmnd) {
Async async;
if(async.branch(sock->getPlayer(), CHILD_LISTER) == AsyncExternal) {
bstring lister = Path::UniqueRoom;
lister += "list.exe";
std::cout << "Running <" << lister << ">\n";
execl(lister.c_str(), lister.c_str(), cmnd->str[1], cmnd->str[2], cmnd->str[3], cmnd->str[4], NULL);
printf("Error!");
exit(0);
}
return(0);
}