Bug #792: Add app_random
[asterisk/asterisk.git] / apps / app_random.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Random application
5  * 
6  * Copyright (c) 2003-2004 Tilghman Lesher.  All rights reserved.
7  *
8  * Tilghman Lesher <asterisk__app_random__20040111@the-tilghman.com>
9  *
10  * This code is released by the author with no restrictions on usage or distribution.
11  *
12  */
13
14 #include <asterisk/file.h>
15 #include <asterisk/logger.h>
16 #include <asterisk/options.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/pbx.h>
19 #include <asterisk/module.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <string.h>
24
25
26 static char *tdesc = "Random goto";
27
28 static char *app_random = "Random";
29
30 static char *random_synopsis = "Conditionally branches, based upon a probability";
31
32 static char *random_descrip =
33 "Random([probability]:[[context|]extension|]priority)\n"
34 "  probability := INTEGER in the range 1 to 100\n";
35
36 STANDARD_LOCAL_USER;
37
38 LOCAL_USER_DECL;
39
40 static int random_exec(struct ast_channel *chan, void *data)
41 {
42         int res=0;
43         struct localuser *u;
44
45         char *s, *ts;
46         char *exten, *pri, *context;
47         char *prob;
48         int probint, priorityint;
49
50         if (!data) {
51                 ast_log(LOG_WARNING, "Random requires an argument ([probability]:[[context|]extension|]priority)\n");
52                 return -1;
53         }
54         LOCAL_USER_ADD(u);
55         s = ast_strdupa((void *) data);
56
57         prob = strsep(&ts,":");
58         if ((!prob) || (sscanf(prob, "%d", &probint) != 1))
59                 probint = 0;
60
61         if ((random() % 100) + probint > 100) {
62                 context = strsep(&s, "|");
63                 exten = strsep(&s, "|");
64                 if (!exten) {
65                         /* Only a priority */
66                         pri = context;
67                         exten = NULL;
68                         context = NULL;
69                 } else {
70                         pri = strsep(&s, "|");
71                         if (!pri) {
72                                 pri = exten;
73                                 exten = context;
74                                 context = NULL;
75                         }
76                 }
77                 if (!pri) {
78                         ast_log(LOG_WARNING, "No label specified\n");
79                         LOCAL_USER_REMOVE(u);
80                         return -1;
81                 } else if (sscanf(pri, "%d", &priorityint) != 1) {
82                         ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", pri);
83                         LOCAL_USER_REMOVE(u);
84                         return -1;
85                 }
86                 /* At this point we have a priority and */
87                 /* maybe an extension and a context     */
88                 chan->priority = priorityint - 1;
89                 if (exten && strcasecmp(exten, "BYEXTENSION"))
90                         strncpy(chan->exten, exten, sizeof(chan->exten)-1);
91                 if (context)
92                         strncpy(chan->context, context, sizeof(chan->context)-1);
93                 if (option_verbose > 2)
94                         ast_verbose( VERBOSE_PREFIX_3 "Random branches to (%s,%s,%d)\n",
95                                 chan->context,chan->exten, chan->priority+1);
96                 LOCAL_USER_REMOVE(u);
97         }
98         return res;
99 }
100
101 int unload_module(void)
102 {
103         STANDARD_HANGUP_LOCALUSERS;
104         return ast_unregister_application(app_random);
105 }
106
107 int load_module(void)
108 {
109         srandom((unsigned int)getpid() + (unsigned int)time(NULL));
110         return ast_register_application(app_random, random_exec, random_synopsis, random_descrip);
111 }
112
113 char *description(void)
114 {
115         return tdesc;
116 }
117
118 int usecount(void)
119 {
120         int res;
121         STANDARD_USECOUNT(res);
122         return res;
123 }
124
125 char *key()
126 {
127         return ASTERISK_GPL_KEY;
128 }