/* -------------------------------------------------------------------- */ /* SMS Client, send messages to mobile phones and pagers */ /* */ /* smsd.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 #include #include #include #include #if defined(LINUX) #include #endif #include "server.h" #include "logfile/logfile.h" #include "common/common.h" #include "resource/resource.h" #include "parser/gs_translate.h" #include "version.h" #include "lock/lock.h" #include "error.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 #if !defined(MSERVICEDIR) #error "MSERVICEDIR undefined" #else #define SERVICEDIR MSERVICEDIR #endif #define DAEMONCONFIGFILE (MSERVICEDIR "/sms_daemons") /* -------------------------------------------------------------------- */ #define ERROR_STATE -2 #define EXIT_STATE -1 #define NULL_STATE 0 #define UNKNOWN_STATE 1 #define OK_STATE 2 /* -------------------------------------------------------------------- */ struct sms_control_data_struct { char *user, *host, *mail, *alen, *destination_service, *destination_id, *control_file, *data_file, *id; long len; }; typedef struct sms_control_data_struct SMS_CONTROL_DATA; struct sms_data_struct { char *data; }; typedef struct sms_data_struct SMS_DATA; /* -------------------------------------------------------------------- */ SMS_DATA sms_data; /* -------------------------------------------------------------------- */ static int smsd_port, smsd_maxid; static char smsd_lockfile[512]; static char *smsd_spool, *smsd_incoming, *smsd_services, *smsd_locks; static TOKEN_HEAP *smsd_services_heap; static RESOURCE resource_list[] = { { RESOURCE_NUMERIC, "server.port", 0, 1, NULL, 0, NULL, 4563, &smsd_port }, { RESOURCE_NUMERIC, "server.maxid", 0, 1, NULL, 0, NULL, 32000, &smsd_maxid }, { RESOURCE_STRING, "directories.spool", 0, 1, NULL, 0, "/var/spool/sms", 0, &smsd_spool }, { RESOURCE_STRING, "directories.incoming", 0, 1, NULL, 0, "incoming", 0, &smsd_incoming }, { RESOURCE_STRING, "directories.services", 0, 1, NULL, 0, "services", 0, &smsd_services }, { RESOURCE_STRING, "directories.locks", 0, 1, NULL, 0, "locks", 0, &smsd_locks }, { RESOURCE_HEAP, "services", 0, 1, NULL, 0, NULL, 0, &smsd_services_heap }, { RESOURCE_NULL, NULL, 0, 1, NULL, 0, NULL, 0, NULL } }; #define SMS_PORT smsd_port /* Standard port number */ /* assigned for sms traffic */ #define SMS_SPOOLDIR smsd_spool #define SMS_LOCKDIR smsd_locks #define SMS_INCOMINGDIR smsd_incoming #define SMS_SERVICESDIR smsd_services #define SMS_MAXID smsd_maxid /* -------------------------------------------------------------------- */ #define SAFEOUTPUT(X) ((X == NULL)?(""):(X)) #define SAFECONTROLOUTPUT(X) ((X == NULL)?(""):(X)) /* -------------------------------------------------------------------- */ void cleanup_files(SMS_CONTROL_DATA *control_data); void display_current(int fd, SMS_CONTROL_DATA *control_data); void gateway(int new_fd); void usage(char *file); char *get_data(char *buf); int gen_controlfile(SMS_CONTROL_DATA *control_data); int copy_data(int dst_fd, int src_fd, long dlen); /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void display_current(int fd, SMS_CONTROL_DATA *control_data) { hprintf(fd, " Current Control Record info:\r\n"); hprintf(fd, " Username: %s\r\n", SAFEOUTPUT(control_data->user)); hprintf(fd, " Hostname: %s\r\n", SAFEOUTPUT(control_data->host)); hprintf(fd, " Mail on Delivery: %s\r\n", SAFEOUTPUT(control_data->mail)); hprintf(fd, " Destination Service: %s\r\n", SAFEOUTPUT(control_data->destination_service)); hprintf(fd, " Destination ID: %s\r\n", SAFEOUTPUT(control_data->destination_id)); hprintf(fd, " Control File: %s\r\n", SAFEOUTPUT(control_data->control_file)); hprintf(fd, " Data File: %s\r\n", SAFEOUTPUT(control_data->data_file)); hprintf(fd, " ID: %s\r\n", SAFEOUTPUT(control_data->id)); hprintf(fd, " Length: %ld\r\n", control_data->len); } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void write_control_data(SMS_CONTROL_DATA *control_data) { FILE *fp; fp = fopen(control_data->control_file, "w"); if (fp == NULL) { lprintf(LOG_ERROR, "Opening control_file '%s'\n", control_data->control_file); exit(-1); } fprintf(fp, "{\n"); fprintf(fp, " username = \"%s\"\n", SAFECONTROLOUTPUT(control_data->user)); fprintf(fp, " hostname = \"%s\"\n", SAFECONTROLOUTPUT(control_data->host)); fprintf(fp, " mail_on_delivery = \"%s\"\n", SAFECONTROLOUTPUT(control_data->mail)); fprintf(fp, " destination_service = \"%s\"\n", SAFECONTROLOUTPUT(control_data->destination_service)); fprintf(fp, " destination_id = \"%s\"\n", SAFECONTROLOUTPUT(control_data->destination_id)); fprintf(fp, " control_file = \"%s\"\n", SAFECONTROLOUTPUT(control_data->control_file)); fprintf(fp, " data_file = \"%s\"\n", SAFECONTROLOUTPUT(control_data->data_file)); fprintf(fp, " id = \"%s\"\n", SAFECONTROLOUTPUT(control_data->id)); fprintf(fp, " length = \"%ld\"\n", control_data->len); fprintf(fp, "}\n"); fclose(fp); } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ #define iseol(x) ((x == '\n') || (x == '\r')) char *get_field(char *buf, char **eptr) { char *new_buf, *ptr, *dst; int inword; /* ---------------------------------------- */ new_buf = NULL; inword = FALSE; ptr = buf; while(!iseol(*ptr) && (*ptr != '\0')) { if (!isspace(*ptr) && !inword) { new_buf = (char *)malloc(sizeof(char) * (strlen(buf) +1)); if (new_buf == NULL) { lprintf(LOG_ERROR, "malloc() failed\n"); exit(EMALLOC); } inword = TRUE; dst = new_buf; } else if (isspace(*ptr)) { if (inword) { break; } inword = FALSE; } if (inword) { *dst++ = *ptr; } ptr++; } if (inword) { *dst = '\0'; } *eptr = ptr; return new_buf; } /* -------------------------------------------------------------------- */ /* Parse string of form: */ /* */ /* COMMANDDATA */ /* */ /* Copy data to newly allocated buffer and return */ /* a pointer to it. If no data available return NULL */ /* -------------------------------------------------------------------- */ #define iseol(x) ((x == '\n') || (x == '\r')) char *get_data(char *buf) { char *src, *dst, *data; int i, j, cmd; cmd = TRUE; src = buf; i = 0; j = 0; #if 0 while ((*src != '\n') && (*src != '\0') && (*src != '\r')) #else while ((!iseol(*src)) && (*src != '\0')) #endif { if ((cmd) && (*src == ' ')) { cmd = FALSE; j = i+1; i = 0; } else { i++; } src++; } if (j == 0) { return NULL; } data = (char *)malloc(sizeof(char) * (i +1)); if (dst == NULL) { lprintf(LOG_ERROR, "malloc() failed\n"); exit(EMALLOC); } dst = data; src = &buf[j]; #if 0 while ((*src != '\n') && (*src != '\0') && (*src != '\r')) #else while ((!iseol(*src)) && (*src != '\0')) #endif { *dst++ = *src++; } *dst = '\0'; return data; } /* -------------------------------------------------------------------- */ /* Return Values: */ /* */ /* 0 - If the current control record is incomplete */ /* 1 - if the current control record is complete */ /* */ /* -------------------------------------------------------------------- */ int is_complete(SMS_CONTROL_DATA *control_data) { if ((control_data->user == NULL) || (control_data->host == NULL) || (control_data->mail == NULL) || (control_data->alen == NULL) || (control_data->id == NULL) || (control_data->destination_service == NULL) || (control_data->destination_id == NULL) || (control_data->control_file == NULL) || (control_data->data_file == NULL)) { return 0; } return 1; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ SMS_CONTROL_DATA *init_control_data(void) { SMS_CONTROL_DATA *control_data; control_data = (SMS_CONTROL_DATA *)malloc(sizeof(SMS_CONTROL_DATA)); if (control_data == NULL) { lprintf(LOG_ERROR, "malloc() failed\n"); exit(EMALLOC); } control_data->user = NULL; control_data->host = NULL; control_data->mail = NULL; control_data->alen = NULL; control_data->id = NULL; control_data->destination_service = NULL; control_data->destination_id = NULL; control_data->control_file = NULL; control_data->data_file = NULL; control_data->len = 0; return control_data; } /* -------------------------------------------------------------------- */ /* Generate a control file in the incoming directory. */ /* The control file is empty. */ /* The control_data structure is updated to include the full path */ /* to the generated control file and it's corresponding data file. */ /* Note that memory is allocated for each of control_file, */ /* data_file and id. It is the responsibility of the caller to */ /* free this memory. */ /* */ /* Return Value: */ /* */ /* -1 error */ /* 0 Success */ /* -------------------------------------------------------------------- */ int gen_controlfile(SMS_CONTROL_DATA *control_data) { int n, fd; cleanup_files(control_data); control_data->id = (char *)malloc(sizeof(char) * 8); if (control_data->id == NULL) { lprintf(LOG_ERROR, "malloc() failed\n"); exit(EMALLOC); } control_data->control_file = (char *)malloc(sizeof(char) * (strlen(SMS_SPOOLDIR) + strlen(SMS_INCOMINGDIR) + 10)); if (control_data->control_file == NULL) { lprintf(LOG_ERROR, "malloc() failed\n"); exit(EMALLOC); } control_data->data_file = (char *)malloc(sizeof(char) * (strlen(SMS_SPOOLDIR) + strlen(SMS_INCOMINGDIR) + 10)); if (control_data->data_file == NULL) { lprintf(LOG_ERROR, "malloc() failed\n"); exit(EMALLOC); } strcpy(control_data->control_file, SMS_SPOOLDIR); libcommon_strfcat(control_data->control_file, SMS_INCOMINGDIR); libcommon_strfcat(control_data->control_file, ""); strcpy(control_data->data_file, SMS_SPOOLDIR); libcommon_strfcat(control_data->data_file, SMS_INCOMINGDIR); libcommon_strfcat(control_data->data_file, ""); for (n = getpid(); n < SMS_MAXID; n++) { sprintf(control_data->id, "%05d", n); sprintf(control_data->control_file, "%scf%s", control_data->control_file, control_data->id); sprintf(control_data->data_file, "%sdf%s", control_data->data_file, control_data->id); if (access(control_data->control_file, F_OK) == 0) { continue; } else { fd = open(control_data->control_file, O_CREAT|O_WRONLY|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (fd == -1) { if (errno == EEXIST) { continue; } lprintf(LOG_WARNING, "Cannot create file %s\n", control_data->control_file); free(control_data->control_file); free(control_data->data_file); free(control_data->id); return -1; } else { close(fd); break; } } } if (n == SMS_MAXID) { lprintf(LOG_WARNING, "Cannot create file as MAXID exceeded\n"); free(control_data->control_file); free(control_data->data_file); free(control_data->id); return -1; } return 0; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void cleanup_files(SMS_CONTROL_DATA *control_data) { if (control_data->control_file != NULL) { unlink(control_data->control_file); free(control_data->control_file); control_data->control_file = NULL; } if (control_data->data_file != NULL) { unlink(control_data->data_file); free(control_data->data_file); control_data->data_file = NULL; } if (control_data->id != NULL) { free(control_data->id); control_data->id = NULL; } } char *strip_eol(char *buf) { char *ptr; ptr = buf; while (*ptr != '\0') { if (iseol(*ptr)) { *ptr = '\0'; break; } ptr++; } return buf; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void gateway(int new_fd) { char buf[MAX_STRING_LEN], host_name[512], ip_address[512], *tmp_buf, *ptr, *cmd, *job, *queue, *command; int state, data_fd; SMS_CONTROL_DATA *control_data; control_data = init_control_data(); if (get_client_information(new_fd, host_name, ip_address) == 0) { lprintf(LOG_STANDARD, "Connection from %s [%s]\n", host_name, ip_address); } hprintf(new_fd, "400 SMS Gateway Ready\r\n"); while ((state != EXIT_STATE) && (state != ERROR_STATE) && (hgets(buf, MAX_STRING_LEN, new_fd) != NULL)) { state = NULL_STATE; cmd = get_field(buf, &ptr); if (cmd == NULL) { hprintf(new_fd, "502 '%s': command not understood.\r\n", strip_eol(buf)); continue; } if (strcasecmp(cmd, "MAIL") == 0) { control_data->mail = get_field(ptr, &ptr); if (control_data->mail == NULL) { state = UNKNOWN_STATE; } else { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { /* Check this is a valid */ /* email address. */ state = OK_STATE; } } } else if (strcasecmp(cmd, "HOST") == 0) { control_data->host = get_field(ptr, &ptr); if (control_data->host == NULL) { state = UNKNOWN_STATE; } else { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { /* Check that this is a valid */ /* hostname. */ state = OK_STATE; } } } else if (strcasecmp(cmd, "DEST") == 0) { control_data->destination_service = get_field(ptr, &ptr); if (control_data->destination_service == NULL) { state = UNKNOWN_STATE; } else { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { /* Check that this is a valid */ /* destination-service. */ if (get_varlist(smsd_services_heap, control_data->destination_service) != NULL) { state = OK_STATE; } else { state = UNKNOWN_STATE; } } } } else if (strcasecmp(cmd, "ID") == 0) { control_data->destination_id = get_field(ptr, &ptr); if (control_data->destination_id == NULL) { state = UNKNOWN_STATE; } else { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { /* Check that this is a valid */ /* destination-id. */ state = OK_STATE; } } } else if (strcasecmp(cmd, "DATA") == 0) { /* The control file only gets generated when */ /* data is received. It is placed in incoming */ /* All required fields have been sent and */ /* are included. */ control_data->alen = get_field(ptr, &ptr); if (control_data->alen == NULL) { state = UNKNOWN_STATE; } else { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { control_data->len = atoi(control_data->alen); /* WARNING - use strtol and strict */ /* checks */ /* Read 'len' bytes of data from fd */ /* and copy to data_file */ /* Open up the data_file - */ /* ensure we have a control file and */ /* all locks are setup */ if (gen_controlfile(control_data) == -1) { state = ERROR_STATE; } else { data_fd = open(control_data->data_file, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (data_fd < 0) { lprintf(LOG_ERROR, "Opening data_file '%s'\n", control_data->data_file); exit(-1); } if (copy_data(data_fd, new_fd, control_data->len) != 0) { lprintf(LOG_ERROR, "Copying data failed\n"); exit(-1); } close(data_fd); read(new_fd, &buf[0], 1); if (buf[0] == '\n') { state = OK_STATE; } else if (buf[0] == '\r') { read(new_fd, &buf[0], 1); if (buf[0] == '\n') { state = OK_STATE; } else { state = ERROR_STATE; } } else { state = ERROR_STATE; } } } } } else if (strcasecmp(cmd, "USER") == 0) { control_data->user = get_field(ptr, &ptr); if (control_data->user == NULL) { state = UNKNOWN_STATE; } else { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { /* Check that this is a valid */ /* user. */ state = OK_STATE; } } } else if (strcasecmp(cmd, "SEND") == 0) { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { if (is_complete(control_data)) { write_control_data(control_data); state = OK_STATE; } else { state = ERROR_STATE; } } } else if (strcasecmp(cmd, "SENJ") == 0) { job = get_field(ptr, &ptr); if (job == NULL) { state = UNKNOWN_STATE; } else { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { /* Check this is a valid */ /* job. */ if (is_complete(control_data)) { write_control_data(control_data); state = OK_STATE; } else { state = ERROR_STATE; } } free(job); } } else if (strcasecmp(cmd, "SENQ") == 0) { queue = get_field(ptr, &ptr); if (queue == NULL) { state = UNKNOWN_STATE; } else { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { /* Check this is a valid */ /* queue. */ if (is_complete(control_data)) { write_control_data(control_data); state = OK_STATE; } else { state = ERROR_STATE; } } free(queue); } } else if (strcasecmp(cmd, "SENA") == 0) { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { if (is_complete(control_data)) { write_control_data(control_data); state = OK_STATE; } else { state = ERROR_STATE; } } } else if (strcasecmp(cmd, "STAJ") == 0) { job = get_field(ptr, &ptr); if (job == NULL) { state = UNKNOWN_STATE; } else { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { state = UNKNOWN_STATE; } else { /* Check this is a valid */ /* job. */ state = OK_STATE; } free(job); } } else if (strcasecmp(cmd, "STAQ") == 0) { queue = get_field(ptr, &ptr); if (queue == NULL) { state = UNKNOWN_STATE; } else { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { /* Check this is a valid */ /* queue. */ state = OK_STATE; } free(queue); } } else if (strcasecmp(cmd, "STAT") == 0) { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { state = OK_STATE; } } else if (strcasecmp(cmd, "INFO") == 0) { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { hprintf(new_fd, "231- SMS Server info:\r\n"); hprintf(new_fd, " Version: 0.1\r\n"); display_current(new_fd, control_data); hprintf(new_fd, "231 End of Info.\r\n"); } } else if (strcasecmp(cmd, "QUIT") == 0) { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { hprintf(new_fd, "220 Goodbye.\r\n"); state = EXIT_STATE; } } else if (strcasecmp(cmd, "HELP") == 0) { command = get_field(ptr, &ptr); if (command == NULL) { hprintf(new_fd, "230- The following commands are recognized\r\n"); hprintf(new_fd, " USER DATA MAIL HOST DEST\r\n"); hprintf(new_fd, " SEND SENJ SENQ SENA \r\n"); hprintf(new_fd, " STAT STAJ STAQ ID \r\n"); hprintf(new_fd, " QUIT INFO HELP \r\n"); hprintf(new_fd, "230 End of Help.\r\n"); } else { tmp_buf = get_field(ptr, &ptr); if (tmp_buf != NULL) { free(tmp_buf); state = UNKNOWN_STATE; } else { if (strcasecmp(command, "USER") == 0) { hprintf(new_fd, "214 Syntax: USER username\r\n"); } else if (strcasecmp(command, "HOST") == 0) { hprintf(new_fd, "214 Syntax: HOST hostname\r\n"); } else if (strcasecmp(command, "DEST") == 0) { hprintf(new_fd, "214 Syntax: DEST service\r\n"); } else if (strcasecmp(command, "ID") == 0) { hprintf(new_fd, "214 Syntax: ID id\r\n"); } else if (strcasecmp(command, "DATA") == 0) { hprintf(new_fd, "214 Syntax: DATA len <\\r\\n> data <\\r\\n>\r\n"); } else if (strcasecmp(command, "MAIL") == 0) { hprintf(new_fd, "214 Syntax: MAIL address\r\n"); } else if (strcasecmp(command, "QUIT") == 0) { hprintf(new_fd, "214 Syntax: QUIT (terminate service)\r\n"); } else { hprintf(new_fd, "502 '%s': command unknown.\r\n", strip_eol(buf)); } } free(command); } } else { state = UNKNOWN_STATE; } if (state == ERROR_STATE) { hprintf(new_fd, "510 Error Connection Terminated.\r\n"); } else if (state == UNKNOWN_STATE) { hprintf(new_fd, "511 '%s': command not understood.\r\n", strip_eol(buf)); } else if (state == OK_STATE) { hprintf(new_fd, "210 Ok.\r\n"); } } if (state == ERROR_STATE) { cleanup_files(control_data); } free(control_data); } /* -------------------------------------------------------------------- */ /* Read 'len' bytes of data from src_fd and copy to 'dst_fd' */ /* Return Values */ /* */ /* 0 Success */ /* -1 Failure */ /* -------------------------------------------------------------------- */ int copy_data(int dst_fd, int src_fd, long dlen) { int len, sent; char *ptr; char *mbuf; mbuf = (char *)malloc(sizeof(char) * 1024); if (mbuf == NULL) { lprintf(LOG_ERROR, "malloc() failed\n"); exit(EMALLOC); } { len = read(src_fd, mbuf, ((dlen<1024)?(dlen):(1024))); if (len < 0) { if (errno != EINTR) { lprintf(LOG_ERROR, "read() failed\n"); return(-1); } } } while (len < 0); while(len) { dlen -= len; ptr = mbuf; sent = 0; while (len - sent) { len -= sent; ptr += sent; { sent = write(dst_fd, ptr, len); if (sent < 0) { if (errno != EINTR) { lprintf(LOG_ERROR, "write() failed\n"); return(-1); } } } while (len < 0); if (sent == 0) { lprintf(LOG_ERROR, "write() failed\n"); return(-1); } } if (dlen <= 0) { break; } { len = read(src_fd, mbuf, ((dlen<1024)?(dlen):(1024))); if (len < 0) { if (errno != EINTR) { lprintf(LOG_ERROR, "read() failed\n"); return(-1); } } } while (len < 0); } free(mbuf); return 0; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void usage(char *file) { lprintf(LOG_STANDARD, "Usage: %s [-l loglevel] [-p port]\n", file); lprintf(LOG_STANDARD, " %s -v\n", file); } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void release_lock(void) { resource_unlock(smsd_lockfile); } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ int main(int argc, char *argv[]) { int c, port; char *ptr, *progname; struct sockaddr sa_client; progname = strrchr(argv[0], '/'); if (progname == NULL) { progname = argv[0]; } else { progname++; } /* ---------------------------- */ set_logfile(LOGFILE); set_loglevel(LOGLEVEL); set_consolelog(TRUE); /* ---------------------------- */ port = 0; while ((c = getopt (argc, argv, "p:l:v")) != -1) { switch (c) { case 'p': port = (int)strtol(optarg, &ptr, 10); break; case 'l': set_loglevel((int)strtol(optarg, &ptr, 10)); if (ptr == optarg) { lprintf(LOG_ERROR, "Option l requires an argument\n"); usage(progname); exit(-1); } break; case 'v': lprintf(LOG_STANDARD, "%s %s\n", progname, VERSION); exit(0); case '?': lprintf(LOG_ERROR, "Unknown option `-%c'\n", optopt); usage(progname); exit(-1); default: abort (); } } /* ---------------------------- */ if (read_resource_file(DAEMONCONFIGFILE, resource_list, 1) == RESOURCE_FILE_ERROR) { lprintf(LOG_ERROR, "Failed to read resource file '%s'\n", DAEMONCONFIGFILE); exit(-1); } if (port != 0) { SMS_PORT = port; } /* ---------------------------- */ if ((argc - optind) != 0) { usage(progname); exit(-1); } /* ---------------------------- */ c = sizeof(sa_client); if (getpeername(fileno(stdin), &sa_client, &c) < 0) { /* getpeername() fails if fd isn't a */ /* socket. If this is the case we can */ /* assume that we aren't running */ /* from inetd and should startup and */ /* run as a daemon ourselves. */ strcpy(smsd_lockfile, SMS_SPOOLDIR); libcommon_strfcat(smsd_lockfile, SMS_LOCKDIR); libcommon_strfcat(smsd_lockfile, "smsd.pid"); lprintf(LOG_STANDARD, "Starting SMSD Standalone Server deamon...\n"); if (server_main(SMS_PORT, gateway, smsd_lockfile) == -1) { lprintf(LOG_STANDARD, "Failed to start SMSD Standalone Server deamon\n"); exit(-1); } } else { set_consolelog(FALSE); lprintf(LOG_STANDARD, "Starting SMSD Server as an INETD service\n"); gateway(fileno(stdin)); } return 0; }