Mon Oct 8 12:39:23 2012

Asterisk developer's documentation


func_env.c File Reference

Environment related dialplan functions. More...

#include "asterisk.h"
#include <sys/stat.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/file.h"

Go to the source code of this file.

Defines

#define LINE_COUNTER(cptr, term, counter)

Enumerations

enum  file_format { FF_UNKNOWN = -1, FF_UNIX, FF_DOS, FF_MAC }

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int64_t count_lines (const char *filename, enum file_format newline_format)
static int env_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int env_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
static enum file_format file2format (const char *filename)
static int file_count_line (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static int file_format (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static int file_read (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static int file_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
const char * format2term (enum file_format f)
static int load_module (void)
static int stat_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Environment/filesystem dialplan functions" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_custom_function env_function
static struct ast_custom_function file_count_line_function
static struct ast_custom_function file_format_function
static struct ast_custom_function file_function
static struct ast_custom_function stat_function


Detailed Description

Environment related dialplan functions.

Definition in file func_env.c.


Define Documentation

#define LINE_COUNTER ( cptr,
term,
counter   ) 

Definition at line 407 of file func_env.c.

Referenced by file_read(), and file_write().


Enumeration Type Documentation

enum file_format

Enumerator:
FF_UNKNOWN 
FF_UNIX 
FF_DOS 
FF_MAC 

Definition at line 300 of file func_env.c.

00300                  {
00301    FF_UNKNOWN = -1,
00302    FF_UNIX,
00303    FF_DOS,
00304    FF_MAC,
00305 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1269 of file func_env.c.

static void __unreg_module ( void   )  [static]

Definition at line 1269 of file func_env.c.

static int64_t count_lines ( const char *  filename,
enum file_format  newline_format 
) [static]

Definition at line 307 of file func_env.c.

References ast_log(), errno, FF_DOS, FF_MAC, FF_UNIX, FF_UNKNOWN, and LOG_ERROR.

Referenced by file_count_line().

00308 {
00309    int count = 0;
00310    char fbuf[4096];
00311    FILE *ff;
00312 
00313    if (!(ff = fopen(filename, "r"))) {
00314       ast_log(LOG_ERROR, "Unable to open '%s': %s\n", filename, strerror(errno));
00315       return -1;
00316    }
00317 
00318    while (fgets(fbuf, sizeof(fbuf), ff)) {
00319       char *next = fbuf, *first_cr = NULL, *first_nl = NULL;
00320 
00321       /* Must do it this way, because if the fileformat is FF_MAC, then Unix
00322        * assumptions about line-format will not come into play. */
00323       while (next) {
00324          if (newline_format == FF_DOS || newline_format == FF_MAC || newline_format == FF_UNKNOWN) {
00325             first_cr = strchr(next, '\r');
00326          }
00327          if (newline_format == FF_UNIX || newline_format == FF_UNKNOWN) {
00328             first_nl = strchr(next, '\n');
00329          }
00330 
00331          /* No terminators found in buffer */
00332          if (!first_cr && !first_nl) {
00333             break;
00334          }
00335 
00336          if (newline_format == FF_UNKNOWN) {
00337             if ((first_cr && !first_nl) || (first_cr && first_cr < first_nl)) {
00338                if (first_nl && first_nl == first_cr + 1) {
00339                   newline_format = FF_DOS;
00340                } else if (first_cr && first_cr == &fbuf[sizeof(fbuf) - 2]) {
00341                   /* Get it on the next pass */
00342                   fseek(ff, -1, SEEK_CUR);
00343                   break;
00344                } else {
00345                   newline_format = FF_MAC;
00346                   first_nl = NULL;
00347                }
00348             } else {
00349                newline_format = FF_UNIX;
00350                first_cr = NULL;
00351             }
00352             /* Jump down into next section */
00353          }
00354 
00355          if (newline_format == FF_DOS) {
00356             if (first_nl && first_cr && first_nl == first_cr + 1) {
00357                next = first_nl + 1;
00358                count++;
00359             } else if (first_cr == &fbuf[sizeof(fbuf) - 2]) {
00360                /* Get it on the next pass */
00361                fseek(ff, -1, SEEK_CUR);
00362                break;
00363             }
00364          } else if (newline_format == FF_MAC) {
00365             if (first_cr) {
00366                next = first_cr + 1;
00367                count++;
00368             }
00369          } else if (newline_format == FF_UNIX) {
00370             if (first_nl) {
00371                next = first_nl + 1;
00372                count++;
00373             }
00374          }
00375       }
00376    }
00377    fclose(ff);
00378 
00379    return count;
00380 }

static int env_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 227 of file func_env.c.

References ast_copy_string().

00229 {
00230    char *ret = NULL;
00231 
00232    *buf = '\0';
00233 
00234    if (data)
00235       ret = getenv(data);
00236 
00237    if (ret)
00238       ast_copy_string(buf, ret, len);
00239 
00240    return 0;
00241 }

static int env_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
) [static]

Definition at line 243 of file func_env.c.

References ast_strlen_zero(), setenv(), and unsetenv().

00245 {
00246    if (!ast_strlen_zero(data) && strncmp(data, "AST_", 4)) {
00247       if (!ast_strlen_zero(value)) {
00248          setenv(data, value, 1);
00249       } else {
00250          unsetenv(data);
00251       }
00252    }
00253 
00254    return 0;
00255 }

static enum file_format file2format ( const char *  filename  )  [static]

Definition at line 421 of file func_env.c.

References ast_log(), errno, FF_DOS, FF_MAC, FF_UNIX, FF_UNKNOWN, file_format(), and LOG_ERROR.

Referenced by file_format(), file_read(), and file_write().

00422 {
00423    FILE *ff;
00424    char fbuf[4096];
00425    char *first_cr, *first_nl;
00426    enum file_format newline_format = FF_UNKNOWN;
00427 
00428    if (!(ff = fopen(filename, "r"))) {
00429       ast_log(LOG_ERROR, "Cannot open '%s': %s\n", filename, strerror(errno));
00430       return -1;
00431    }
00432 
00433    while (fgets(fbuf, sizeof(fbuf), ff)) {
00434       first_cr = strchr(fbuf, '\r');
00435       first_nl = strchr(fbuf, '\n');
00436 
00437       if (!first_cr && !first_nl) {
00438          continue;
00439       }
00440 
00441       if ((first_cr && !first_nl) || (first_cr && first_cr < first_nl)) {
00442 
00443          if (first_nl && first_nl == first_cr + 1) {
00444             newline_format = FF_DOS;
00445          } else if (first_cr && first_cr == &fbuf[sizeof(fbuf) - 2]) {
00446             /* Edge case: get it on the next pass */
00447             fseek(ff, -1, SEEK_CUR);
00448             continue;
00449          } else {
00450             newline_format = FF_MAC;
00451          }
00452       } else {
00453          newline_format = FF_UNIX;
00454       }
00455       break;
00456    }
00457    fclose(ff);
00458    return newline_format;
00459 }

static int file_count_line ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 382 of file func_env.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, ast_str_set(), count_lines(), FF_DOS, FF_MAC, FF_UNIX, FF_UNKNOWN, file_format(), and format.

00383 {
00384    enum file_format newline_format = FF_UNKNOWN;
00385    int64_t count;
00386    AST_DECLARE_APP_ARGS(args,
00387       AST_APP_ARG(filename);
00388       AST_APP_ARG(format);
00389    );
00390 
00391    AST_STANDARD_APP_ARGS(args, data);
00392    if (args.argc > 1) {
00393       if (tolower(args.format[0]) == 'd') {
00394          newline_format = FF_DOS;
00395       } else if (tolower(args.format[0]) == 'm') {
00396          newline_format = FF_MAC;
00397       } else if (tolower(args.format[0]) == 'u') {
00398          newline_format = FF_UNIX;
00399       }
00400    }
00401 
00402    count = count_lines(args.filename, newline_format);
00403    ast_str_set(buf, len, "%" PRId64, count);
00404    return 0;
00405 }

static int file_format ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 461 of file func_env.c.

References ast_str_set(), FF_DOS, FF_MAC, FF_UNIX, and file2format().

Referenced by file2format(), file_count_line(), file_read(), and file_write().

00462 {
00463    enum file_format newline_format = file2format(data);
00464    ast_str_set(buf, len, "%c", newline_format == FF_UNIX ? 'u' : newline_format == FF_DOS ? 'd' : newline_format == FF_MAC ? 'm' : 'x');
00465    return 0;
00466 }

static int file_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 468 of file func_env.c.

References args, AST_APP_ARG, ast_debug, AST_DECLARE_APP_ARGS, ast_log(), AST_LOG_ERROR, AST_STANDARD_APP_ARGS, ast_str_append_substr(), ast_str_reset(), errno, FF_DOS, FF_MAC, FF_UNIX, FF_UNKNOWN, file2format(), file_format(), format, LINE_COUNTER, LLONG_MAX, LOG_ERROR, and LOG_WARNING.

00469 {
00470    FILE *ff;
00471    int64_t offset = 0, length = LLONG_MAX;
00472    enum file_format format = FF_UNKNOWN;
00473    char fbuf[4096];
00474    int64_t flength, i; /* iterator needs to be signed, so it can go negative and terminate the loop */
00475    int64_t offset_offset = -1, length_offset = -1;
00476    char dos_state = 0;
00477    size_t readlen;
00478    AST_DECLARE_APP_ARGS(args,
00479       AST_APP_ARG(filename);
00480       AST_APP_ARG(offset);
00481       AST_APP_ARG(length);
00482       AST_APP_ARG(options);
00483       AST_APP_ARG(fileformat);
00484    );
00485 
00486    AST_STANDARD_APP_ARGS(args, data);
00487 
00488    if (args.argc > 1) {
00489       sscanf(args.offset, "%" SCNd64, &offset);
00490    }
00491    if (args.argc > 2) {
00492       sscanf(args.length, "%" SCNd64, &length);
00493    }
00494 
00495    if (args.argc < 4 || !strchr(args.options, 'l')) {
00496       /* Character-based mode */
00497       off_t off_i;
00498 
00499       if (!(ff = fopen(args.filename, "r"))) {
00500          ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", args.filename, strerror(errno));
00501          return 0;
00502       }
00503 
00504       if (fseeko(ff, 0, SEEK_END) < 0) {
00505          ast_log(LOG_ERROR, "Cannot seek to end of '%s': %s\n", args.filename, strerror(errno));
00506          fclose(ff);
00507          return -1;
00508       }
00509       flength = ftello(ff);
00510 
00511       if (offset < 0) {
00512          fseeko(ff, offset, SEEK_END);
00513          if ((offset = ftello(ff)) < 0) {
00514             ast_log(AST_LOG_ERROR, "Cannot determine offset position of '%s': %s\n", args.filename, strerror(errno));
00515             fclose(ff);
00516             return -1;
00517          }
00518       }
00519       if (length < 0) {
00520          fseeko(ff, length, SEEK_END);
00521          if ((length = ftello(ff)) - offset < 0) {
00522             /* Eliminates all results */
00523             fclose(ff);
00524             return -1;
00525          }
00526       } else if (length == LLONG_MAX) {
00527          fseeko(ff, 0, SEEK_END);
00528          length = ftello(ff);
00529       }
00530 
00531       ast_str_reset(*buf);
00532 
00533       fseeko(ff, offset, SEEK_SET);
00534       for (off_i = ftello(ff); off_i < flength && off_i < offset + length; off_i += sizeof(fbuf)) {
00535          /* Calculate if we need to retrieve just a portion of the file in memory */
00536          size_t toappend = sizeof(fbuf);
00537 
00538          if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
00539             ast_log(LOG_ERROR, "Short read?!!\n");
00540             break;
00541          }
00542 
00543          /* Don't go past the length requested */
00544          if (off_i + toappend > offset + length) {
00545             toappend = length - off_i;
00546          }
00547 
00548          ast_str_append_substr(buf, len, fbuf, toappend);
00549       }
00550       fclose(ff);
00551       return 0;
00552    }
00553 
00554    /* Line-based read */
00555    if (args.argc == 5) {
00556       if (tolower(args.fileformat[0]) == 'd') {
00557          format = FF_DOS;
00558       } else if (tolower(args.fileformat[0]) == 'm') {
00559          format = FF_MAC;
00560       } else if (tolower(args.fileformat[0]) == 'u') {
00561          format = FF_UNIX;
00562       }
00563    }
00564 
00565    if (format == FF_UNKNOWN) {
00566       if ((format = file2format(args.filename)) == FF_UNKNOWN) {
00567          ast_log(LOG_WARNING, "'%s' is not a line-based file\n", args.filename);
00568          return -1;
00569       }
00570    }
00571 
00572    if (offset < 0 && length <= offset) {
00573       /* Length eliminates all content */
00574       return -1;
00575    } else if (offset == 0) {
00576       offset_offset = 0;
00577    }
00578 
00579    if (!(ff = fopen(args.filename, "r"))) {
00580       ast_log(LOG_ERROR, "Cannot open '%s': %s\n", args.filename, strerror(errno));
00581       return -1;
00582    }
00583 
00584    if (fseek(ff, 0, SEEK_END)) {
00585       ast_log(LOG_ERROR, "Cannot seek to end of file '%s': %s\n", args.filename, strerror(errno));
00586       fclose(ff);
00587       return -1;
00588    }
00589 
00590    flength = ftello(ff);
00591 
00592    if (length == LLONG_MAX) {
00593       length_offset = flength;
00594    }
00595 
00596    /* For negative offset and/or negative length */
00597    if (offset < 0 || length < 0) {
00598       int64_t count = 0;
00599       /* Start with an even multiple of fbuf, so at the end of reading with a
00600        * 0 offset, we don't try to go past the beginning of the file. */
00601       for (i = (flength / sizeof(fbuf)) * sizeof(fbuf); i >= 0; i -= sizeof(fbuf)) {
00602          size_t end;
00603          char *pos;
00604          if (fseeko(ff, i, SEEK_SET)) {
00605             ast_log(LOG_ERROR, "Cannot seek to offset %" PRId64 ": %s\n", i, strerror(errno));
00606          }
00607          end = fread(fbuf, 1, sizeof(fbuf), ff);
00608          for (pos = end < sizeof(fbuf) ? fbuf + end - 1 : fbuf + sizeof(fbuf) - 1; pos > fbuf - 1; pos--) {
00609             LINE_COUNTER(pos, format, count);
00610 
00611             if (length < 0 && count * -1 == length) {
00612                length_offset = i + (pos - fbuf);
00613             } else if (offset < 0 && count * -1 == (offset - 1)) {
00614                /* Found our initial offset.  We're done with reverse motion! */
00615                if (format == FF_DOS) {
00616                   offset_offset = i + (pos - fbuf) + 2;
00617                } else {
00618                   offset_offset = i + (pos - fbuf) + 1;
00619                }
00620                break;
00621             }
00622          }
00623          if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
00624             break;
00625          }
00626       }
00627       /* We're at the beginning, and the negative offset indicates the exact number of lines in the file */
00628       if (offset < 0 && offset_offset < 0 && offset == count * -1) {
00629          offset_offset = 0;
00630       }
00631    }
00632 
00633    /* Positve line offset */
00634    if (offset > 0) {
00635       int64_t count = 0;
00636       fseek(ff, 0, SEEK_SET);
00637       for (i = 0; i < flength; i += sizeof(fbuf)) {
00638          char *pos;
00639          if (i + sizeof(fbuf) <= flength) {
00640             /* Don't let previous values influence current counts, due to short reads */
00641             memset(fbuf, 0, sizeof(fbuf));
00642          }
00643          if (fread(fbuf, 1, sizeof(fbuf), ff) && !feof(ff)) {
00644             ast_log(LOG_ERROR, "Short read?!!\n");
00645             fclose(ff);
00646             return -1;
00647          }
00648          for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
00649             LINE_COUNTER(pos, format, count);
00650 
00651             if (count == offset) {
00652                offset_offset = i + (pos - fbuf) + 1;
00653                break;
00654             }
00655          }
00656          if (offset_offset >= 0) {
00657             break;
00658          }
00659       }
00660    }
00661 
00662    if (offset_offset < 0) {
00663       ast_log(LOG_ERROR, "Offset '%s' refers to before the beginning of the file!\n", args.offset);
00664       fclose(ff);
00665       return -1;
00666    }
00667 
00668    ast_str_reset(*buf);
00669    if (fseeko(ff, offset_offset, SEEK_SET)) {
00670       ast_log(LOG_ERROR, "fseeko failed: %s\n", strerror(errno));
00671    }
00672 
00673    /* If we have both offset_offset and length_offset, then grabbing the
00674     * buffer is simply a matter of just retrieving the file and adding it
00675     * to buf.  Otherwise, we need to run byte-by-byte forward until the
00676     * length is complete. */
00677    if (length_offset >= 0) {
00678       ast_debug(3, "offset=%" PRId64 ", length=%" PRId64 ", offset_offset=%" PRId64 ", length_offset=%" PRId64 "\n", offset, length, offset_offset, length_offset);
00679       for (i = offset_offset; i < length_offset; i += sizeof(fbuf)) {
00680          if (fread(fbuf, 1, i + sizeof(fbuf) > flength ? flength - i : sizeof(fbuf), ff) < (i + sizeof(fbuf) > flength ? flength - i : sizeof(fbuf))) {
00681             ast_log(LOG_ERROR, "Short read?!!\n");
00682          }
00683          ast_debug(3, "Appending first %" PRId64" bytes of fbuf=%s\n", i + sizeof(fbuf) > length_offset ? length_offset - i : sizeof(fbuf), fbuf);
00684          ast_str_append_substr(buf, len, fbuf, i + sizeof(fbuf) > length_offset ? length_offset - i : sizeof(fbuf));
00685       }
00686    } else if (length == 0) {
00687       /* Nothing to do */
00688    } else {
00689       /* Positive line offset */
00690       int64_t current_length = 0;
00691       char dos_state = 0;
00692       ast_debug(3, "offset=%" PRId64 ", length=%" PRId64 ", offset_offset=%" PRId64 ", length_offset=%" PRId64 "\n", offset, length, offset_offset, length_offset);
00693       for (i = offset_offset; i < flength; i += sizeof(fbuf)) {
00694          char *pos;
00695          if ((readlen = fread(fbuf, 1, sizeof(fbuf), ff)) < sizeof(fbuf) && !feof(ff)) {
00696             ast_log(LOG_ERROR, "Short read?!!\n");
00697          }
00698          for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
00699             LINE_COUNTER(pos, format, current_length);
00700 
00701             if (current_length == length) {
00702                length_offset = i + (pos - fbuf) + 1;
00703                break;
00704             }
00705          }
00706          ast_debug(3, "length_offset=%" PRId64 ", length_offset - i=%" PRId64 "\n", length_offset, length_offset - i);
00707          ast_str_append_substr(buf, len, fbuf, length_offset >= 0 ? length_offset - i : flength > i + sizeof(fbuf)) ? sizeof(fbuf) : flength - i;
00708 
00709          if (length_offset >= 0) {
00710             break;
00711          }
00712       }
00713    }
00714 
00715    fclose(ff);
00716    return 0;
00717 }

static int file_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
) [static]

Definition at line 726 of file func_env.c.

References args, AST_APP_ARG, ast_debug, AST_DECLARE_APP_ARGS, ast_log(), AST_LOG_ERROR, AST_STANDARD_APP_ARGS, errno, FF_DOS, FF_MAC, FF_UNIX, FF_UNKNOWN, file2format(), file_format(), format, format2term(), LINE_COUNTER, LLONG_MAX, LOG_ERROR, LOG_WARNING, and S_OR.

00727 {
00728    AST_DECLARE_APP_ARGS(args,
00729       AST_APP_ARG(filename);
00730       AST_APP_ARG(offset);
00731       AST_APP_ARG(length);
00732       AST_APP_ARG(options);
00733       AST_APP_ARG(format);
00734    );
00735    int64_t offset = 0, length = LLONG_MAX;
00736    off_t flength, vlength;
00737    size_t foplen = 0;
00738    FILE *ff;
00739 
00740    AST_STANDARD_APP_ARGS(args, data);
00741 
00742    if (args.argc > 1) {
00743       sscanf(args.offset, "%" SCNd64, &offset);
00744    }
00745    if (args.argc > 2) {
00746       sscanf(args.length, "%" SCNd64, &length);
00747    }
00748 
00749    vlength = strlen(value);
00750 
00751    if (args.argc < 4 || !strchr(args.options, 'l')) {
00752       /* Character-based mode */
00753 
00754       if (args.argc > 3 && strchr(args.options, 'a')) {
00755          /* Append mode */
00756          if (!(ff = fopen(args.filename, "a"))) {
00757             ast_log(LOG_WARNING, "Cannot open file '%s' for appending: %s\n", args.filename, strerror(errno));
00758             return 0;
00759          }
00760          if (fwrite(value, 1, vlength, ff) < vlength) {
00761             ast_log(LOG_ERROR, "Short write?!!\n");
00762          }
00763          fclose(ff);
00764          return 0;
00765       } else if (offset == 0 && length == LLONG_MAX) {
00766          if (!(ff = fopen(args.filename, "w"))) {
00767             ast_log(LOG_WARNING, "Cannot open file '%s' for writing: %s\n", args.filename, strerror(errno));
00768             return 0;
00769          }
00770          if (fwrite(value, 1, vlength, ff) < vlength) {
00771             ast_log(LOG_ERROR, "Short write?!!\n");
00772          }
00773          fclose(ff);
00774          return 0;
00775       }
00776 
00777       if (!(ff = fopen(args.filename, "r+"))) {
00778          ast_log(LOG_WARNING, "Cannot open file '%s' for modification: %s\n", args.filename, strerror(errno));
00779          return 0;
00780       }
00781       fseeko(ff, 0, SEEK_END);
00782       flength = ftello(ff);
00783 
00784       if (offset < 0) {
00785          if (fseeko(ff, offset, SEEK_END)) {
00786             ast_log(LOG_ERROR, "Cannot seek to offset of '%s': %s\n", args.filename, strerror(errno));
00787             fclose(ff);
00788             return -1;
00789          }
00790          if ((offset = ftello(ff)) < 0) {
00791             ast_log(AST_LOG_ERROR, "Cannot determine offset position of '%s': %s\n", args.filename, strerror(errno));
00792             fclose(ff);
00793             return -1;
00794          }
00795       }
00796 
00797       if (length < 0) {
00798          length = flength - offset + length;
00799          if (length < 0) {
00800             ast_log(LOG_ERROR, "Length '%s' exceeds the file length.  No data will be written.\n", args.length);
00801             fclose(ff);
00802             return -1;
00803          }
00804       }
00805 
00806       fseeko(ff, offset, SEEK_SET);
00807 
00808       ast_debug(3, "offset=%s/%" PRId64 ", length=%s/%" PRId64 ", vlength=%" PRId64 ", flength=%" PRId64 "\n",
00809          S_OR(args.offset, "(null)"), offset, S_OR(args.length, "(null)"), length, vlength, flength);
00810 
00811       if (length == vlength) {
00812          /* Simplest case, a straight replace */
00813          if (fwrite(value, 1, vlength, ff) < vlength) {
00814             ast_log(LOG_ERROR, "Short write?!!\n");
00815          }
00816          fclose(ff);
00817       } else if (length == LLONG_MAX) {
00818          /* Simple truncation */
00819          if (fwrite(value, 1, vlength, ff) < vlength) {
00820             ast_log(LOG_ERROR, "Short write?!!\n");
00821          }
00822          fclose(ff);
00823          if (truncate(args.filename, offset + vlength)) {
00824             ast_log(LOG_ERROR, "Unable to truncate the file: %s\n", strerror(errno));
00825          }
00826       } else if (length > vlength) {
00827          /* More complex -- need to close a gap */
00828          char fbuf[4096];
00829          off_t cur;
00830          if (fwrite(value, 1, vlength, ff) < vlength) {
00831             ast_log(LOG_ERROR, "Short write?!!\n");
00832          }
00833          fseeko(ff, length - vlength, SEEK_CUR);
00834          while ((cur = ftello(ff)) < flength) {
00835             if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
00836                ast_log(LOG_ERROR, "Short read?!!\n");
00837             }
00838             fseeko(ff, cur + vlength - length, SEEK_SET);
00839             if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
00840                ast_log(LOG_ERROR, "Short write?!!\n");
00841             }
00842             /* Seek to where we stopped reading */
00843             if (fseeko(ff, cur + sizeof(fbuf), SEEK_SET) < 0) {
00844                /* Only reason for seek to fail is EOF */
00845                break;
00846             }
00847          }
00848          fclose(ff);
00849          if (truncate(args.filename, flength - (length - vlength))) {
00850             ast_log(LOG_ERROR, "Unable to truncate the file: %s\n", strerror(errno));
00851          }
00852       } else {
00853          /* Most complex -- need to open a gap */
00854          char fbuf[4096];
00855          off_t lastwritten = flength + vlength - length;
00856 
00857          /* Start reading exactly the buffer size back from the end. */
00858          fseeko(ff, flength - sizeof(fbuf), SEEK_SET);
00859          while (offset < ftello(ff)) {
00860             if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
00861                ast_log(LOG_ERROR, "Short read?!!\n");
00862                fclose(ff);
00863                return -1;
00864             }
00865             /* Since the read moved our file ptr forward, we reverse, but
00866              * seek an offset equal to the amount we want to extend the
00867              * file by */
00868             fseeko(ff, vlength - length - sizeof(fbuf), SEEK_CUR);
00869 
00870             /* Note the location of this buffer -- we must not overwrite this position. */
00871             lastwritten = ftello(ff);
00872 
00873             if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
00874                ast_log(LOG_ERROR, "Short write?!!\n");
00875                fclose(ff);
00876                return -1;
00877             }
00878 
00879             if (lastwritten < offset + sizeof(fbuf)) {
00880                break;
00881             }
00882             /* Our file pointer is now either pointing to the end of the
00883              * file (new position) or a multiple of the fbuf size back from
00884              * that point.  Move back to where we want to start reading
00885              * again.  We never actually try to read beyond the end of the
00886              * file, so we don't have do deal with short reads, as we would
00887              * when we're shortening the file. */
00888             fseeko(ff, 2 * sizeof(fbuf) + vlength - length, SEEK_CUR);
00889          }
00890 
00891          /* Last part of the file that we need to preserve */
00892          if (fseeko(ff, offset + length, SEEK_SET)) {
00893             ast_log(LOG_WARNING, "Unable to seek to %" PRId64 " + %" PRId64 " != %" PRId64 "?)\n", offset, length, ftello(ff));
00894          }
00895 
00896          /* Doesn't matter how much we read -- just need to restrict the write */
00897          ast_debug(1, "Reading at %" PRId64 "\n", ftello(ff));
00898          if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
00899             ast_log(LOG_ERROR, "Short read?!!\n");
00900          }
00901          fseek(ff, offset, SEEK_SET);
00902          /* Write out the value, then write just up until where we last moved some data */
00903          if (fwrite(value, 1, vlength, ff) < vlength) {
00904             ast_log(LOG_ERROR, "Short write?!!\n");
00905          } else {
00906             off_t curpos = ftello(ff);
00907             foplen = lastwritten - curpos;
00908             if (fwrite(fbuf, 1, foplen, ff) < foplen) {
00909                ast_log(LOG_ERROR, "Short write?!!\n");
00910             }
00911          }
00912          fclose(ff);
00913       }
00914    } else {
00915       enum file_format newline_format = FF_UNKNOWN;
00916 
00917       /* Line mode */
00918       if (args.argc == 5) {
00919          if (tolower(args.format[0]) == 'u') {
00920             newline_format = FF_UNIX;
00921          } else if (tolower(args.format[0]) == 'm') {
00922             newline_format = FF_MAC;
00923          } else if (tolower(args.format[0]) == 'd') {
00924             newline_format = FF_DOS;
00925          }
00926       }
00927       if (newline_format == FF_UNKNOWN && (newline_format = file2format(args.filename)) == FF_UNKNOWN) {
00928          ast_log(LOG_ERROR, "File '%s' not in line format\n", args.filename);
00929          return -1;
00930       }
00931 
00932       if (strchr(args.options, 'a')) {
00933          /* Append to file */
00934          if (!(ff = fopen(args.filename, "a"))) {
00935             ast_log(LOG_ERROR, "Unable to open '%s' for appending: %s\n", args.filename, strerror(errno));
00936             return -1;
00937          }
00938          if (fwrite(value, 1, vlength, ff) < vlength) {
00939             ast_log(LOG_ERROR, "Short write?!!\n");
00940          } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, strlen(format2term(newline_format)), ff) < strlen(format2term(newline_format))) {
00941             ast_log(LOG_ERROR, "Short write?!!\n");
00942          }
00943          fclose(ff);
00944       } else if (offset == 0 && length == LLONG_MAX) {
00945          /* Overwrite file */
00946          off_t truncsize;
00947          if (!(ff = fopen(args.filename, "w"))) {
00948             ast_log(LOG_ERROR, "Unable to open '%s' for writing: %s\n", args.filename, strerror(errno));
00949             return -1;
00950          }
00951          if (fwrite(value, 1, vlength, ff) < vlength) {
00952             ast_log(LOG_ERROR, "Short write?!!\n");
00953          } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, strlen(format2term(newline_format)), ff) < strlen(format2term(newline_format))) {
00954             ast_log(LOG_ERROR, "Short write?!!\n");
00955          }
00956          if ((truncsize = ftello(ff)) < 0) {
00957             ast_log(AST_LOG_ERROR, "Unable to determine truncate position of '%s': %s\n", args.filename, strerror(errno));
00958          }
00959          fclose(ff);
00960          if (truncsize >= 0 && truncate(args.filename, truncsize)) {
00961             ast_log(LOG_ERROR, "Unable to truncate file '%s': %s\n", args.filename, strerror(errno));
00962             return -1;
00963          }
00964       } else {
00965          int64_t offset_offset = (offset == 0 ? 0 : -1), length_offset = -1, flength, i, current_length = 0;
00966          char dos_state = 0, fbuf[4096];
00967 
00968          if (offset < 0 && length < offset) {
00969             /* Nonsense! */
00970             ast_log(LOG_ERROR, "Length cannot specify a position prior to the offset\n");
00971             return -1;
00972          }
00973 
00974          if (!(ff = fopen(args.filename, "r+"))) {
00975             ast_log(LOG_ERROR, "Cannot open '%s' for modification: %s\n", args.filename, strerror(errno));
00976             return -1;
00977          }
00978 
00979          if (fseek(ff, 0, SEEK_END)) {
00980             ast_log(LOG_ERROR, "Cannot seek to end of file '%s': %s\n", args.filename, strerror(errno));
00981             fclose(ff);
00982             return -1;
00983          }
00984          if ((flength = ftello(ff)) < 0) {
00985             ast_log(AST_LOG_ERROR, "Cannot determine end position of file '%s': %s\n", args.filename, strerror(errno));
00986             fclose(ff);
00987             return -1;
00988          }
00989 
00990          /* For negative offset and/or negative length */
00991          if (offset < 0 || length < 0) {
00992             int64_t count = 0;
00993             for (i = (flength / sizeof(fbuf)) * sizeof(fbuf); i >= 0; i -= sizeof(fbuf)) {
00994                char *pos;
00995                if (fseeko(ff, i, SEEK_SET)) {
00996                   ast_log(LOG_ERROR, "Cannot seek to offset %" PRId64 ": %s\n", i, strerror(errno));
00997                }
00998                if (i + sizeof(fbuf) >= flength) {
00999                   memset(fbuf, 0, sizeof(fbuf));
01000                }
01001                if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
01002                   ast_log(LOG_ERROR, "Short read: %s\n", strerror(errno));
01003                   fclose(ff);
01004                   return -1;
01005                }
01006                for (pos = fbuf + sizeof(fbuf) - 1; pos > fbuf - 1; pos--) {
01007                   LINE_COUNTER(pos, newline_format, count);
01008 
01009                   if (length < 0 && count * -1 == length) {
01010                      length_offset = i + (pos - fbuf);
01011                   } else if (offset < 0 && count * -1 == (offset - 1)) {
01012                      /* Found our initial offset.  We're done with reverse motion! */
01013                      if (newline_format == FF_DOS) {
01014                         offset_offset = i + (pos - fbuf) + 2;
01015                      } else {
01016                         offset_offset = i + (pos - fbuf) + 1;
01017                      }
01018                      break;
01019                   }
01020                }
01021                if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
01022                   break;
01023                }
01024             }
01025             /* We're at the beginning, and the negative offset indicates the exact number of lines in the file */
01026             if (offset < 0 && offset_offset < 0 && offset == count * -1) {
01027                offset_offset = 0;
01028             }
01029          }
01030 
01031          /* Positve line offset */
01032          if (offset > 0) {
01033             int64_t count = 0;
01034             fseek(ff, 0, SEEK_SET);
01035             for (i = 0; i < flength; i += sizeof(fbuf)) {
01036                char *pos;
01037                if (i + sizeof(fbuf) >= flength) {
01038                   memset(fbuf, 0, sizeof(fbuf));
01039                }
01040                if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
01041                   ast_log(LOG_ERROR, "Short read?!!\n");
01042                   fclose(ff);
01043                   return -1;
01044                }
01045                for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
01046                   LINE_COUNTER(pos, newline_format, count);
01047 
01048                   if (count == offset) {
01049                      offset_offset = i + (pos - fbuf) + 1;
01050                      break;
01051                   }
01052                }
01053                if (offset_offset >= 0) {
01054                   break;
01055                }
01056             }
01057          }
01058 
01059          if (offset_offset < 0) {
01060             ast_log(LOG_ERROR, "Offset '%s' refers to before the beginning of the file!\n", args.offset);
01061             fclose(ff);
01062             return -1;
01063          }
01064 
01065          if (length == 0) {
01066             length_offset = offset_offset;
01067          } else if (length == LLONG_MAX) {
01068             length_offset = flength;
01069          }
01070 
01071          /* Positive line length */
01072          if (length_offset < 0) {
01073             fseeko(ff, offset_offset, SEEK_SET);
01074             for (i = offset_offset; i < flength; i += sizeof(fbuf)) {
01075                char *pos;
01076                if (i + sizeof(fbuf) >= flength) {
01077                   memset(fbuf, 0, sizeof(fbuf));
01078                }
01079                if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
01080                   ast_log(LOG_ERROR, "Short read?!!\n");
01081                   fclose(ff);
01082                   return -1;
01083                }
01084                for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
01085                   LINE_COUNTER(pos, newline_format, current_length);
01086 
01087                   if (current_length == length) {
01088                      length_offset = i + (pos - fbuf) + 1;
01089                      break;
01090                   }
01091                }
01092                if (length_offset >= 0) {
01093                   break;
01094                }
01095             }
01096             if (length_offset < 0) {
01097                /* Exceeds length of file */
01098                ast_debug(3, "Exceeds length of file? length=%" PRId64 ", count=%" PRId64 ", flength=%" PRId64 "\n", length, current_length, flength);
01099                length_offset = flength;
01100             }
01101          }
01102 
01103          /* Have offset_offset and length_offset now */
01104          if (length_offset - offset_offset == vlength + (strchr(args.options, 'd') ? 0 : strlen(format2term(newline_format)))) {
01105             /* Simple case - replacement of text inline */
01106             fseeko(ff, offset_offset, SEEK_SET);
01107             if (fwrite(value, 1, vlength, ff) < vlength) {
01108                ast_log(LOG_ERROR, "Short write?!!\n");
01109             } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, strlen(format2term(newline_format)), ff) < strlen(format2term(newline_format))) {
01110                ast_log(LOG_ERROR, "Short write?!!\n");
01111             }
01112             fclose(ff);
01113          } else if (length_offset - offset_offset > vlength + (strchr(args.options, 'd') ? 0 : strlen(format2term(newline_format)))) {
01114             /* More complex case - need to shorten file */
01115             off_t cur;
01116             int64_t length_length = length_offset - offset_offset;
01117             size_t vlen = vlength + (strchr(args.options, 'd') ? 0 : strlen(format2term(newline_format)));
01118 
01119             ast_debug(3, "offset=%s/%" PRId64 ", length=%s/%" PRId64 " (%" PRId64 "), vlength=%" PRId64 ", flength=%" PRId64 "\n",
01120                args.offset, offset_offset, args.length, length_offset, length_length, vlength, flength);
01121 
01122             fseeko(ff, offset_offset, SEEK_SET);
01123             if (fwrite(value, 1, vlength, ff) < vlength) {
01124                ast_log(LOG_ERROR, "Short write?!!\n");
01125                fclose(ff);
01126                return -1;
01127             } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, vlen - vlength, ff) < vlen - vlength) {
01128                ast_log(LOG_ERROR, "Short write?!!\n");
01129                fclose(ff);
01130                return -1;
01131             }
01132             while ((cur = ftello(ff)) < flength) {
01133                if (cur < 0) {
01134                   ast_log(AST_LOG_ERROR, "Unable to determine last write position for '%s': %s\n", args.filename, strerror(errno));
01135                   fclose(ff);
01136                   return -1;
01137                }
01138                fseeko(ff, length_length - vlen, SEEK_CUR);
01139                if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
01140                   ast_log(LOG_ERROR, "Short read?!!\n");
01141                   fclose(ff);
01142                   return -1;
01143                }
01144                /* Seek to where we last stopped writing */
01145                fseeko(ff, cur, SEEK_SET);
01146                if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
01147                   ast_log(LOG_ERROR, "Short write?!!\n");
01148                   fclose(ff);
01149                   return -1;
01150                }
01151             }
01152             fclose(ff);
01153             if (truncate(args.filename, flength - (length_length - vlen))) {
01154                ast_log(LOG_ERROR, "Truncation of file failed: %s\n", strerror(errno));
01155             }
01156          } else {
01157             /* Most complex case - need to lengthen file */
01158             size_t vlen = vlength + (strchr(args.options, 'd') ? 0 : strlen(format2term(newline_format)));
01159             int64_t origlen = length_offset - offset_offset;
01160             off_t lastwritten = flength + vlen - origlen;
01161 
01162             ast_debug(3, "offset=%s/%" PRId64 ", length=%s/%" PRId64 ", vlength=%" PRId64 ", flength=%" PRId64 "\n",
01163                args.offset, offset_offset, args.length, length_offset, vlength, flength);
01164 
01165             fseeko(ff, flength - sizeof(fbuf), SEEK_SET);
01166             while (offset_offset + sizeof(fbuf) < ftello(ff)) {
01167                if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
01168                   ast_log(LOG_ERROR, "Short read?!!\n");
01169                   fclose(ff);
01170                   return -1;
01171                }
01172                fseeko(ff, sizeof(fbuf) - vlen - origlen, SEEK_CUR);
01173                if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
01174                   ast_log(LOG_ERROR, "Short write?!!\n");
01175                   fclose(ff);
01176                   return -1;
01177                }
01178                if ((lastwritten = ftello(ff) - sizeof(fbuf)) < offset_offset + sizeof(fbuf)) {
01179                   break;
01180                }
01181                fseeko(ff, 2 * sizeof(fbuf) + vlen - origlen, SEEK_CUR);
01182             }
01183             fseek(ff, length_offset, SEEK_SET);
01184             if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
01185                ast_log(LOG_ERROR, "Short read?!!\n");
01186                fclose(ff);
01187                return -1;
01188             }
01189             fseek(ff, offset_offset, SEEK_SET);
01190             if (fwrite(value, 1, vlength, ff) < vlength) {
01191                ast_log(LOG_ERROR, "Short write?!!\n");
01192                fclose(ff);
01193                return -1;
01194             } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, strlen(format2term(newline_format)), ff) < strlen(format2term(newline_format))) {
01195                ast_log(LOG_ERROR, "Short write?!!\n");
01196                fclose(ff);
01197                return -1;
01198             } else {
01199                off_t curpos = ftello(ff);
01200                foplen = lastwritten - curpos;
01201                if (fwrite(fbuf, 1, foplen, ff) < foplen) {
01202                   ast_log(LOG_ERROR, "Short write?!!\n");
01203                }
01204             }
01205             fclose(ff);
01206          }
01207       }
01208    }
01209 
01210    return 0;
01211 }

const char * format2term ( enum file_format  f  ) 

Definition at line 720 of file func_env.c.

Referenced by file_write().

00721 {
00722    const char *term[] = { "", "\n", "\r\n", "\r" };
00723    return term[f + 1];
00724 }

static int load_module ( void   )  [static]

Definition at line 1256 of file func_env.c.

References ast_custom_function_register, env_function, file_count_line_function, file_format_function, file_function, and stat_function.

01257 {
01258    int res = 0;
01259 
01260    res |= ast_custom_function_register(&env_function);
01261    res |= ast_custom_function_register(&stat_function);
01262    res |= ast_custom_function_register(&file_function);
01263    res |= ast_custom_function_register(&file_count_line_function);
01264    res |= ast_custom_function_register(&file_format_function);
01265 
01266    return res;
01267 }

static int stat_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 257 of file func_env.c.

References ast_copy_string(), and strsep().

00259 {
00260    char *action;
00261    struct stat s;
00262 
00263    ast_copy_string(buf, "0", len);
00264 
00265    action = strsep(&data, ",");
00266    if (stat(data, &s)) {
00267       return 0;
00268    } else {
00269       switch (*action) {
00270       case 'e':
00271          strcpy(buf, "1");
00272          break;
00273       case 's':
00274          snprintf(buf, len, "%d", (unsigned int) s.st_size);
00275          break;
00276       case 'f':
00277          snprintf(buf, len, "%d", S_ISREG(s.st_mode) ? 1 : 0);
00278          break;
00279       case 'd':
00280          snprintf(buf, len, "%d", S_ISDIR(s.st_mode) ? 1 : 0);
00281          break;
00282       case 'M':
00283          snprintf(buf, len, "%d", (int) s.st_mtime);
00284          break;
00285       case 'A':
00286          snprintf(buf, len, "%d", (int) s.st_mtime);
00287          break;
00288       case 'C':
00289          snprintf(buf, len, "%d", (int) s.st_ctime);
00290          break;
00291       case 'm':
00292          snprintf(buf, len, "%o", (int) s.st_mode);
00293          break;
00294       }
00295    }
00296 
00297    return 0;
00298 }

static int unload_module ( void   )  [static]

Definition at line 1243 of file func_env.c.

References ast_custom_function_unregister(), env_function, file_count_line_function, file_format_function, file_function, and stat_function.

01244 {
01245    int res = 0;
01246 
01247    res |= ast_custom_function_unregister(&env_function);
01248    res |= ast_custom_function_unregister(&stat_function);
01249    res |= ast_custom_function_unregister(&file_function);
01250    res |= ast_custom_function_unregister(&file_count_line_function);
01251    res |= ast_custom_function_unregister(&file_format_function);
01252 
01253    return res;
01254 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Environment/filesystem dialplan functions" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 1269 of file func_env.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1269 of file func_env.c.

struct ast_custom_function env_function [static]

Initial value:

 {
   .name = "ENV",
   .read = env_read,
   .write = env_write
}

Definition at line 1213 of file func_env.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function file_count_line_function [static]

Initial value:

 {
   .name = "FILE_COUNT_LINE",
   .read2 = file_count_line,
   .read_max = 12,
}

Definition at line 1231 of file func_env.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function file_format_function [static]

Initial value:

 {
   .name = "FILE_FORMAT",
   .read2 = file_format,
   .read_max = 2,
}

Definition at line 1237 of file func_env.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function file_function [static]

Initial value:

 {
   .name = "FILE",
   .read2 = file_read,
   .write = file_write,
}

Definition at line 1225 of file func_env.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function stat_function [static]

Initial value:

 {
   .name = "STAT",
   .read = stat_read,
   .read_max = 12,
}

Definition at line 1219 of file func_env.c.

Referenced by load_module(), and unload_module().


Generated on Mon Oct 8 12:39:23 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7