| r2973 | r2975 | |
| 214 | 214 | const char *description; /* Description (help text) for 'show application <name>' */ |
| 215 | 215 | }; |
| 216 | 216 | |
| 217 | /* opbx_func: A function */ |
| 218 | struct opbx_func { |
| 219 | struct opbx_func *next; |
| 220 | unsigned int hash; |
| 221 | char *(*read)(struct opbx_channel *chan, char *cmd, int argc, char **argv, char *buf, size_t len); |
| 222 | void (*write)(struct opbx_channel *chan, char *cmd, int argc, char **argv, const char *value); |
| 223 | const char *name; |
| 224 | const char *synopsis; |
| 225 | const char *syntax; |
| 226 | const char *desc; |
| 227 | }; |
| 228 | |
| 217 | 229 | /* opbx_state_cb: An extension state notify */ |
| 218 | 230 | struct opbx_state_cb |
| 219 | 231 | { |
| --- | --- | |
| 275 | 287 | static int countcalls = 0; |
| 276 | 288 | |
| 277 | 289 | OPBX_MUTEX_DEFINE_STATIC(funcs_lock); /* Lock for the custom function list */ |
| 278 | | static struct opbx_custom_function *funcs_head = NULL; |
| 290 | static struct opbx_func *funcs_head = NULL; |
| 279 | 291 | |
| 280 | 292 | static struct pbx_builtin { |
| 281 | 293 | char *name; |
| --- | --- | |
| 1495 | 1507 | |
| 1496 | 1508 | static int handle_show_functions(int fd, int argc, char *argv[]) |
| 1497 | 1509 | { |
| 1498 | | struct opbx_custom_function *acf; |
| 1510 | struct opbx_func *acf; |
| 1499 | 1511 | int count_acf = 0; |
| 1500 | 1512 | |
| 1501 | 1513 | opbx_cli(fd, "Installed Custom Functions:\n--------------------------------------------------------------------------------\n"); |
| --- | --- | |
| 1510 | 1522 | |
| 1511 | 1523 | static int handle_show_function(int fd, int argc, char *argv[]) |
| 1512 | 1524 | { |
| 1513 | | struct opbx_custom_function *acf; |
| 1525 | struct opbx_func *acf; |
| 1514 | 1526 | /* Maximum number of characters added by terminal coloring is 22 */ |
| 1515 | 1527 | char infotitle[64 + OPBX_MAX_APP + 22], syntitle[40], destitle[40]; |
| 1516 | 1528 | char info[64 + OPBX_MAX_APP], *synopsis = NULL, *description = NULL; |
| --- | --- | |
| 1519 | 1531 | |
| 1520 | 1532 | if (argc < 3) return RESULT_SHOWUSAGE; |
| 1521 | 1533 | |
| 1522 | | if (!(acf = opbx_custom_function_find(argv[2]))) |
| 1534 | if (!(acf = opbx_function_find(argv[2]))) |
| 1523 | 1535 | { |
| 1524 | 1536 | opbx_cli(fd, "No function by that name registered.\n"); |
| 1525 | 1537 | return RESULT_FAILURE; |
| --- | --- | |
| 1566 | 1578 | |
| 1567 | 1579 | static char *complete_show_function(char *line, char *word, int pos, int state) |
| 1568 | 1580 | { |
| 1569 | | struct opbx_custom_function *acf; |
| 1581 | struct opbx_func *acf; |
| 1570 | 1582 | int which = 0; |
| 1571 | 1583 | |
| 1572 | 1584 | /* try to lock functions list ... */ |
| --- | --- | |
| 1595 | 1607 | return NULL; |
| 1596 | 1608 | } |
| 1597 | 1609 | |
| 1598 | | struct opbx_custom_function* opbx_custom_function_find(const char *name) |
| 1610 | struct opbx_func* opbx_function_find(const char *name) |
| 1599 | 1611 | { |
| 1600 | | struct opbx_custom_function *p; |
| 1612 | struct opbx_func *p; |
| 1601 | 1613 | unsigned int hash = opbx_hash_app_name(name); |
| 1602 | 1614 | |
| 1603 | 1615 | if (opbx_mutex_lock(&funcs_lock)) { |
| --- | --- | |
| 1616 | 1628 | |
| 1617 | 1629 | int opbx_unregister_function(void *func) |
| 1618 | 1630 | { |
| 1619 | | struct opbx_custom_function **p; |
| 1631 | struct opbx_func **p; |
| 1620 | 1632 | int ret; |
| 1621 | 1633 | |
| 1622 | 1634 | if (!func) |
| --- | --- | |
| 1640 | 1652 | |
| 1641 | 1653 | if (!ret) { |
| 1642 | 1654 | if (option_verbose > 1) |
| 1643 | | opbx_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", ((struct opbx_custom_function *)func)->name); |
| 1655 | opbx_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", ((struct opbx_func *)func)->name); |
| 1644 | 1656 | free(func); |
| 1645 | 1657 | } |
| 1646 | 1658 | |
| --- | --- | |
| 1653 | 1665 | const char *synopsis, const char *syntax, const char *description) |
| 1654 | 1666 | { |
| 1655 | 1667 | char tmps[80]; |
| 1656 | | struct opbx_custom_function *p; |
| 1668 | struct opbx_func *p; |
| 1657 | 1669 | unsigned int hash; |
| 1658 | 1670 | |
| 1659 | 1671 | if (opbx_mutex_lock(&funcs_lock)) { |
| --- | --- | |
| 1706 | 1718 | char *argv[100]; /* No function can take more than 100 args unless it parses them itself */ |
| 1707 | 1719 | char *args = NULL, *function, *p; |
| 1708 | 1720 | char *ret = "0"; |
| 1709 | | struct opbx_custom_function *acfptr; |
| 1721 | struct opbx_func *acfptr; |
| 1710 | 1722 | |
| 1711 | 1723 | function = opbx_strdupa(in); |
| 1712 | 1724 | |
| --- | --- | |
| 1720 | 1732 | opbx_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n"); |
| 1721 | 1733 | } |
| 1722 | 1734 | |
| 1723 | | if ((acfptr = opbx_custom_function_find(function))) { |
| 1735 | if ((acfptr = opbx_function_find(function))) { |
| 1724 | 1736 | if (acfptr->read) |
| 1725 | 1737 | return (*acfptr->read)(chan, function, opbx_separate_app_args(args, ',', arraysize(argv), argv), argv, workspace, len); |
| 1726 | 1738 | opbx_log(LOG_ERROR, "Function %s cannot be read\n", function); |
| --- | --- | |
| 1735 | 1747 | { |
| 1736 | 1748 | char *argv[100]; /* No function can take more than 100 args unless it parses them itself */ |
| 1737 | 1749 | char *args = NULL, *function, *p; |
| 1738 | | struct opbx_custom_function *acfptr; |
| 1750 | struct opbx_func *acfptr; |
| 1739 | 1751 | |
| 1740 | 1752 | /* FIXME: unnecessary dup? */ |
| 1741 | 1753 | function = opbx_strdupa(in); |
| --- | --- | |
| 1750 | 1762 | opbx_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n"); |
| 1751 | 1763 | } |
| 1752 | 1764 | |
| 1753 | | if ((acfptr = opbx_custom_function_find(function))) { |
| 1765 | if ((acfptr = opbx_function_find(function))) { |
| 1754 | 1766 | if (acfptr->write) { |
| 1755 | 1767 | (*acfptr->write)(chan, function, opbx_separate_app_args(args, ',', arraysize(argv), argv), argv, value); |
| 1756 | 1768 | return; |