Janitor, use ARRAY_LEN() when possible.
[asterisk/asterisk.git] / res / res_indications.c
index 475a79d..eb61a02 100644 (file)
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include <unistd.h>
-#include <string.h>
 #include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
 #include <sys/stat.h>
 
 #include "asterisk/lock.h"
 #include "asterisk/file.h"
 #include "asterisk/cli.h"
-#include "asterisk/logger.h"
 #include "asterisk/config.h"
 #include "asterisk/channel.h"
 #include "asterisk/pbx.h"
@@ -49,17 +42,44 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/indications.h"
 #include "asterisk/utils.h"
 
+/*** DOCUMENTATION
+       <application name="PlayTones" language="en_US">
+               <synopsis>
+                       Play a tone list.
+               </synopsis>
+               <syntax>
+                       <parameter name="arg" required="true">
+                               <para>Arg is either the tone name defined in the <filename>indications.conf</filename>
+                               configuration file, or a directly specified list of frequencies and durations.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Plays a tone list. Execution will continue with the next step immediately,
+                       while the tones continue to play.</para>
+                       <para>See the sample <filename>indications.conf</filename> for a description of the
+                       specification of a tonelist.</para>
+               </description>
+               <see-also>
+                       <ref type="application">StopPlayTones</ref>
+               </see-also>
+       </application>
+       <application name="StopPlayTones" language="en_US">
+               <synopsis>
+                       Stop playing a tone list.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>Stop playing a tone list, initiated by PlayTones().</para>
+               </description>
+               <see-also>
+                       <ref type="application">PlayTones</ref>
+               </see-also>
+       </application>
+ ***/
+
 /* Globals */
 static const char config[] = "indications.conf";
 
-char *playtones_desc=
-"PlayTones(arg): Plays a tone list. Execution will continue with the next step immediately,\n"
-"while the tones continue to play.\n"
-"Arg is either the tone name defined in the indications.conf configuration file, or a directly\n"
-"specified list of frequencies and durations.\n"
-"See the sample indications.conf for a description of the specification of a tonelist.\n\n"
-"Use the StopPlayTones application to stop the tones playing. \n";
-
 /*
  * Implementation of functions provided by this module
  */
@@ -196,7 +216,7 @@ static char *handle_cli_indication_show(struct ast_cli_entry *e, int cmd, struct
                int i, j;
                for (i = 2; i < a->argc; i++) {
                        if (strcasecmp(tz->country, a->argv[i]) == 0 && !tz->alias[0]) {
-                               struct ind_tone_zone_sound* ts;
+                               struct ind_tone_zone_sound *ts;
                                if (!found_country) {
                                        found_country = 1;
                                        ast_cli(a->fd, "Country Indication      PlayList\n");
@@ -209,9 +229,10 @@ static char *handle_cli_indication_show(struct ast_cli_entry *e, int cmd, struct
                                if (tz->nrringcadence)
                                        j--;
                                ast_copy_string(buf + j, "\n", sizeof(buf) - j);
-                               ast_cli(a->fd, buf);
-                               for (ts = tz->tones; ts; ts = ts->next)
+                               ast_cli(a->fd, "%s", buf);
+                               AST_LIST_TRAVERSE(&tz->tones, ts, list) {
                                        ast_cli(a->fd, "%-7.7s %-15.15s %s\n", tz->country, ts->name, ts->data);
+                               }
                                break;
                        }
                }
@@ -270,10 +291,11 @@ static int ind_load_module(int reload)
        /* that the following cast is needed, is yuk! */
        /* yup, checked it out. It is NOT written to. */
        cfg = ast_config_load((char *)config, config_flags);
-       if (!cfg)
+       if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
                return -1;
-       else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
+       } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
                return 0;
+       }
 
        if (reload)
                ast_unregister_indication_country(NULL);
@@ -309,6 +331,7 @@ static int ind_load_module(int reload)
                                        }                                       
                                        if (!(tmp = ast_realloc(tones->ringcadence, (tones->nrringcadence + 1) * sizeof(int)))) {
                                                ast_config_destroy(cfg);
+                                               ast_destroy_indication_zone(tones);
                                                return -1;
                                        }
                                        tones->ringcadence = tmp;
@@ -325,56 +348,59 @@ static int ind_load_module(int reload)
                                        struct ind_tone_zone* azone;
                                        if (!(azone = ast_calloc(1, sizeof(*azone)))) {
                                                ast_config_destroy(cfg);
+                                               ast_destroy_indication_zone(tones);
                                                return -1;
                                        }
                                        ast_copy_string(azone->country, country, sizeof(azone->country));
                                        ast_copy_string(azone->alias, cxt, sizeof(azone->alias));
                                        if (ast_register_indication_country(azone)) {
                                                ast_log(LOG_WARNING, "Unable to register indication alias at line %d.\n",v->lineno);
-                                               ast_free(tones);
+                                               ast_destroy_indication_zone(tones);
                                        }
                                        /* next item */
                                        country = strsep(&c,",");
                                }
                        } else {
+                               struct ind_tone_zone_sound *ts;
+
                                /* add tone to country */
-                               struct ind_tone_zone_sound *ps,*ts;
-                               for (ps=NULL,ts=tones->tones; ts; ps=ts, ts=ts->next) {
-                                       if (strcasecmp(v->name,ts->name)==0) {
+                               AST_LIST_TRAVERSE(&tones->tones, ts, list) {
+                                       if (!strcasecmp(v->name, ts->name)) {
                                                /* already there */
-                                               ast_log(LOG_NOTICE,"Duplicate entry '%s', skipped.\n",v->name);
+                                               ast_log(LOG_NOTICE, "Duplicate entry '%s' skipped.\n", v->name);
                                                goto out;
                                        }
                                }
-                               /* not there, add it to the back */                             
-                               if (!(ts = ast_malloc(sizeof(*ts)))) {
+
+                               /* not there, add it to the back */
+                               if (!(ts = ast_calloc(1, sizeof(*ts)))) {
                                        ast_config_destroy(cfg);
                                        return -1;
                                }
-                               ts->next = NULL;
                                ts->name = ast_strdup(v->name);
                                ts->data = ast_strdup(v->value);
-                               if (ps)
-                                       ps->next = ts;
-                               else
-                                       tones->tones = ts;
+
+                               AST_LIST_INSERT_TAIL(&tones->tones, ts, list);
                        }
 out:                   v = v->next;
                }
-               if (tones->description[0] || tones->alias[0] || tones->tones) {
+               if (tones->description[0] || tones->alias[0] || !AST_LIST_EMPTY(&tones->tones)) {
                        if (ast_register_indication_country(tones)) {
                                ast_log(LOG_WARNING, "Unable to register indication at line %d.\n",v->lineno);
-                               ast_free(tones);
+                               ast_destroy_indication_zone(tones);
                        }
-               } else ast_free(tones);
+               } else {
+                       ast_destroy_indication_zone(tones);
+               }
 
                cxt = ast_category_browse(cfg, cxt);
        }
 
        /* determine which country is the default */
        country = ast_variable_retrieve(cfg,"general","country");
-       if (!country || !*country || ast_set_indication_country(country))
+       if (ast_strlen_zero(country) || ast_set_indication_country(country)) {
                ast_log(LOG_WARNING,"Unable to set the default country (for indication tones)\n");
+       }
 
        ast_config_destroy(cfg);
        return 0;
@@ -382,9 +408,9 @@ out:                        v = v->next;
 
 /*! \brief CLI entries for commands provided by this module */
 static struct ast_cli_entry cli_indications[] = {
-       AST_CLI(handle_cli_indication_add,    "Add the given indication to the country"),
-       AST_CLI(handle_cli_indication_remove, "Remove the given indication from the country"),
-       AST_CLI(handle_cli_indication_show,   "Display a list of all countries/indications")
+       AST_CLI_DEFINE(handle_cli_indication_add,    "Add the given indication to the country"),
+       AST_CLI_DEFINE(handle_cli_indication_remove, "Remove the given indication from the country"),
+       AST_CLI_DEFINE(handle_cli_indication_show,   "Display a list of all countries/indications")
 };
 
 /*! \brief Unload indicators module */
@@ -394,7 +420,7 @@ static int unload_module(void)
        ast_unregister_indication_country(NULL);
 
        /* and the functions */
-       ast_cli_unregister_multiple(cli_indications, sizeof(cli_indications) / sizeof(struct ast_cli_entry));
+       ast_cli_unregister_multiple(cli_indications, ARRAY_LEN(cli_indications));
        ast_unregister_application("PlayTones");
        ast_unregister_application("StopPlayTones");
        return 0;
@@ -406,11 +432,11 @@ static int load_module(void)
 {
        if (ind_load_module(0))
                return AST_MODULE_LOAD_DECLINE; 
-       ast_cli_register_multiple(cli_indications, sizeof(cli_indications) / sizeof(struct ast_cli_entry));
-       ast_register_application("PlayTones", handle_playtones, "Play a tone list", playtones_desc);
-       ast_register_application("StopPlayTones", handle_stopplaytones, "Stop playing a tone list","Stop playing a tone list");
+       ast_cli_register_multiple(cli_indications, ARRAY_LEN(cli_indications));
+       ast_register_application_xml("PlayTones", handle_playtones);
+       ast_register_application_xml("StopPlayTones", handle_stopplaytones);
 
-       return 0;
+       return AST_MODULE_LOAD_SUCCESS;
 }
 
 /*! \brief Reload indications module */