#include "Spooler.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Util.h" #include "Exceptions.h" const std::string spooldir = "/home/torben/smstool"; using namespace std; void errnoException(std::string msg = "") { if (msg != "") msg += ": "; msg += std::string(strerror(errno)); throw std::runtime_error(msg); } void Spooler::enqueue(std::string recipient, std::string message) { bool error = false; lock(); std::string file = findSpoolFilename(); std::ofstream out(file.c_str()); if (out) { out << recipient << "\n" << message; out.close(); } else { error = true; } unlock(); if (error) throw std::runtime_error("Could not create spoolfile"); this->filename = file; } std::string Spooler::dequeue() { lock(); DIR* dir = opendir( spooldir.c_str() ); if (dir == 0) errnoException(); string file; string message; dirent* entry; while ( (entry = readdir(dir)) != 0) { if (entry->d_name[0] == '.' ) { continue; } else { file = spooldir + string(entry->d_name); break; } } closedir(dir); if (file != "") { message = Util::readfile(file); ::unlink(file.c_str()); } unlock(); this->filename = file; if (file != "") return message; else throw filenotfoundexception(); } std::string Spooler::findSpoolFilename() { std::string file; std::stringstream ss; int retrycount = 0; while (1) { ss.str(std::string()); //clear ss << std::setw(8) << std::setfill('0') << std::uppercase << std::hex << rand(); string file = spooldir; file += ss.str().c_str(); int fd = ::open(file.c_str(), O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP| S_IROTH); retrycount ++; if (fd != -1) { ::close(fd); return file; } int err = errno; ::close(fd); if (err == EEXIST) { continue; } if (retrycount > 20) throw std::runtime_error("to many retry attempt at creating spool file"); throw std::runtime_error("no access to spool directory"); } } void Spooler::lock() { lockfd = open(spooldir.c_str() , O_RDONLY); if (lockfd == -1) { errnoException("Couldn open lockfile"); } int status = flock(lockfd, LOCK_EX); if (status == -1) { errnoException(); } } void Spooler::unlock() { flock(lockfd, LOCK_UN); close(lockfd); } string Spooler::getFilename() { return filename; }