server.y
上传用户:eo_sii
上传日期:2007-01-05
资源大小:91k
文件大小:39k
- %{
- /*==========================================================
- * Program : server.y Project : smslink
- * Author : Philippe Andersson.
- * Date : 02/12/99
- * Version : 0.35b
- * Notice : (c) Les Ateliers du Heron, 1998 for Scitex Europe, S.A.
- * Comment : Parser module for SMS server
- *
- * Modification History :
- * - 0.01a (19/08/98) : Initial release.
- * - 0.02a (21/08/98) : Implemented "variable" assignment and
- * individual clearing.
- * - 0.03a (21/08/98) : Added support for prompt.
- * - 0.04a (21/08/98) : Added dequoting for strings.
- * - 0.05a (22/08/98) : Added detailed help handling and individ.
- * show for items. Also implemented a separate exit function.
- * - 0.06a (24/08/98) : Completed help system. Also stuffed the
- * conclude() function a bit.
- * - 0.10a (27/08/98) : Merged the parser module into the main
- * sms_serv program. Moved yyerror () to server.l.
- * - 0.11a (01/09/98) : Completed output migration to socket
- * (printf's to sprintf's).
- * - 0.12a (01/09/98) : Start implementing restricted access
- * to non-sharable resources (modems) through semaphores.
- * - 0.13a (03/09/98) : Completed implementation of crit.
- * sections through semaphores and shared memory.
- * - 0.14a (06/09/98) : Inserted #ifdef's to have it compile
- * under RedHat (GNU Libc 6). Also implemented minimal validation
- * on message parameters (presence checking).
- * - 0.15a (24/09/98) : Changed [LF] to [CR][LF] in messages
- * sent through the socket.
- * - 0.16a (27/09/98) : Added positive acknowledgement for
- * variable setting ("Ok") for error checking on client side.
- * Improved some help messages in give_help().
- * - 0.17a (01/10/98) : Added logging detail (variable setting).
- * - 0.18a (19/10/98) : Changed 'struct modem_def' to 'struct
- * gsms_def' and 'modemsdef' to 'gsmdevices'. Cosmetics.
- * - 0.20a (20/10/98) : Merge the 'spit.c' source into this.
- * Implement the actual SMS sending code.
- * - 0.21a (20/10/98) : Implemented 'devicelist' command.
- * - 0.22a (21/10/98) : Added a signal trap for SIGPIPE, in
- * order to avoid getting locked GSM modules when a client
- * dies or quits unexpectedly (in the critical section).
- * ++++ Switched to Beta ++++
- * - 0.23b (21/10/98) : Added deslashdot() function to clean
- * phone numbers before sending them to the GSM.
- * - 0.24b (22/10/98) : Improved SIGPIPE handling by adding
- * 'instance_is_set' variable telling whether the value of
- * 'instance' should be considered relevant.
- * - 0.25b (23/10/98) : Added handling for 'user' parameter,
- * and improved checking on phone number validity. 'user'
- * parameter also be made required. Corrected timeout values
- * in PIN / PUK transmission, and a bug in CSCA-related sprintf
- * format.
- * - 0.26b (05/11/98) : Corrected an inconsistency in the error
- * message related to catching SIGPIPE signal.
- * - 0.27b (13/12/98) : Moved to sigaction() signal handling.
- * Added handler for SIGTERM in crit. section. Included
- * handling of new member "owner" in struct gsms_def.
- * - 0.28b (14/12/98) : Corrected a boundary-checking bug in the
- * search for a free GSM instance loop.
- * - 0.29b (16/05/99) : Added "uptime" command.
- * - 0.30b (18/05/99) : Refined the uptime display. Solved a
- * bug related to the buffer length in "help" command.
- * - 0.31b (06/06/99) : Added "days" counter to uptime display.
- * Adapted on-line help accordingly. Also added a command to
- * turn off notification for incoming SMS messages in send_sms().
- * - 0.32b (28/06/99) : In send_sms(), moved the AT+CNMI command
- * after the PIN check routine. PIN-Activated SIM is required
- * for AT+CNMI.
- * - 0.33b (29/06/99) : Moved 3 functions over to stuff.c and
- * made them public (misc. string handling functions).
- * - 0.34b (20/09/99) : Improved the "show" command to also
- * display the current length of the message string.
- * - 0.35b (02/12/99) : Improved default SMSC handling in
- * send_sms(). Now takes its default value from the configuration
- * file only (/etc/gsmdevices). Adapted on-line help accordingly.
- * Added "aclist" command and related help. Cosmetics.
- *========================================================*/
- /* must be defined before the usual includes (stdlib.h) */
- #define RAND_MAX 9999 /* max val. for random PIN */
- #include <stdio.h>
- #include <stdlib.h> /* for errno & div() */
- #ifdef LINUX_LC6
- # include <errno.h>
- #endif /* #ifdef LINUX_LC6 */
- #include <strings.h>
- #include <signal.h>
- #include <time.h> /* for difftime() */
- #include <math.h> /* for log() */
- #include <netinet/in.h> /* for ntohl() */
- #include <termios.h> /* for baudrates definitions */
- #include <dial/modems.h> /* requires 'libmodem' */
- #include "sms_serv.h"
- #define min(a, b) ( a < b ? a : b )
- /*-------------------------------------External variables */
- /* for lex & yacc/bison */
- extern int errno;
- extern int yyleng;
- extern char *yytext;
- extern char myinput[];
- extern char *myinputptr; /* cur. pos. in myinput */
- extern char *myinputlim; /* end of data */
- /* program specific */
- extern int csfd; /* client socket FD */
- extern char *buffer; /* scratch space for C/S dialogue */
- extern struct symbols symbols;
- extern int ngsmdevs; /* num. configured GSM devices */
- /*---------------------------------------Global variables */
- char *paramname = NULL;
- char *idname = NULL;
- /* char *buffer = NULL; */
- int i;
- int instance;
- int instance_is_set = FALSE;
- int vtype;
- /*------------------------------------For the help system */
- /* Be carefull to match the defines here with the array below */
- #define H_HELP 0
- #define H_CLEAR 1
- #define H_SET 2
- #define H_SEND 3
- #define H_QUIT 4
- #define H_EXIT 5
- #define H_BYE 6
- #define H_SHOW 7
- #define H_STATS 8
- #define H_DEVLIST 9
- #define H_UPTIME 10
- #define H_ACLIST 11
- #define H_MAX 12 /* keeps (last + 1) */
- char *help_topics[(H_MAX + 1)] = {"help",
- "clear",
- "set",
- "send",
- "quit",
- "exit",
- "bye",
- "show",
- "stats",
- "devicelist",
- "uptime",
- "aclist",
- NULL};
- /*----------------------------Local Function declarations */
- int shiftleft (char *, int);
- int dequote (char *);
- int deslashdot (char *);
- int give_help (char *);
- int help_lookup (char *);
- int load_help ();
- void free_help ();
- void print_device_list ();
- void print_access_list ();
- void compute_uptime ();
- int validate_msg_param (struct symbols *);
- int send_sms (struct gsms_def *);
- void sms_send_wrapper ();
- void unlock_gsm ();
- void conclude ();
- /*========================================================*/
- %}
- %union {
- char *string; /* string buffer for token value */
- }
- /* commands */
- %token T_HELP
- %token T_CLEAR
- %token T_SEND
- %token T_DEVLIST
- %token T_ACLIST
- %token T_UPTIME
- %token T_SET
- %token T_QUIT
- %token T_STATS
- %token T_SHOW
- /* others */
- %token T_PARAM
- %token <string> T_TEXT
- %token <string> T_PHNUM
- %token T_NAME
- %type <string> value
- %%
- statement: single_command
- | param_command
- | assignment
- | /* allow empty input */
- ;
- single_command: T_HELP {
- sprintf (buffer, "rnSMS Server Helprn"
- "===============rn"
- "he | help [command] : displays helprn"
- "set item = value : sets message parametersrn"
- "clear [item] : clears item (all items)rn"
- "send : sends SMSrn");
- tellsock (csfd, buffer);
- sprintf (buffer, "dl | devicelist : lists configured GSM devicesrn"
- "acl | aclist : dumps the registered ACL's to screenrn"
- "ut | uptime : displays server uptimern"
- "quit | exit | bye : closes connection and exitsrn"
- "stats : displays server statsrn"
- "sh | show [item] : displays item (all items)rnrn");
- tellsock (csfd, buffer);
- }
- | T_CLEAR {
- strcpy (symbols.smsc, DEFAULTSMSC);
- symbols.destgsm[0] = ' ';
- symbols.user[0] = ' ';
- symbols.message[0] = ' ';
- sprintf (buffer, "All items cleared...rn");
- tellsock (csfd, buffer);
- }
- | T_SEND {
- if (validate_msg_param (&symbols))
- sms_send_wrapper ();
- else {
- sprintf (buffer, "ERROR: Not all required items are filled in.rn");
- tellsock (csfd, buffer);
- }
- }
- | T_DEVLIST {
- print_device_list ();
- }
- | T_ACLIST {
- print_access_list ();
- }
- | T_UPTIME {
- compute_uptime ();
- }
- | T_STATS {
- sprintf (buffer, "Statistics are not implemented yet.rn");
- tellsock (csfd, buffer);
- }
- | T_SHOW {
- sprintf (buffer, "rnCurrent settings:rn");
- tellsock (csfd, buffer);
- sprintf (buffer, "smsc = [%s]rn", symbols.smsc);
- tellsock (csfd, buffer);
- sprintf (buffer, "user = [%s]rn", symbols.user);
- tellsock (csfd, buffer);
- sprintf (buffer, "dest = [%s]rn", symbols.destgsm);
- tellsock (csfd, buffer);
- sprintf (buffer, "msg = [%s] - Length: %drnrn",
- symbols.message, strlen (symbols.message));
- tellsock (csfd, buffer);
- }
- | T_QUIT { conclude (); }
- ;
- param_command: T_HELP parameter
- {
- give_help (paramname);
- free (paramname);
- paramname = NULL;
- }
- | T_SHOW parameter
- {
- if (strcmp (paramname, "msg") == 0) {
- free (paramname);
- paramname = (char *) malloc (8 * sizeof (char));
- strcpy (paramname, "message");
- }
-
- if (strcmp (paramname, "smsc") == 0) {
- sprintf (buffer, "smsc = [%s]rn", symbols.smsc);
- tellsock (csfd, buffer);
- }
- else if (strcmp (paramname, "user") == 0) {
- sprintf (buffer, "user = [%s]rn", symbols.user);
- tellsock (csfd, buffer);
- }
- else if (strcmp (paramname, "dest") == 0) {
- sprintf (buffer, "dest = [%s]rn", symbols.destgsm);
- tellsock (csfd, buffer);
- }
- else if (strcmp (paramname, "message") == 0) {
- sprintf (buffer, "msg = [%s] - Length: %drn",
- symbols.message, strlen (symbols.message));
- tellsock (csfd, buffer);
- }
- else {
- sprintf (buffer, "ERROR: unknown item <%s>rn", paramname);
- tellsock (csfd, buffer);
- }
- free (paramname);
- paramname = NULL;
- }
- | T_CLEAR parameter
- {
- if (strcmp (paramname, "msg") == 0) {
- free (paramname);
- paramname = (char *) malloc (8 * sizeof (char));
- strcpy (paramname, "message");
- }
-
- if (strcmp (paramname, "smsc") == 0) {
- strcpy (symbols.smsc, DEFAULTSMSC);
- }
- else if (strcmp (paramname, "user") == 0) {
- symbols.user[0] = ' ';
- }
- else if (strcmp (paramname, "dest") == 0) {
- symbols.destgsm[0] = ' ';
- }
- else if (strcmp (paramname, "message") == 0) {
- symbols.message[0] = ' ';
- }
- else {
- sprintf (buffer, "ERROR: unknown item <%s>rn", paramname);
- tellsock (csfd, buffer);
- }
- free (paramname);
- paramname = NULL;
- }
- ;
- assignment: T_SET variable '=' value
- {
- if (strcmp (idname, "msg") == 0) {
- free (idname);
- idname = (char *) malloc (8 * sizeof (char));
- strcpy (idname, "message");
- }
-
- if (strcmp (idname, "smsc") == 0) {
- /* Assign smsc */
- if (strlen ($4) > MAXPHNUMLEN) {
- strncpy (symbols.smsc, $4, MAXPHNUMLEN);
- symbols.smsc[MAXPHNUMLEN] = ' ';
- sprintf (buffer, "WARNING: max. smsc length is %d, value now truncatedrn",
- MAXPHNUMLEN);
- tellsock (csfd, buffer);
- }
- else
- strcpy (symbols.smsc, $4);
- sprintf (buffer, "Okrn");
- tellsock (csfd, buffer);
- syslog ((FACILITY | LOG_NOTICE),
- "got new smsc <%s>.", symbols.smsc);
- }
-
- else if (strcmp (idname, "user") == 0) {
- /* Assign user */
- if (strlen ($4) > MAXUIDLEN) {
- strncpy (symbols.user, $4, MAXUIDLEN);
- symbols.user[MAXUIDLEN] = ' ';
- sprintf (buffer, "WARNING: max. sender ID length is %d, value now truncatedrn",
- MAXUIDLEN);
- tellsock (csfd, buffer);
- }
- else
- strcpy (symbols.user, $4);
- sprintf (buffer, "Okrn");
- tellsock (csfd, buffer);
- syslog ((FACILITY | LOG_NOTICE),
- "sender ID is [%s].", symbols.user);
- }
-
- else if (strcmp (idname, "dest") == 0) {
- /* Check whether we have a T_PHNUM */
- if (vtype != T_PHNUM) {
- sprintf (buffer, "Expected a phone numberrn");
- tellsock (csfd, buffer);
- }
- else {
- /* Assign dest */
- if (strlen ($4) > MAXPHNUMLEN) {
- strncpy (symbols.destgsm, $4, MAXPHNUMLEN);
- symbols.destgsm[MAXPHNUMLEN] = ' ';
- sprintf (buffer, "WARNING: max. dest length is %d, value now truncatedrn",
- MAXPHNUMLEN);
- tellsock (csfd, buffer);
- }
- else {
- strcpy (symbols.destgsm, $4);
- }
- sprintf (buffer, "Okrn");
- tellsock (csfd, buffer);
- syslog ((FACILITY | LOG_NOTICE),
- "got destgsm <%s>.", symbols.destgsm);
- }
- }
-
- else if (strcmp (idname, "message") == 0) {
- /* Assign message */
- if (strlen ($4) > MAXMSGLEN) {
- strncpy (symbols.message, $4, MAXMSGLEN);
- symbols.message[MAXMSGLEN] = ' ';
- sprintf (buffer, "WARNING: max. message length is %d, value now truncatedrn",
- MAXMSGLEN);
- tellsock (csfd, buffer);
- }
- else
- strcpy (symbols.message, $4);
- sprintf (buffer, "Okrn");
- tellsock (csfd, buffer);
- syslog ((FACILITY | LOG_NOTICE),
- "message to transmit is set.");
- }
-
- else {
- sprintf (buffer, "ERROR: unknown item <%s>rn", idname);
- tellsock (csfd, buffer);
- }
-
- free (idname);
- idname = NULL;
- free ($4);
- }
- ;
- parameter: T_PARAM { if (paramname)
- free (paramname);
- paramname = (char *) malloc ((yyleng + 1) * sizeof (char));
- paramname[0] = ' ';
- strcpy (paramname, yytext);
- }
- ;
- variable: T_NAME { if (idname)
- free (idname);
- idname = (char *) malloc ((yyleng + 1) * sizeof (char));
- idname[0] = ' ';
- strcpy (idname, yytext);
- }
- ;
- value: T_TEXT {
- /* let's dequote here */
- dequote ($1);
- vtype = T_TEXT;
- }
- | T_PHNUM {
- /* let's dequote and remove [/.] here */
- dequote ($1);
- deslashdot ($1);
- vtype = T_PHNUM;
- }
- ;
- %%
- /*########################################################*/
- /* Main entry point for the parser module */
- int parser ()
- {
- /*======================================Initialisations */
- /*==============================Main Call to the Parser */
- yyparse ();
- } /* parser () */
- /*########################################################*/
- /*========================================================*/
- /* Local Functions */
- /*========================================================*/
- int my_yyinput (buf, max_size)
- char *buf;
- int max_size;
- {
- int n = min (max_size, (myinputlim - myinputptr));
-
- if (n > 0) {
- memcpy (buf, myinputptr, n);
- myinputptr += n;
- }
-
- return (n);
- } /* my_yyinput () */
- /*========================================================*/
- int give_help (p)
- char *p;
- {
- int topic_id;
- topic_id = help_lookup (p);
- switch (topic_id) {
- case H_HELP: {
- sprintf (buffer, "rnSyntax: he | help [command]rn"
- "Used with no option, gives a list of all available commands.rn"
- "When a command is provided, gives detailed help on this command.rnrn");
- tellsock (csfd, buffer);
- break;
- }
- case H_CLEAR: {
- sprintf (buffer, "rnSyntax: clear [item]rn"
- "Where [item] is one of:rn"
- "- smsc: SMS Message Center (reverts it to "%s")rn"
- "- user: sender identification (user name) for logging purposesrn"
- "- dest: destination GSM numberrn"
- "- message | msg: message text to be sent to destinationrn"
- "Used with no option, clears all items.rn"
- "When an item is specified, clears only this one.rnrn",
- DEFAULTSMSC);
- tellsock (csfd, buffer);
- break;
- }
- case H_SET: {
- sprintf (buffer, "rnSyntax: set item = valuern"
- "Where [item] is one of:rn"
- "- smsc: SMS Message Center (see your provider or use default)rn"
- "- user: sender identification (user name) for logging purposesrn"
- "- dest: destination GSM numberrn"
- "- message | msg: message text to be sent to destinationrnrn");
- tellsock (csfd, buffer);
- sprintf (buffer, "Note 1: text must be quoted, GSM numbers can be quoted, GSM numbers canrn"
- "contain any of [/.-+].rnrn"
- "Note 2: for SMSC, a value of "%s" means the default SMSCrn"
- "as defined per device in %s. Set it to a valid phonern"
- "number to use a different one. Use the "clear" command to reset itrn"
- "to "%s".rnrn", DEFAULTSMSC, GSMDEVFILE, DEFAULTSMSC);
- tellsock (csfd, buffer);
- break;
- }
- case H_SEND: {
- sprintf (buffer, "rnSyntax: sendrn"
- "When all parameters are filled in as required, use this command torn"
- "send the SMS message. You'll wait during the time it takes to send.rn"
- "An acknowlegment will be returned when done.rnrn");
- tellsock (csfd, buffer);
- break;
- }
- case H_QUIT: {
- /* just jump to next */
- }
- case H_EXIT: {
- /* just jump to next */
- }
- case H_BYE: {
- sprintf (buffer, "rnSyntax: quit | exit | byern"
- "Closes the connection and leaves the program.rnrn");
- tellsock (csfd, buffer);
- break;
- }
- case H_SHOW: {
- sprintf (buffer, "rnSyntax: sh | show [item]rn"
- "Where [item] is one of:rn"
- "- smsc: SMS Message Center (see your provider or use default)rn"
- "- user: sender identification (user name) for logging purposesrn"
- "- dest: destination GSM numberrn"
- "- message | msg: message text to be sent to destinationrn"
- "Used without parameter, the command displays the current settingrn"
- "for all items. When an item is specified, only this one isrn"
- "displayed.rnrn");
- tellsock (csfd, buffer);
- break;
- }
- case H_STATS: {
- sprintf (buffer, "rnStatistics are not implemented yet.rnrn");
- tellsock (csfd, buffer);
- break;
- }
- case H_DEVLIST: {
- sprintf (buffer, "rnSyntax: devicelist | dlrn"
- "Lists registered GSM devices.rn"
- "Those are usually configured through <%s>.rn"
- "The fields provided in the output are:rn", GSMDEVFILE);
- tellsock (csfd, buffer);
- sprintf (buffer, "- owner: pid owning a lock on it (0 = not locked)rn"
- "- device: Unix device namern"
- "- CallerID: the GSM's network addr. (its phone number)rn"
- "- Def SCA: the default Service Center Addr. (or SMSC)rn"
- "- Provider: Network Provider Namernrn");
- tellsock (csfd, buffer);
- break;
- }
- case H_ACLIST: {
- sprintf (buffer, "rnSyntax: aclist | aclrn"
- "Dumps the registered ACL entries to screen.rn"
- "ACL's are Access Control Lists that define which machinern"
- "is allowed to use the server and which isn't. ACL's arern"
- "usually configured through <%s>.rn"
- "man 5 gsmaccess for more details.rnrn", ACCESSFILE);
- tellsock (csfd, buffer);
- break;
- }
- case H_UPTIME: {
- sprintf (buffer, "rnSyntax: uptime | utrn"
- "Displays the SMS server process uptime in days, hours, rn"
- "minutes and seconds.rnrn");
- tellsock (csfd, buffer);
- break;
- }
- default: {
- sprintf (buffer, "ERROR: don't know about <%s>. Can't help.rn", p);
- tellsock (csfd, buffer);
- break;
- }
- } /* switch (topic_id) */
- return (topic_id);
- } /* give_help () */
- /*========================================================*/
- int help_lookup (p)
- char *p;
- {
- int i;
- for (i = 0; (help_topics[i] != NULL) && (strcmp (p, help_topics[i]) != 0); i++);
- return (i);
- } /* help_lookup () */
- /*========================================================*/
- void print_device_list ()
- {
- extern int shmem_sem;
- extern struct gsms_def *gsmdevices;
- sprintf (buffer, "rn"
- "L | Owner | Device | CallerID | Def. SCA | Provider rn"
- "--+-------+---------------+----------------+----------------+------------rn");
- tellsock (csfd, buffer);
-
- /* get exclusive access to shared mem. for safety's sake */
- if (sem_wait (shmem_sem) == -1)
- syserr ("sms_serv: failed to wait on shared mem. semaphore");
- /* ---- Begin Crit. Sect. #4 ---- */
- for (i = 0; i < ngsmdevs; i++) {
- sprintf (buffer, "%s | %5d | /dev/%-8s | %-14s | %-14s | %srn",
- (gsmdevices[i].free ? "." : "*"),
- gsmdevices[i].owner,
- gsmdevices[i].device,
- gsmdevices[i].addr,
- gsmdevices[i].defsca,
- gsmdevices[i].provider);
- tellsock (csfd, buffer);
- } /* for (i... */
- /* leave crit. sect. */
- if (sem_signal (shmem_sem) == -1)
- syserr ("sms_serv: can't signal shared mem. semaphore");
- /* ---- End Crit. Sect. #4 ---- */
-
- sprintf (buffer, "rn");
- tellsock (csfd, buffer);
- } /* print_device_list () */
- /*========================================================*/
- void print_access_list ()
- {
- extern acl_list gsm_acl;
- struct acl_item *cursor;
- unsigned long nomask;
- int netmask;
- double power;
- sprintf (buffer, "rnCurrent Access Control List:rn"
- "============================rn");
- tellsock (csfd, buffer);
- if (!empty_acl_list (gsm_acl)) {
- cursor = gsm_acl.head;
- /* convert mask value */
- nomask = ntohl (cursor->nomask);
- if (nomask < (unsigned long) 4294967295) {
- nomask++;
- power = (log (nomask) / log (2));
- netmask = (32 - power);
- }
- else {
- netmask = 0;
- }
- sprintf (buffer, "%-5s : [%s] / %drn",
- (cursor->action == ACL_ALLOW) ? "ALLOW" : "DENY",
- inet_ntoa (cursor->network),
- netmask);
- tellsock (csfd, buffer);
- while (cursor->next != NULL) {
- cursor = cursor->next;
- /* convert mask value */
- nomask = ntohl (cursor->nomask);
- if (nomask < (unsigned long) 4294967295) {
- nomask++;
- power = (log (nomask) / log (2));
- netmask = (32 - power);
- }
- else {
- netmask = 0;
- }
- sprintf (buffer, "%-5s : [%s] / %drn",
- (cursor->action == ACL_ALLOW) ? "ALLOW" : "DENY",
- inet_ntoa (cursor->network),
- netmask);
- tellsock (csfd, buffer);
- }
- }
- else {
- sprintf (buffer, "Nothing to print: empty 'ACL' list.rn");
- tellsock (csfd, buffer);
- }
- sprintf (buffer, "rn");
- tellsock (csfd, buffer);
- } /* print_access_list () */
- /*========================================================*/
- void compute_uptime ()
- {
- extern time_t starttime;
- double upsecs;
- int days;
- int hours;
- int rem;
- div_t dt;
- /* compute the uptime in seconds */
- upsecs = difftime (time (NULL), starttime);
-
- /* first extract the number of days */
- dt = div ((int) upsecs, 86400);
- days = dt.quot;
- rem = dt.rem;
- /* now extract the number of hours */
- dt = div (rem, 3600);
- hours = dt.quot;
- rem = dt.rem;
-
- /* then extract the number of minutes and seconds */
- dt = div (rem, 60);
-
- sprintf (buffer, "rnServer uptime: %d days %d hours %d min %d secs.rnrn",
- days, hours, dt.quot, dt.rem);
- tellsock (csfd, buffer);
- } /* compute_uptime () */
- /*========================================================*/
- int validate_msg_param (struct symbols *msg)
- {
- int retval;
- retval = ((msg->smsc[0] != ' ') && (msg->destgsm[0] != ' ') &&
- (msg->message[0] != ' ') && (msg->user[0] != ' '));
- return (retval);
- } /* validate_msg_param () */
- /*========================================================*/
- int send_sms (struct gsms_def *gsm)
- {
- int fd, retval = 0;
- char *scratch;
- char *ptr;
- char *cmsgid;
- int nread;
- int newpin;
- int retries;
- int msgid;
- char reqsca[MAXPHNUMLEN + 1];
-
- scratch = (char *) malloc ((BIGBUFF + 1) * sizeof (char));
- if (!scratch)
- syserr ("sms_serv: can't allocate scratch space");
- memset (scratch, 0, (BIGBUFF + 1));
-
- /* open modem line */
- fd = blopen_mdm_line (gsm->device, B9600);
- if (fd < 0) {
- syslog ((FACILITY | LOG_ERR), "call to blopen_mdm_line() failed.");
- mdmperror ("sms_serv: blopen_mdm_line() failed");
- free (scratch);
- return (-1);
- }
-
- /*------------set GSM to "verbose" error reporting mode */
- sprintf (scratch, "at+cmee=1r");
- tell_gsm (fd, scratch);
- memset (scratch, 0, (BIGBUFF + 1));
- if (get_gsm_answer (fd, scratch, BIGBUFF, 1)) {
- tellsock (csfd, scratch);
- /* check for "OK" */
- if (strstr (scratch, "OK") == NULL) {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "error after sending AT+CMEE command.");
- mdmperror ("sms_serv: error after sending AT+CMEE command");
- return (-1);
- }
- }
- else {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "GSM module not responding.");
- mdmperror ("sms_serv: GSM not responding");
- return (-1);
- }
-
- /*---------------------------then, check for SIM status */
- sprintf (scratch, "at+cpin?r");
- tell_gsm (fd, scratch);
- memset (scratch, 0, (BIGBUFF + 1));
- if (get_gsm_answer (fd, scratch, BIGBUFF, 1)) {
- tellsock (csfd, scratch);
- /* check for "READY" -- if not, make it so */
- retries = MAXATTEMPTS;
- while ((strstr (scratch, "READY") == NULL) && retries--) {
- /* not ready yet -> asking for PIN or PUK ? */
- if (strstr (scratch, "SIM PIN")) {
- /* send PIN */
- sprintf (scratch, "at+cpin=%sr", gsm->PIN);
- tell_gsm (fd, scratch);
- memset (scratch, 0, (BIGBUFF + 1));
- if (get_gsm_answer (fd, scratch, BIGBUFF, 15)) {
- tellsock (csfd, scratch);
- /* check for "OK" */
- if (strstr (scratch, "OK") == NULL) {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "can't send PIN to GSM or wrong PIN.");
- mdmperror ("sms_serv: can't send PIN to GSM or wrong PIN");
- return (-1);
- }
- }
- else {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "GSM module not responding.");
- mdmperror ("sms_serv: GSM not responding");
- return (-1);
- }
- }
- else if (strstr (scratch, "SIM PUK")) {
- /* send PUK - set new random PIN */
- srand (getpid ());
- newpin = rand ();
- syslog ((FACILITY | LOG_WARNING), "I'll try to set new PIN for </dev/%s>.", gsm->device);
- sprintf (scratch, "at+cpin="%s","%04d"r", gsm->PUK, newpin);
- tell_gsm (fd, scratch);
- memset (scratch, 0, (BIGBUFF + 1));
- if (get_gsm_answer (fd, scratch, BIGBUFF, 20)) {
- tellsock (csfd, scratch);
- /* check for "OK" */
- if (strstr (scratch, "OK") == NULL) {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "can't send PUK to GSM or wrong PUK.");
- mdmperror ("sms_serv: can't send PUK to GSM or wrong PUK");
- return (-1);
- }
- }
- else {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "GSM module not responding.");
- mdmperror ("sms_serv: GSM not responding");
- return (-1);
- }
- /* store new PIN in conf. file (GSMDEVFILE) */
- /* log it */
- syslog ((FACILITY | LOG_WARNING), "new PIN for </dev/%s> set to [%04d].", gsm->device, newpin);
- }
- else { /* ERROR */
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "unable to get SIM status info.");
- mdmperror ("sms_serv: unable to get SIM status info");
- return (-1);
- } /* if "PIN" elseif "PUK" else ... */
- /* query the status again */
- sprintf (scratch, "at+cpin?r");
- tell_gsm (fd, scratch);
- memset (scratch, 0, (BIGBUFF + 1));
- if (!get_gsm_answer (fd, scratch, BIGBUFF, 1)) {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "GSM module not responding.");
- mdmperror ("sms_serv: GSM not responding");
- return (-1);
- }
- tellsock (csfd, scratch);
- } /* while (!"READY") */
- }
- else {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "GSM module not responding.");
- mdmperror ("sms_serv: GSM not responding");
- return (-1);
- }
-
- /*------------set "no notify for incoming SMS messages" */
- sprintf (scratch, "at+cnmi=0,0,0,0,0r");
- tell_gsm (fd, scratch);
- memset (scratch, 0, (BIGBUFF + 1));
- if (get_gsm_answer (fd, scratch, BIGBUFF, 1)) {
- tellsock (csfd, scratch);
- /* check for "OK" */
- if (strstr (scratch, "OK") == NULL) {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "error after sending AT+CNMI command.");
- mdmperror ("sms_serv: error after sending AT+CNMI command");
- return (-1);
- }
- }
- else {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "GSM module not responding.");
- mdmperror ("sms_serv: GSM not responding");
- return (-1);
- }
-
- /*--------------Check stored SCA against requested SMSC */
- /* Which SMSC do we require ? */
- if (strcmp (symbols.smsc, DEFAULTSMSC) == 0) {
- /* user kept default value - let's use device-level default */
- strcpy (reqsca, gsm->defsca);
- }
- else {
- /* user requested specific SMSC - let's use it */
- strcpy (reqsca, symbols.smsc);
- }
- sprintf (scratch, "at+csca?r");
- tell_gsm (fd, scratch);
- memset (scratch, 0, (BIGBUFF + 1));
- if (get_gsm_answer (fd, scratch, BIGBUFF, 1)) {
- tellsock (csfd, scratch);
- /* compare with requested SMSC */
- if (strstr (scratch, reqsca) == NULL) {
- /* let's set it then */
- sprintf (scratch, "at+csca="%s"r", reqsca);
- tell_gsm (fd, scratch);
- memset (scratch, 0, (BIGBUFF + 1));
- if (get_gsm_answer (fd, scratch, BIGBUFF, 2)) {
- tellsock (csfd, scratch);
- /* check for "OK" */
- if (strstr (scratch, "OK") == NULL) {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "error after sending AT+CSCA= command.");
- mdmperror ("sms_serv: error after sending AT+CSCA= command");
- return (-1);
- }
- }
- else {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "GSM module not responding.");
- mdmperror ("sms_serv: GSM not responding");
- return (-1);
- }
- }
- }
- else {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "GSM module not responding.");
- mdmperror ("sms_serv: GSM not responding");
- return (-1);
- }
-
- /*---------------------Am I registered on the network ? */
- sprintf (scratch, "at+creg?r");
- tell_gsm (fd, scratch);
- memset (scratch, 0, (BIGBUFF + 1));
- if (get_gsm_answer (fd, scratch, BIGBUFF, 1)) {
- tellsock (csfd, scratch);
- /* check for "0,1" status */
- if (strstr (scratch, "+CREG: 0,1") == NULL) {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "not registered on the network - can't send.");
- mdmperror ("sms_serv: not registered on the network - can't send");
- return (-1);
- }
- }
- else {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "GSM module not responding.");
- mdmperror ("sms_serv: GSM not responding");
- return (-1);
- }
-
- /*------------------------Now actually send SMS message */
- sprintf (scratch, "at+cmgs="%s"r%s%s", symbols.destgsm, symbols.message, CTRL_Z);
- tell_gsm (fd, scratch);
- memset (scratch, 0, (BIGBUFF + 1));
- if (get_gsm_answer (fd, scratch, BIGBUFF, 4)) {
- tellsock (csfd, scratch);
- /* check for "OK" */
- if (strstr (scratch, "OK") == NULL) {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "error when sending SMS message.");
- mdmperror ("sms_serv: error when sending SMS message");
- return (-1);
- }
- }
- else {
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- syslog ((FACILITY | LOG_ERR), "GSM module not responding.");
- mdmperror ("sms_serv: GSM not responding");
- return (-1);
- }
- /* we have the answer - now extract the message ID from it */
- if ((ptr = strstr (scratch, "+CMGS:")) == NULL) {
- }
- ptr += 6; /* jumps to next space */
- cmsgid = strtok (ptr, " tnr");
- msgid = atoi (cmsgid);
-
- /*----------------------------------Close communication */
- mdm_unlock (mdmopendevice);
- hangup (fd);
- free (scratch);
- return (msgid);
- } /* send_sms () */
- /*========================================================*/
- void sms_send_wrapper ()
- {
- extern int global_sem;
- extern int shmem_sem;
- extern struct gsms_def *gsmdevices;
- int nwaitsecs = 0;
- int last_errno;
- int retval;
- /* int instance; */
- char device[MAXDEVLEN];
- struct gsms_def gsm;
- int msgid;
- struct sigaction sa_c;
-
- sprintf (buffer, "Waiting for a free GSM instance...rn");
- tellsock (csfd, buffer);
- sprintf (buffer, ".");
-
- while (((retval = sem_decreq (global_sem)) == -1) &&
- (errno == EAGAIN) &&
- (nwaitsecs < M_TIMEOUT)) {
- sleep (W_STEP);
- nwaitsecs += W_STEP;
- tellsock (csfd, buffer); /* display dot */
- } /* while (...) */
- last_errno = errno;
- sprintf (buffer, "rn");
- tellsock (csfd, buffer);
-
- if (retval == -1) { /* failed to get a modem */
- switch (last_errno) {
- case EAGAIN: {
- syslog ((FACILITY | LOG_WARNING), "timeout expired (all GSMs busy).");
- sprintf (buffer, "timeout expired (all GSMs busy) - try again laterrn");
- tellsock (csfd, buffer);
- break;
- }
- default: {
- syserr ("sms_serv: can't decrease global semaphore");
- break;
- }
- } /* switch (last_errno) */
- }
- else { /* ---- Begin Crit. Sect. #1 --- */
- /* at least 1 GSM module is free - find it */
- if (sem_wait (shmem_sem) == -1)
- syserr ("sms_serv: failed to wait on shared mem. semaphore");
- /* ---- Begin Crit. Sect. #2 ---- */
- /* Signal Handling */
- sa_c.sa_handler = unlock_gsm;
- if (sigfillset (&sa_c.sa_mask) == -1)
- syserr ("sms_serv: can't fill signal set");
- sa_c.sa_flags = 0;
- /* catch SIGTERM to handle child's death while GSM's locked */
- if (sigaction (SIGTERM, &sa_c, NULL) == -1)
- syserr ("sms_serv: can't catch SIGTERM");
- /* catch SIGPIPE to handle client disconnect while GSM's locked */
- if (sigaction (SIGPIPE, &sa_c, NULL) == -1)
- syserr ("sms_serv: can't catch SIGPIPE");
- /* search free instance */
- instance = 0;
- while (instance < ngsmdevs) {
- if (gsmdevices[instance].free) {
- /* let's process this one */
- break;
- }
- instance++;
- } /* while (instance...) */
- if (instance >= ngsmdevs)
- fatal ("sms_serv: can't get a free GSM - internal error");
-
- /* got it - now lock it (device lockfile handled by libmodem) */
- instance_is_set = TRUE;
- gsmdevices[instance].free = FALSE;
- gsmdevices[instance].owner = getpid ();
-
- /* copy to "local" space, to avoid the shmem balagan */
- if (gsmdevcpy (&gsm, &gsmdevices[instance]) == -1)
- syserr ("sms_serv: error copying GSM instance");
-
- /* leave crit. sect. */
- if (sem_signal (shmem_sem) == -1)
- syserr ("sms_serv: can't signal shared mem. semaphore");
- /* ---- End Crit. Sect. #2 ---- */
- /* log it */
- syslog ((FACILITY | LOG_NOTICE), "using device </dev/%s>.", gsm.device);
- sprintf (buffer, "got </dev/%s>, now sending...rn", gsm.device);
- tellsock (csfd, buffer);
-
- /* ---->>> Actual SEND <<<---- */
- if ((msgid = send_sms (&gsm)) != -1) {
- syslog ((FACILITY | LOG_NOTICE), "message sent OK, message ID is <%d>.", msgid);
- sprintf (buffer, "message sent OK, message ID is <%d>rn", msgid);
- tellsock (csfd, buffer);
- }
- else { /* some error occured */
- syslog ((FACILITY | LOG_WARNING), "ERROR: failed to send message.");
- sprintf (buffer, "ERROR: failed to send message - try again laterrn");
- tellsock (csfd, buffer);
- }
-
- /* now free the modem again */
- if (sem_wait (shmem_sem) == -1)
- syserr ("sms_serv: failed to wait on shared mem. semaphore");
- /* ---- Begin Crit. Sect. #3 ---- */
- gsmdevices[instance].free = TRUE;
- gsmdevices[instance].owner = 0;
- instance_is_set = FALSE;
- /* leave crit. sect. */
- if (sem_signal (shmem_sem) == -1)
- syserr ("sms_serv: can't signal shared mem. semaphore");
- /* ---- End Crit. Sect. #3 ---- */
- /* leave main crit. sect. */
- if (sem_signal (global_sem) == -1)
- syserr ("sms_serv: can't signal global semaphore");
- } /* ---- End Crit. Sect. #1 --- */
- } /* sms_send_wrapper () */
- /*========================================================*/
- void unlock_gsm ()
- {
- extern int shmem_sem;
- extern struct gsms_def *gsmdevices;
- syslog ((FACILITY | LOG_WARNING), "Socket connection unexpectedly lost.");
- /* set the allocated GSM module back to 'free' status */
- if (instance_is_set) {
- if (sem_wait (shmem_sem) == -1)
- syserr ("sms_serv: failed to wait on shared mem. semaphore");
- /* ---- Begin Crit. Sect. #5 ---- */
- if (!gsmdevices[instance].free) {
- gsmdevices[instance].free = TRUE;
- gsmdevices[instance].owner = 0;
- syslog ((FACILITY | LOG_WARNING), "GSM instance </dev/%s> has been unlocked.",
- gsmdevices[instance].device);
- }
- /* leave crit. sect. */
- if (sem_signal (shmem_sem) == -1)
- syserr ("sms_serv: can't signal shared mem. semaphore");
- /* ---- End Crit. Sect. #5 ---- */
- }
- /* free what's need to be freed and exit */
- free (symbols.smsc);
- free (symbols.destgsm);
- free (symbols.message);
- free (buffer);
- /*------------------------------------------------------*/
- exit (0);
- } /* unlock_gsm () */
- /*========================================================*/
- void conclude ()
- {
- syslog ((FACILITY | LOG_NOTICE), "Connection closed by client.");
- /* free what's need to be freed and exit */
- free (symbols.smsc);
- free (symbols.destgsm);
- free (symbols.message);
- free (buffer);
- /*------------------------------------------------------*/
- exit (0);
- } /* conclude () */
- /*========================================================*/
- /*==========================================================
- * EOF : server.y
- *===================*/