sendsms.c
上传用户:eo_sii
上传日期:2007-01-05
资源大小:91k
文件大小:22k
- /*==========================================================
- * Program : sendsms.c Project : smslink
- * Author : Philippe Andersson.
- * Date : 01/03/00
- * Version : 0.10b
- * Notice : (c) Les Ateliers du Heron, 1998 for Scitex Europe, S.A.
- * Comment : SMS client.
- *
- * Modification History :
- * - 0.01a (28/09/98) : Initial release.
- * - 0.02a (21/10/98) : Adapted client to modifications in server
- * consecutive to full GSM dialog implementation.
- * ++++ Switch to Beta ++++
- * - 0.03b (21/10/98) : First Beta release.
- * - 0.04b (23/10/98) : Added handling of the 'user' parameter.
- * - 0.05b (28/10/98) : Improved error reporting regarding
- * host name resolution failure.
- * - 0.06b (03/11/98) : Added -f parameter (load message from
- * a text file).
- * - 0.07b (06/02/99) : Added "-f -" option for stdin processing.
- * Added Solaris compatibility. (contrib. by Philipp Klaus).
- * - 0.08b (16/02/99) : Adapted "slurping" of server announce
- * after Ph. Klaus' modifications. Also solved a problem
- * in the HP-UX port (PATH_MAX needs limits.h on HP-UX).
- * - 0.09b (20/05/99) : Corrected a bug that prevented comp-
- * ilation on LINUX_LC6 platform.
- * - 0.10b (01/03/00) : Replaced the "old" slurp_n_catch() by
- * a new version copied on get_gsm_answer(). This one should
- * be more robust and less sensitive to the amount of data
- * sent back by the server.
- *========================================================*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h> /* for strcpy & friends */
- #ifdef HPUX
- # include <sys/unistd.h> /* for getopt () */
- # include <limits.h> /* for PATH_MAX */
- #else
- # include <unistd.h> /* for getopt () */
- # ifdef LINUX_LC6
- # include <limits.h>
- # include <linux/limits.h>
- # endif
- #endif /* ifdef HPUX */
- #include <netdb.h> /* for gethostbyname() */
- #include <pwd.h> /* for getpwuid() */
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <sys/types.h>
- #include <sys/time.h> /* for the struct timeval */
- #include <sys/ioctl.h> /* for the ioctl() call */
- #ifdef SOLARIS
- # include <sys/filio.h>
- #endif
- /*--------------------------------------Personal includes */
- #include "sendsms.h"
- /*========================================================*/
- /********** LOCAL DEFINES ********/
- /*========================================================*/
- /* For debugging purposes only - comment out for normal compile */
- /* #define INCL_DEBUG_CODE */
- /*========================================================*/
- /********** GLOBAL VARIABLES ********/
- /*========================================================*/
- /*========================================================*/
- /********** FUNCTIONS ********/
- /*========================================================*/
- void syserr (char *msg)
- {
- extern int errno, sys_nerr;
- #ifdef LINUX_LC6
- extern const char *const sys_errlist[];
- #else
- extern char * sys_errlist[];
- #endif /* #ifdef LINUX_LC6 */
- fprintf (stderr, "ERROR %s", msg);
- if (errno > 0 && errno < sys_nerr)
- fprintf (stderr, " (%d ; %s)n", errno, sys_errlist[errno]);
- else
- fprintf (stderr, "n");
- exit (1);
- } /* syserr () */
- /*========================================================*/
- void tellsock (int sock, char *string)
- {
- int length;
-
- length = strlen (string);
- if (write (sock, string, length) != length)
- syserr ("sendsms: error while writing to socket");
- } /* tellsock () */
- /*========================================================*/
- void quote (char *string)
- /* we take it for granted that we malloc'ed at least 2 char more
- than max length */
- {
- char *ptr;
-
- ptr = string + strlen (string);
- /* shift all chars 1 place to the right */
- while (ptr >= string) {
- ptr [1] = ptr[0];
- ptr--;
- }
- string[0] = '"';
- ptr = string + strlen (string);
- ptr[1] = ' ';
- ptr[0] = '"';
- } /* quote () */
- /*========================================================*/
- int desLF (char *string)
- {
- char *ptr;
-
- if ((ptr = strchr (string, 'n')) != NULL) {
- ptr[0] = ' ';
- }
-
- return (strlen (string));
- } /* desLF () */
- /*========================================================*/
- int is_dotted_quad (char *string)
- {
- int is_dq;
- char *s;
- int ntok = 0;
- char *ptok = NULL;
- long int ip_byte;
- char **endptr;
- char *dummyp;
-
- /*--------------------------------------Initializations */
- s = (char *) malloc ((strlen (string) + 1) * sizeof (char));
- strcpy (s, string);
- /*--------------------------------------------Main Loop */
- /* no point going any further if the 1st char. is not a digit */
- is_dq = isdigit (string[0]);
- if (is_dq) {
- ptok = strtok (s, ".");
- while (ptok != NULL) {
- ntok++;
- #ifdef INCL_DEBUG_CODE
- printf ("got token #%d : <%s>n", ntok, ptok);
- #endif
- dummyp = ptok + strlen (ptok);
- endptr = &dummyp;
- ip_byte = strtol (ptok, endptr, 10);
- if (strlen (*endptr) != 0) {
- #ifdef INCL_DEBUG_CODE
- printf ("error on token #%d : can't convert <%s>n", ntok, *endptr);
- #endif
- is_dq = FALSE;
- }
- ptok = strtok (NULL, ".");
- }
- if (ntok != 4) {
- is_dq = FALSE;
- }
- } /* if (is_dq) */
- /*------------------------------------------Conclusions */
- free (s);
- /*-------------------------------------------------Exit */
- return (is_dq);
- } /* is_dotted_quad () */
- /*========================================================*/
- unsigned long int resolve (char *host)
- /* return the host ip address in network format */
- {
- struct hostent *h_ent;
- struct in_addr target_ip;
- char **addrs;
- char *scratch;
-
- if (is_dotted_quad (host)) {
- #ifdef INCL_DEBUG_CODE
- printf ("I think I got an IP addressn");
- #endif
- if (inet_aton (host, &target_ip) == 0)
- syserr ("sendsms: invalid server IP address");
- }
- else {
- #ifdef INCL_DEBUG_CODE
- printf ("I think I got a host namen");
- #endif
- if ((h_ent = gethostbyname (host)) == NULL) {
- scratch = (char *) malloc ((MINIBUFF + 1) * sizeof (char));
- sprintf (scratch, "sendsms: can't resolve hostname (%s)", host);
- herror (scratch);
- free (scratch);
- exit (1);
- }
- /* lines below cf. "Beginning Linux Progr.", pp. 468-473 */
- addrs = h_ent->h_addr_list;
- target_ip = *(struct in_addr *)*addrs;
- #ifdef INCL_DEBUG_CODE
- printf ("server IP address is: [%s]n", inet_ntoa (target_ip));
- #endif
- } /* if (isdigit (host[0])) */
- return (target_ip.s_addr);
- } /* resolve () */
- /*========================================================*/
- int load_from_file (char *msg, char *file)
- {
- FILE *infile;
- char *buff;
-
- /*--------------------------------------Initializations */
- buff = (char *) malloc ((BUFFSIZE + 1) * sizeof (char));
- if (!buff)
- syserr ("sendsms: can't malloc");
- msg[0] = ' ';
-
- /*------------------------------------------------------*/
- /* open file */
- if (file[0] == '-' && file[1] == ' ') {
- infile = stdin;
- } else {
- if ((infile = fopen (file, "r")) == NULL)
- syserr ("sendsms: can't open input file");
- }
-
- /* read from file */
- while (fgets (buff, BUFFSIZE, infile)) {
- desLF (buff);
- if ((strlen (msg) + strlen (buff)) > MAXMSGLEN) {
- strncat (msg, buff, (MAXMSGLEN - strlen (msg)));
- fprintf (stderr, "Warning: input file too long - truncation will occurn");
- }
- else {
- strcat (msg, buff);
- }
- } /* while () */
-
- /* close file */
- if (infile != stdin)
- fclose (infile);
-
- /*------------------------------------------------------*/
- return (strlen (msg));
- } /* load_from_file () */
- /*========================================================*/
- int slurp_n_catch (int fd, int resptime, char *catch)
- {
- int nread, retval, previous, found;
- fd_set inputs;
- struct timeval timeout;
- char *buffer;
-
- /*--------------------------------------Initializations */
- nread = previous = 0;
- found = FALSE;
-
- FD_ZERO (&inputs);
- FD_SET (fd, &inputs);
-
- timeout.tv_sec = 10;
- timeout.tv_usec = 0;
-
- /* wait for data to arrive on the line */
- retval = select (FD_SETSIZE, &inputs, NULL, NULL, &timeout);
- switch (retval) {
- case 0:
- fprintf (stderr, "sendsms: WARNING: timeout while waiting for server reply.");
- break;
-
- case -1:
- syserr ("sendsms: call to select() failed");
- break;
-
- default:
- if (FD_ISSET (fd, &inputs)) {
- /* first wait for all data to be ready */
- ioctl (fd, FIONREAD, &nread);
- while (nread != previous) {
- sleep (resptime);
- previous = nread;
- ioctl (fd, FIONREAD, &nread);
- } /* while (nread != previous) */
- /* we know what's the data size - alloc space for it */
- buffer = (char *) malloc ((nread + 1) * sizeof (char));
- if (!buffer)
- syserr ("sendsms: can't allocate buffer space");
- /* now we can finally read this data */
- nread = read (fd, buffer, nread);
- switch (nread) {
- case 0:
- /* EOF */
- buffer[nread] = ' ';
- fprintf (stderr, "sendsms: no data from server waiting for [%s].",
- catch);
- break;
-
- case -1:
- syserr ("sendsms: error while reading answer from server");
- break;
-
- default:
- buffer[nread] = ' ';
- #ifdef INCL_DEBUG_CODE
- fprintf (stderr, "pid<%d> Got : [%s] (%d char)n", getpid (), buffer,
- nread);
- #endif
- /* here we could pre-process it (remove Ctrl-Z) */
- /* look for catch */
- found = (strstr (buffer, catch) != NULL);
- break;
- } /* switch (nread) */
- } /* if (FD_ISSET... */
- free (buffer);
- break;
- } /* switch (retval) */
- /*------------------------------------------------------*/
- #ifdef INCL_DEBUG_CODE
- printf ("catch found: [%s]n", found ? "yes" : "no");
- #endif
- /*----------------------------------Conclusion and exit */
- return (found);
- } /* slurp_n_catch () */
- /*========================================================*/
- int get_gsm_answer (int fd, char *answer, int size, int resptime)
- {
- int nread, retval, previous;
- fd_set inputs;
- struct timeval timeout;
- char *buffer;
-
- /*--------------------------------------Initializations */
- nread = previous = 0;
-
- FD_ZERO (&inputs);
- FD_SET (fd, &inputs);
-
- timeout.tv_sec = 10;
- timeout.tv_usec = 0;
-
- /* wait for data to arrive on the line */
- retval = select (FD_SETSIZE, &inputs, NULL, NULL, &timeout);
- switch (retval) {
- case 0:
- fprintf (stderr, "timeout while waiting for GSM answer.n");
- break;
-
- case -1:
- syserr ("sendsms: call to select() failed");
- break;
-
- default:
- if (FD_ISSET (fd, &inputs)) {
- /* first wait for all data to be ready */
- ioctl (fd, FIONREAD, &nread);
- while (nread != previous) {
- sleep (resptime);
- previous = nread;
- ioctl (fd, FIONREAD, &nread);
- } /* while (nread != previous) */
- /* we know what's the data size - alloc space for it */
- buffer = (char *) malloc ((nread + 1) * sizeof (char));
- if (!buffer)
- syserr ("sendsms: can't allocate buffer space");
- /* now we can finally read this data */
- nread = read (fd, buffer, nread);
- switch (nread) {
- case 0:
- /* EOF */
- fprintf (stderr, "got no data from GSM module.n");
- break;
-
- case -1:
- syserr ("sendsms: error while reading answer from GSM");
- break;
-
- default:
- buffer[nread] = ' ';
- #ifdef INCL_DEBUG_CODE
- fprintf (stderr, "pid<%d> Got : [%s] (%d char)n", getpid (), buffer, nread);
- #endif
- /* here we could pre-process it (remove Ctrl-Z) */
- /* copy it over to out string param. */
- if (nread > size) {
- fprintf (stderr, "too much data, truncation will occurn");
- strncpy (answer, buffer, size);
- answer[size] = ' ';
- }
- else {
- strcpy (answer, buffer);
- }
- break;
- } /* switch (nread) */
- } /* if (FD_ISSET... */
- free (buffer);
- break;
- } /* switch (retval) */
- return (nread);
- } /* get_gsm_answer () */
- /*========================================================*/
- /*========================================================*/
- /********** MAIN PROGRAM LOOP ********/
- /*========================================================*/
- main (int argc, char *argv[])
- {
- extern char *optarg;
- extern int optind, optopt;
- int c; /* option char returned by getopt */
- int errflag = 0; /* error in command line options */
- char *destgsm;
- char *user;
- char *smsc;
- char *message;
- char *msgfile;
- char *host_or_ip;
- struct in_addr server_ip;
- struct sockaddr_in sockaddr;
- int sockfd;
- int addrlen;
- char *cmdline;
- int retval;
- char *sendlog;
- struct passwd *pwduentry;
- /*--------------------------------------Initialisations */
- cmdline = (char *) malloc ((BUFFSIZE + 1) * sizeof (char));
- cmdline[0] = ' ';
- destgsm = (char *) malloc ((MAXPHNUMLEN + 1) * sizeof (char));
- destgsm[0] = ' ';
- smsc = (char *) malloc ((MAXPHNUMLEN + 1) * sizeof (char));
- smsc[0] = ' ';
- msgfile = (char *) malloc ((PATH_MAX + 1) * sizeof (char));
- msgfile[0] = ' ';
- /* MAXUIDLEN + 3 to leave space for the quotes */
- user = (char *) malloc ((MAXUIDLEN + 3) * sizeof (char));
- user[0] = ' ';
- /* MAXMSGLEN + 3 to leave space for the quotes */
- message = (char *) malloc ((MAXMSGLEN + 3) * sizeof (char));
- message[0] = ' ';
- host_or_ip = (char *) malloc ((MINIBUFF + 1) * sizeof (char));
- host_or_ip[0] = ' ';
- sendlog = (char *) malloc ((BIGBUFF + 1) * sizeof (char));
- sendlog[0] = ' ';
- /* default values for parameters */
- if ((pwduentry = getpwuid (getuid ())) == NULL)
- syserr ("sendsms: can't get user entry in passwd file");
- if (strlen (pwduentry->pw_name) > MAXUIDLEN) {
- strncpy (user, pwduentry->pw_name, MAXUIDLEN);
- fprintf (stderr, "sendsms: WARNING: username too long (max. %d), truncatedn",
- MAXUIDLEN);
- }
- else {
- strcpy (user, pwduentry->pw_name);
- }
- quote (user);
- /*-------------------------Command line processing loop */
- while ((c = getopt (argc, argv, ":d:s:m:f:u:")) != -1) {
- switch (c) {
- case 'd': /* destination GSM number */
- if (strlen (optarg) > MAXPHNUMLEN) {
- fprintf (stderr, "sendsms: -d parameter too long, max. is %dn",
- MAXPHNUMLEN);
- errflag++;
- }
- else
- strcpy (destgsm, optarg);
- break;
- case 's': /* SMSC number */
- if (strlen (optarg) > MAXPHNUMLEN) {
- fprintf (stderr, "sendsms: -s parameter too long, max. is %dn",
- MAXPHNUMLEN);
- errflag++;
- }
- else
- strcpy (smsc, optarg);
- break;
- case 'm': /* message to send */
- if (strlen (optarg) > MAXMSGLEN) {
- fprintf (stderr, "sendsms: warning: message too long (max. %d char.) - truncatedn",
- MAXMSGLEN);
- strncpy (message, optarg, MAXMSGLEN);
- }
- else
- strcpy (message, optarg);
- quote (message);
- break;
- case 'f': /* file to load message from */
- if (strlen (optarg) > PATH_MAX) {
- fprintf (stderr, "sendsms: warning: filename too long (max. %d char.)n",
- PATH_MAX);
- errflag++;
- }
- else
- strcpy (msgfile, optarg);
- break;
- case 'u': /* sender ID */
- if (strlen (optarg) > MAXUIDLEN) {
- fprintf (stderr, "sendsms: warning: username too long (max. %d char.) - truncatedn",
- MAXUIDLEN);
- strncpy (user, optarg, MAXUIDLEN);
- }
- else
- strcpy (user, optarg);
- quote (user);
- break;
- case ':': /* parameter without argument */
- fprintf (stderr, "sendsms: Option -%c requires an argument.n",
- optopt);
- errflag++;
- break;
- case '?': /* unrecognized option char */
- fprintf (stderr, "sendsms: Unrecognized option: -%c.n", optopt);
- errflag++;
- break;
- default:
- fprintf (stderr, "sendsms: getopt() returned char. code 0%o ??n", c);
- } /* switch (c) */
- } /* while (c...) */
- /*......................................................*/
- /* now transfer the last element (server name) */
- if (optind < argc) {
- if (strlen (argv[optind]) > MINIBUFF) {
- fprintf (stderr, "sendsms: <server name> parameter too long, max. is %dn",
- MINIBUFF);
- errflag++;
- }
- else
- strcpy (host_or_ip, argv[optind]);
- }
- /*----------------------Check for required parameter(s) */
- /* -d, either -m or -f and server name or address */
- if (!errflag) {
- if (strlen (destgsm) == 0) {
- fprintf (stderr, "sendsms: Required parameter -d not present.n");
- errflag++;
- }
- if ((strlen (message) == 0) && (strlen (msgfile) == 0)) {
- fprintf (stderr, "sendsms: You must provide either -m or -f.n");
- errflag++;
- }
- if (strlen (host_or_ip) == 0) {
- fprintf (stderr, "sendsms: Required parameter <server name> not present.n");
- errflag++;
- }
- } /* if (!errflag) */
- /*-------------------Check for conflicting parameter(s) */
- /* -m with -f */
- if ((strlen (message) > 0) && (strlen (msgfile) > 0)) {
- fprintf (stderr, "sendsms: Conflicting parameters -m and -f.n");
- errflag++;
- }
- /*-----------------------On error, display usage & exit */
- if (errflag) {
- fprintf (stderr, "nsendsms ver. %s (%s), SMS Client for Unixn",
- SMS_CLI_VERSION, SMS_CLI_DATE);
- fprintf (stderr, "(c) Les Ateliers du Heron, 1998 for Scitex Europe, S.A.n");
- fprintf (stderr, "nUsage: sendsms -d dest [-s smsc] (-m msg | -f file) [-u user] servern");
- fprintf (stderr, "nWhere: dest = destination GSM numbern");
- fprintf (stderr, " smsc = SMSC number (opt)n");
- fprintf (stderr, " msg = message to be sent (max. %d char.)n", MAXMSGLEN);
- fprintf (stderr, " file = file containing the message (- for stdin)n");
- fprintf (stderr, " user = sender ID (max. %d char. - opt)n", MAXUIDLEN);
- fprintf (stderr, " server = SMS Server name or ip addr.n");
- exit (2);
- }
- /* DEBUG ...............................................*/
- #ifdef INCL_DEBUG_CODE
- fprintf (stdout, "Those are the parameters :n");
- fprintf (stdout, "dest = [%s]n", destgsm);
- fprintf (stdout, "smsc = [%s]n", smsc);
- fprintf (stdout, "message = [%s]n", message);
- fprintf (stdout, "msgfile = [%s]n", msgfile);
- fprintf (stdout, "user = [%s]n", user);
- fprintf (stdout, "raw host = [%s]n", host_or_ip);
- #endif
- /*---------------------------Start real processing loop */
- /* first resolve server name */
- server_ip.s_addr = resolve (host_or_ip);
-
- /* load message from file is required */
- if (strlen (msgfile) > 0) {
- if (load_from_file (message, msgfile) == 0)
- syserr ("sendsms: error loading message from file or empty file");
- quote (message);
- }
-
- /* create the socket */
- if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
- syserr ("sendsms: can't create socket");
-
- /* build the server socket address parameters */
- sockaddr.sin_family = AF_INET;
- sockaddr.sin_port = htons (DEFSMSPORT);
- sockaddr.sin_addr.s_addr = server_ip.s_addr;
- addrlen = sizeof (sockaddr);
-
- /* now connect to the server */
- if (connect (sockfd, (struct sockaddr *)&sockaddr, addrlen) == -1)
- syserr ("sendsms: can't connect to server");
-
- /*......................................Start of dialog */
- /* slurp server announce and catch prompt */
- if (!slurp_n_catch (sockfd, 1, SERVPROMPT))
- syserr ("sendsms: can't get server prompt");
-
- /* set sender ID - get ok */
- sprintf (cmdline, "set user = %sn", user);
- tellsock (sockfd, cmdline);
- if (!slurp_n_catch (sockfd, 1, "Ok"))
- syserr ("sendsms: failed to set sender ID (user name)");
-
- /* set dest GSM - get ok */
- sprintf (cmdline, "set dest = %sn", destgsm);
- tellsock (sockfd, cmdline);
- if (!slurp_n_catch (sockfd, 1, "Ok"))
- syserr ("sendsms: failed to set destination GSM number");
-
- /* set smsc if needs be - get ok */
- if (strlen (smsc) > 0) {
- sprintf (cmdline, "set smsc = %sn", smsc);
- tellsock (sockfd, cmdline);
- if (!slurp_n_catch (sockfd, 1, "Ok"))
- syserr ("sendsms: failed to set new SMSC number");
- }
-
- /* set message - get ok */
- sprintf (cmdline, "set message = %sn", message);
- tellsock (sockfd, cmdline);
- if (!slurp_n_catch (sockfd, 1, "Ok"))
- syserr ("sendsms: failed to set message to be transmitted");
-
- /* send - get feedback (message sent) */
- sprintf (cmdline, "sendn");
- tellsock (sockfd, cmdline);
- if (get_gsm_answer (sockfd, sendlog, BIGBUFF, 20)) {
- /* timeout needs to be as large as 20 here, because of the
- * huge time it takes to send and verify a PIN code (at a
- * min. 13 secs. */
- #ifdef INCL_DEBUG_CODE
- fprintf (stderr, "SMS send dialog:n%sn", sendlog);
- #endif
- if (strstr (sendlog, "message sent")) {
- fprintf (stderr, "message successfully sentn");
- retval = 0; /* success */
- }
- else {
- fprintf (stderr, "failed to send messagen");
- retval = 102; /* sending failed */
- }
- }
- else {
- fprintf (stderr, "no answer from servern");
- retval = 101; /* no answer */
- }
-
- /* close connection */
- sprintf (cmdline, "byen");
- tellsock (sockfd, cmdline);
- /*------------------------------------------Conclusions */
- /* close socket */
- if (close (sockfd) == -1)
- syserr ("sendsms: can't close socket");
-
- /* free what's need to be */
- free (destgsm);
- free (smsc);
- free (message);
- free (msgfile);
- free (host_or_ip);
- free (cmdline);
- free (sendlog);
- /*------------------------------------------End program */
- exit (retval);
- } /* main () */
- /*==========================================================
- * EOF : sendsms.c
- *===================*/