/* -------------------------------------------------------------------- */ /* SMS Client, send messages to mobile phones and pagers */ /* */ /* queue.c */ /* */ /* Copyright (C) 1997,1998,1999 Angelo Masci */ /* */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Library General Public */ /* License as published by the Free Software Foundation; either */ /* version 2 of the License, or (at your option) any later version. */ /* */ /* This library 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 */ /* Library General Public License for more details. */ /* */ /* You should have received a copy of the GNU Library General Public */ /* License along with this library; if not, write to the Free */ /* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* */ /* You can contact the author at this e-mail address: */ /* */ /* angelo@styx.demon.co.uk */ /* */ /* -------------------------------------------------------------------- */ /* $Id$ -------------------------------------------------------------------- */ #include #include #include #include #include #include "common/common.h" #include "logfile/logfile.h" #include "npipe.h" #include "process.h" #include "resource/resource.h" #include "lock/lock.h" #include "parser/gs_translate.h" #include "driver/driver.h" #include "version.h" #include "parser/parser_api/gs_api.h" /* -------------------------------------------------------------------- */ #if !defined(MVERSION) #error "MVERSION undefined" #else #define VERSION MVERSION #endif #if !defined(MSMSDLOGFILE) #error "MSMSDLOGFILE undefined" #else #define LOGFILE MSMSDLOGFILE #endif #if !defined(MSMSDLOGLEVEL) #error "MSMSDLOGLEVEL undefined" #else #define LOGLEVEL MSMSDLOGLEVEL #endif /* -------------------------------------------------------------------- */ char queue_lockfile[512], queue_errordir[512], queue_queuedir[512]; char *queue_spool, *queue_incoming, *queue_services, *queue_errors, *queue_named_pipes, *queue_locks; TOKEN_HEAP *queue_services_heap; static RESOURCE resource_list[] = { { RESOURCE_STRING, "directories.spool", 0, 1, NULL, 0, "/var/spool/sms", 0, &queue_spool }, { RESOURCE_STRING, "directories.incoming", 0, 1, NULL, 0, "incoming", 0, &queue_incoming }, { RESOURCE_STRING, "directories.services", 0, 1, NULL, 0, "services", 0, &queue_services }, { RESOURCE_STRING, "directories.errors", 0, 1, NULL, 0, "errors", 0, &queue_errors }, { RESOURCE_STRING, "directories.named_pipes", 0, 1, NULL, 0, "named_pipes", 0, &queue_named_pipes }, { RESOURCE_STRING, "directories.locks", 0, 1, NULL, 0, "locks", 0, &queue_locks }, { RESOURCE_HEAP, "services", 0, 1, NULL, 0, NULL, 0, &queue_services_heap }, { RESOURCE_NULL, NULL, 0, 1, NULL, 0, NULL, 0, NULL } }; #define SPOOLDIR queue_spool #define LOCKDIR queue_locks #define ERRORDIR queue_errors #define INCOMINGDIR queue_incoming #define SERVICESDIR queue_services #define NAMEDPIPESDIR queue_named_pipes /* -------------------------------------------------------------------- */ #if !defined(MSERVICEDIR) #error "MSERVICEDIR undefined" #else #define SERVICEDIR MSERVICEDIR #endif #define DAEMONCONFIGFILE (MSERVICEDIR "/sms_daemons") /* -------------------------------------------------------------------- */ volatile int term_flag = FALSE; /* -------------------------------------------------------------------- */ static void exit_func(int sig); static void usage(char *file); static int deamon_init(void); static int install_sighandlers(void); /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static void exit_func(int sig) { term_flag = TRUE; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static int install_sighandlers(void) { struct sigaction act, oact; act.sa_handler = exit_func; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (sigaction(SIGTERM, &act, &oact) != 0) { return -1; } return 0; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static int deamon_init(void) { pid_t pid; set_consolelog(FALSE); pid = fork(); if (pid < 0) { lprintf(LOG_ERROR, "fork() failed\n"); return -1; } else if (pid != 0) { exit(0); } if (setsid() < 0) /* Become session leader */ { lprintf(LOG_ERROR, "setsid() failed\n"); return -1; } if (chdir("/") < 0) /* Change working directory */ { lprintf(LOG_ERROR, "chdir() failed\n"); return -1; } return 0; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static void usage(char *file) { lprintf(LOG_STANDARD, "Usage: %s [-l loglevel] service\n", file); lprintf(LOG_STANDARD, " %s -v\n", file); lprintf(LOG_STANDARD, " %s -a\n", file); } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static void release_lock(void) { resource_unlock(queue_lockfile); } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static int list_services(TOKEN_HEAP *heap) { /* unfinished */ return 0; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ int main(int argc, char *argv[]) { DEVICE_ENTRY *device; int c, list_services_flag; char *ptr, service_pipe[512], *service, *protocol, *value, *progname; progname = strrchr(argv[0], '/'); if (progname == NULL) { progname = argv[0]; } else { progname++; } /* ---------------------------- */ set_logfile(LOGFILE); set_loglevel(LOGLEVEL); set_consolelog(TRUE); /* ---------------------------- */ list_services_flag = FALSE; while ((c = getopt (argc, argv, "l:va")) != -1) { switch (c) { case 'l': set_loglevel((int)strtol(optarg, &ptr, 10)); if (ptr == optarg) { lprintf(LOG_ERROR, "Option l requires an argument\n"); usage(progname); return -1; } break; case 'v': lprintf(LOG_STANDARD, "%s %s\n", progname, VERSION); return 0; case 'a': list_services_flag = TRUE; break; case '?': lprintf(LOG_ERROR, "Unknown option `-%c'\n", optopt); usage(progname); return -1; default: return -1; } } /* -------------------------------------------------------------------- */ if (read_resource_file(DAEMONCONFIGFILE, resource_list, 1) == RESOURCE_FILE_ERROR) { lprintf(LOG_ERROR, "Failed to read resource file '%s'\n", DAEMONCONFIGFILE); return -1; } if (list_services_flag) { return list_services(queue_services_heap); } /* -------------------------------------------------------------------- */ if ((argc - optind) != 1) { usage(progname); return -1; } service = argv[optind]; /* -------------------------------------------------------------------- */ if ((value = get_strvalue(queue_services_heap, service)) != NULL) { lprintf(LOG_VERBOSE, "Service '%s' Found\n", service); if (strcmp(value, "ENABLED") == 0) { lprintf(LOG_VERBOSE, "Service '%s' is enabled\n", service); } else { lprintf(LOG_WARNING, "Service '%s' is NOT enabled\n", service); return -1; } if ((protocol = get_protocol(service)) == NULL) { lprintf(LOG_ERROR, "Service '%s' has no entry for 'protocol'\n", service); return -1; } } else { lprintf(LOG_ERROR, "Service '%s' Not Found\n", service); return -1; } /* -------------------------------------------------------------------- */ strcpy(queue_queuedir, SPOOLDIR); libcommon_strfcat(queue_queuedir, SERVICESDIR); libcommon_strfcat(queue_queuedir, service); if (access(queue_queuedir, F_OK) == -1) { lprintf(LOG_ERROR, "Queue directory '%s' Not Found\n", queue_queuedir); return -1; } /* -------------------------------------------------------------------- */ strcpy(queue_errordir, SPOOLDIR); libcommon_strfcat(queue_errordir, ERRORDIR); libcommon_strfcat(queue_errordir, service); if (access(queue_errordir, F_OK) == -1) { lprintf(LOG_ERROR, "Queue Error directory '%s' Not Found\n", queue_errordir); return -1; } /* -------------------------------------------------------------------- */ /* Initialise the driver for this queue */ /* From here on we access the driver using the 'device' entry */ /* -------------------------------------------------------------------- */ device = get_device(protocol); if (device == NULL) { lprintf(LOG_ERROR, "Driver for service %s NOT found\n", service); return -1; } (*device->init)(service, device); /* -------------------------------------------------------------------- */ strcpy(queue_lockfile, SPOOLDIR); libcommon_strfcat(queue_lockfile, LOCKDIR); libcommon_strfcat(queue_lockfile, service); if (resource_test_lockdir(queue_lockfile) == -1) { return -1; } if (resource_lock(queue_lockfile)) { lprintf(LOG_ERROR, "Queue aborted, lockfile held by another queue daemon\n"); return -1; } atexit(release_lock); /* -------------------------------------------------------------------- */ #if 0 if (install_sighandlers() == -1) { return -1; } if (deamon_init() == -1) { return -1; } #endif /* -------------------------------------------------------------------- */ lprintf(LOG_STANDARD, "Starting SMS Queue for '%s'...\n", service); strcpy(service_pipe, SPOOLDIR); libcommon_strfcat(service_pipe, NAMEDPIPESDIR); libcommon_strfcat(service_pipe, service); lprintf(LOG_VERBOSE, "Creating pipe '%s'\n", service_pipe); if (create_named_pipe(service_pipe) == -1) { lprintf(LOG_ERROR, "create_named_pipe() failed\n"); return -1; } /* -------------------------------------------------------------------- */ #if 1 lprintf(LOG_VERBOSE, "Flushing queue...\n"); process_queue(queue_queuedir, queue_errordir, device); #endif while(!term_flag) { lprintf(LOG_VERBOSE, "Waiting on named pipe '%s'...\n", service_pipe); if (block_on_named_pipe(service_pipe) == -1) { if (errno == EINTR) { continue; } else { lprintf(LOG_ERROR, "block_on_named_pipe() failed\n"); return -1; } } lprintf(LOG_VERBOSE, "Woken by write to '%s'\n", service_pipe); lprintf(LOG_VERBOSE, "Processing queue '%s'...\n", queue_queuedir); process_queue(queue_queuedir, queue_errordir, device); } if (term_flag) { lprintf(LOG_STANDARD, "SMS Queue for '%s' received TERM signal\n", service_pipe); } lprintf(LOG_STANDARD, "Stopping SMS Queue for '%s'...\n", service_pipe); lprintf(LOG_VERBOSE, "Deleting named pipe '%s'\n", service_pipe); if (delete_named_pipe(service_pipe) == -1) { lprintf(LOG_ERROR, "delete_named_pipe() failed\n"); return -1; } resource_unlock(queue_lockfile); return 0; }