smsd.c
上传用户:mei_mei897
上传日期:2007-01-05
资源大小:82k
文件大小:19k
- /* -------------------------------------------------------------------- */
- /* SMS Client, send messages to mobile phones and pagers */
- /* */
- /* smsd.c */
- /* */
- /* Copyright (C) 1997,1998 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 <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <errno.h>
- #if !defined(AIX) && !defined(SOLARIS) && !defined(UNIXWARE)
- #include <getopt.h>
- #endif
- #include "server.h"
- #include "logfile.h"
- #include "common.h"
- /* -------------------------------------------------------------------- */
- #if !defined(MSMSDLOGFILE)
- #error "MSMSDLOGFILE undefined"
- #else
- #define LOGFILE MSMSDLOGFILE
- #endif
- #if !defined(MSMSDLOGLEVEL)
- #error "MSMSDLOGLEVEL undefined"
- #else
- #define LOGLEVEL MSMSDLOGLEVEL
- #endif
- /* -------------------------------------------------------------------- */
- #define SMS_PORT 4563 /* Standard port number */
- /* assigned for sms traffic */
- #define SMS_SPOOLDIR "/var/spool/sms"
- #define SMS_INCOMINGDIR "incoming"
- #define SMS_SERVICESDIR "services"
- #define SMS_MAXID 32000
- /* -------------------------------------------------------------------- */
- #define ERROR_STATE -2
- #define EXIT_STATE -1
- #define NULL_STATE 0
- #define UNKNOWN_STATE 1
- /* -------------------------------------------------------------------- */
- struct sms_control_data_struct
- {
- char *user,
- *host,
- *mail,
- *alen,
- *destination,
- *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;
- /* -------------------------------------------------------------------- */
- #define SAFEOUTPUT(X) ((X == NULL)?("<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);
- char *get_data(char *buf);
- int gen_controlfile(SMS_CONTROL_DATA *control_data);
- void gateway(int new_fd);
- int copy_data(int dst_fd, int src_fd, long dlen);
- void usage(char *file);
- /* -------------------------------------------------------------------- */
- /* -------------------------------------------------------------------- */
- void display_current(int fd, SMS_CONTROL_DATA *control_data)
- {
- hprintf(fd, " Current Control Record info:rn");
- hprintf(fd, " Username: %srn", SAFEOUTPUT(control_data->user));
- hprintf(fd, " Hostname: %srn", SAFEOUTPUT(control_data->host));
- hprintf(fd, " Mail on Delivery: %srn", SAFEOUTPUT(control_data->mail));
- hprintf(fd, " Destination: %srn", SAFEOUTPUT(control_data->destination));
- hprintf(fd, " Control File: %srn", SAFEOUTPUT(control_data->control_file));
- hprintf(fd, " Data File: %srn", SAFEOUTPUT(control_data->data_file));
- hprintf(fd, " ID: %srn", SAFEOUTPUT(control_data->id));
- hprintf(fd, " Length: %ldrn", 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 %sn", control_data->control_file);
- exit(-1);
- }
- fprintf(fp, "{n");
- fprintf(fp, "tUsername = "%s";n", SAFECONTROLOUTPUT(control_data->user));
- fprintf(fp, "tHostname = "%s";n", SAFECONTROLOUTPUT(control_data->host));
- fprintf(fp, "tMail_on_Delivery = "%s";n", SAFECONTROLOUTPUT(control_data->mail));
- fprintf(fp, "tDestination = "%s";n", SAFECONTROLOUTPUT(control_data->destination));
- fprintf(fp, "tControl_File = "%s";n", SAFECONTROLOUTPUT(control_data->control_file));
- fprintf(fp, "tData_File = "%s";n", SAFECONTROLOUTPUT(control_data->data_file));
- fprintf(fp, "tID = "%s";n", SAFECONTROLOUTPUT(control_data->id));
- fprintf(fp, "tLength = "%ld"n";, control_data->len);
- fprintf(fp, "}n");
- fclose(fp);
- }
- /* -------------------------------------------------------------------- */
- /* Parse string of form: */
- /* */
- /* COMMAND<SP>DATA<EOL> */
- /* */
- /* Copy data to newly allocated buffer and return */
- /* a pointer to it. If no data available return NULL */
- /* -------------------------------------------------------------------- */
- char *get_data(char *buf)
- {
- char *src,
- *dst,
- *data;
- int i, j,
- cmd;
- cmd = TRUE;
- src = buf;
- i = 0;
- j = 0;
- while ((*src != 'n') && (*src != ' ') && (*src != 'r'))
- {
- if ((cmd) && (*src == ' '))
- { cmd = FALSE;
- j = i+1;
- i = 0;
- }
- else
- { i++;
- }
- src++;
- }
- #if 0
- if ((j == 0) ||
- ((i == 1) && ((*src == 'n') || (*src == 'r') || (isspace(*src)) || (*src == ' '))))
- { return NULL;
- }
- #else
- if (j == 0)
- { return NULL;
- }
- #endif
- data = (char *)malloc(sizeof(char) * i + 1);
- if (dst == NULL)
- { lprintf(LOG_ERROR, "Allocating memoryn");
- exit(-1);
- }
- dst = data;
- src = &buf[j];
- while ((*src != 'n') && (*src != ' ') && (*src != 'r'))
- {
- *dst++ = *src++;
- }
- *dst = ' ';
- return data;
- }
- 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 == 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, "Allocating memoryn");
- exit(-1);
- }
- control_data->user = NULL;
- control_data->host = NULL;
- control_data->mail = NULL;
- control_data->alen = NULL;
- control_data->id = NULL;
- control_data->destination = 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, "Allocating memoryn");
- exit(-1);
- }
- control_data->control_file = (char *)malloc(sizeof(char) * (sms_strlen(SMS_SPOOLDIR) +
- sms_strlen(SMS_INCOMINGDIR) + 10));
- if (control_data->control_file == NULL)
- {
- lprintf(LOG_ERROR, "Allocating memoryn");
- exit(-1);
- }
- control_data->data_file = (char *)malloc(sizeof(char) * (sms_strlen(SMS_SPOOLDIR) +
- sms_strlen(SMS_INCOMINGDIR) + 10));
- if (control_data->data_file == NULL)
- {
- lprintf(LOG_ERROR, "Allocating memoryn");
- exit(-1);
- }
- sms_strcpy(control_data->control_file, SMS_SPOOLDIR);
- sms_strcpy(control_data->data_file, SMS_SPOOLDIR);
- if (control_data->control_file[sms_strlen(control_data->control_file) -1] != '/')
- {
- sms_strcat(control_data->data_file, "/");
- sms_strcat(control_data->control_file, "/");
- }
- sms_strcat(control_data->control_file, SMS_INCOMINGDIR);
- sms_strcat(control_data->data_file, SMS_INCOMINGDIR);
- if (control_data->control_file[sms_strlen(control_data->control_file) -1] != '/')
- {
- sms_strcat(control_data->data_file, "/");
- sms_strcat(control_data->control_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 %sn", 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 exceededn");
- 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;
- }
- }
- /* -------------------------------------------------------------------- */
- /* -------------------------------------------------------------------- */
- void gateway(int new_fd)
- {
- char buf[MAX_STRING_LEN],
- host_name[512],
- ip_address[512];
- 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 Readyrn");
- while ((state != EXIT_STATE) &&
- (state != ERROR_STATE) &&
- (hgets(buf, MAX_STRING_LEN, new_fd) != NULL))
- {
- state = NULL_STATE;
- if (strncasecmp(buf, "MAIL", 4) == 0)
- {
- control_data->mail = get_data(buf);
- if (control_data->mail == NULL)
- { state = ERROR_STATE;
- }
- }
- else if (strncasecmp(buf, "HOST", 4) == 0)
- {
- control_data->host = get_data(buf);
- if (control_data->host == NULL)
- { state = ERROR_STATE;
- }
- }
- else if (strncasecmp(buf, "DEST", 4) == 0)
- {
- control_data->destination = get_data(buf);
- if (control_data->destination == NULL)
- { state = ERROR_STATE;
- }
- }
- else if (strncasecmp(buf, "DATA", 4) == 0)
- {
- control_data->alen = get_data(buf);
- if (control_data->alen == NULL)
- { state = ERROR_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 %sn", control_data->data_file);
- exit(-1);
- }
- if (copy_data(data_fd, new_fd, control_data->len) != 0)
- { lprintf(LOG_ERROR, "copying datan");
- exit(-1);
- }
- close(data_fd);
- read(new_fd, &buf[0], 1);
- if (buf[0] == 'n')
- {
- }
- else if (buf[0] == 'r')
- {
- read(new_fd, &buf[0], 1);
- if (buf[0] == 'n')
- {
- }
- else
- { state = ERROR_STATE;
- }
- }
- else
- { state = ERROR_STATE;
- }
- }
- }
- }
- else if (strncasecmp(buf, "USER", 4) == 0)
- {
- control_data->user = get_data(buf);
- if (control_data->user == NULL)
- { state = ERROR_STATE;
- }
- }
- else if (strncasecmp(buf, "SEND", 4) == 0)
- {
- if (is_complete(control_data))
- {
- write_control_data(control_data);
- }
- else
- { state = ERROR_STATE;
- }
- }
- else if (strncasecmp(buf, "SENJ", 4) == 0)
- {
- if (is_complete(control_data))
- {
- write_control_data(control_data);
- }
- else
- { state = ERROR_STATE;
- }
- }
- else if (strncasecmp(buf, "SENQ", 4) == 0)
- {
- if (is_complete(control_data))
- {
- write_control_data(control_data);
- }
- else
- { state = ERROR_STATE;
- }
- }
- else if (strncasecmp(buf, "SENA", 4) == 0)
- {
- if (is_complete(control_data))
- {
- write_control_data(control_data);
- }
- else
- { state = ERROR_STATE;
- }
- }
- else if (strncasecmp(buf, "STAJ", 4) == 0)
- {
- }
- else if (strncasecmp(buf, "STAQ", 4) == 0)
- {
- }
- else if (strncasecmp(buf, "STAT", 4) == 0)
- {
- }
- else if (strncasecmp(buf, "INFO", 4) == 0)
- {
- if (((buf[4] == 'r') && (buf[5] == 'n')) ||
- (buf[4] == 'n'))
- {
- hprintf(new_fd, "231- SMS Server info:rn");
- hprintf(new_fd, " Version: 0.1rn");
- display_current(new_fd, control_data);
- hprintf(new_fd, "231 End of Info.rn");
- continue;
- }
- else
- {
- }
- }
- else if (strncasecmp(buf, "QUIT", 4) == 0)
- {
- hprintf(new_fd, "220 Goodbye.rn");
- state = EXIT_STATE;
- continue;
- }
- else if (strncasecmp(buf, "HELP", 4) == 0)
- {
- if (((buf[4] == 'r') && (buf[5] == 'n')) ||
- (buf[4] == 'n'))
- {
- hprintf(new_fd, "230- The following commands are recognizedrn");
- hprintf(new_fd, " USER DATA MAIL HOST DESTrn");
- hprintf(new_fd, " SEND SENJ SENQ SENA rn");
- hprintf(new_fd, " STAT STAJ STAQ rn");
- hprintf(new_fd, " QUIT INFO HELP rn");
- hprintf(new_fd, "230 End of Help.rn");
- continue;
- }
- else
- {
- }
- }
- else
- { state = UNKNOWN_STATE;
- }
- if (state == ERROR_STATE)
- { hprintf(new_fd, "510 Error Connection Terminated.rn");
- }
- else if (state == UNKNOWN_STATE)
- { hprintf(new_fd, "511 Error Command not understood.rn");
- }
- else
- { hprintf(new_fd, "210 Ok.rn");
- }
- }
- 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, "Allocating memoryn");
- exit(-1);
- }
- {
- len = read(src_fd, mbuf, ((dlen<1024)?(dlen):(1024)));
- if (len < 0)
- { if (errno != EINTR)
- { lprintf(LOG_ERROR, "readn");
- 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");
- return(-1);
- }
- }
- } while (len < 0);
- if (sent == 0)
- { lprintf(LOG_ERROR, "writen");
- 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");
- return(-1);
- }
- }
- } while (len < 0);
- }
- free(mbuf);
- return 0;
- }
- /* -------------------------------------------------------------------- */
- /* -------------------------------------------------------------------- */
- void usage(char *file)
- {
- lprintf(LOG_STANDARD, "Usage: %s [-l loglevel] [-p port]n", file);
- }
- /* -------------------------------------------------------------------- */
- /* -------------------------------------------------------------------- */
- int main(int argc, char *argv[])
- {
- int c,
- port;
- char *ptr;
- struct sockaddr
- sa_client;
- /* ---------------------------- */
- set_logfile(LOGFILE);
- set_loglevel(LOGLEVEL);
- set_consolelog(TRUE);
- /* ---------------------------- */
- port = SMS_PORT;
- while ((c = getopt (argc, argv, "p:l:")) != -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 argumentn");
- usage(argv[0]);
- exit(-1);
- }
-
- break;
- case '?':
- lprintf(LOG_ERROR, "Unknown option `-%c'n", optopt);
- usage(argv[0]);
- exit(-1);
- default:
- abort ();
- }
- }
- if ((argc - optind) != 0)
- { usage(argv[0]);
- 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 */
- /* as and run as a daemon ourselves. */
- lprintf(LOG_STANDARD, "Starting SMSD Standalone Server deamon...n");
- if (server_main(port, gateway) != 0)
- { lprintf(LOG_STANDARD, "Failed to start SMSD Standalone Server deamonn");
- exit(-1);
- }
- }
- else
- { set_consolelog(FALSE);
- lprintf(LOG_STANDARD, "Starting SMSD Server as an INETD servicen");
- gateway(fileno(stdin));
- }
- return 0;
- }