Asterisk - The Open Source Telephony Project  18.5.0
Macros | Enumerations | Functions | Variables
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"
Include dependency graph for func_env.c:

Go to the source code of this file.

Macros

#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)
 
struct ast_moduleAST_MODULE_SELF_SYM (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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const 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.

Macro Definition Documentation

◆ LINE_COUNTER

#define LINE_COUNTER (   cptr,
  term,
  counter 
)

Definition at line 425 of file func_env.c.

Referenced by file_read(), and file_write().

Enumeration Type Documentation

◆ file_format

Enumerator
FF_UNKNOWN 
FF_UNIX 
FF_DOS 
FF_MAC 

Definition at line 318 of file func_env.c.

318  {
319  FF_UNKNOWN = -1,
320  FF_UNIX,
321  FF_DOS,
322  FF_MAC,
323 };

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1289 of file func_env.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1289 of file func_env.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1289 of file func_env.c.

◆ count_lines()

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

Definition at line 325 of file func_env.c.

References ast_log, errno, FF_DOS, FF_MAC, FF_UNIX, FF_UNKNOWN, LOG_ERROR, and NULL.

Referenced by file_count_line().

326 {
327  int count = 0;
328  char fbuf[4096];
329  FILE *ff;
330 
331  if (!(ff = fopen(filename, "r"))) {
332  ast_log(LOG_ERROR, "Unable to open '%s': %s\n", filename, strerror(errno));
333  return -1;
334  }
335 
336  while (fgets(fbuf, sizeof(fbuf), ff)) {
337  char *next = fbuf, *first_cr = NULL, *first_nl = NULL;
338 
339  /* Must do it this way, because if the fileformat is FF_MAC, then Unix
340  * assumptions about line-format will not come into play. */
341  while (next) {
342  if (newline_format == FF_DOS || newline_format == FF_MAC || newline_format == FF_UNKNOWN) {
343  first_cr = strchr(next, '\r');
344  }
345  if (newline_format == FF_UNIX || newline_format == FF_UNKNOWN) {
346  first_nl = strchr(next, '\n');
347  }
348 
349  /* No terminators found in buffer */
350  if (!first_cr && !first_nl) {
351  break;
352  }
353 
354  if (newline_format == FF_UNKNOWN) {
355  if ((first_cr && !first_nl) || (first_cr && first_cr < first_nl)) {
356  if (first_nl && first_nl == first_cr + 1) {
357  newline_format = FF_DOS;
358  } else if (first_cr && first_cr == &fbuf[sizeof(fbuf) - 2]) {
359  /* Get it on the next pass */
360  fseek(ff, -1, SEEK_CUR);
361  break;
362  } else {
363  newline_format = FF_MAC;
364  first_nl = NULL;
365  }
366  } else {
367  newline_format = FF_UNIX;
368  first_cr = NULL;
369  }
370  /* Jump down into next section */
371  }
372 
373  if (newline_format == FF_DOS) {
374  if (first_nl && first_cr && first_nl == first_cr + 1) {
375  next = first_nl + 1;
376  count++;
377  } else if (first_cr == &fbuf[sizeof(fbuf) - 2]) {
378  /* Get it on the next pass */
379  fseek(ff, -1, SEEK_CUR);
380  break;
381  }
382  } else if (newline_format == FF_MAC) {
383  if (first_cr) {
384  next = first_cr + 1;
385  count++;
386  }
387  } else if (newline_format == FF_UNIX) {
388  if (first_nl) {
389  next = first_nl + 1;
390  count++;
391  }
392  }
393  }
394  }
395  fclose(ff);
396 
397  return count;
398 }
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
int errno

◆ env_read()

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

Definition at line 245 of file func_env.c.

References ast_copy_string(), and NULL.

247 {
248  char *ret = NULL;
249 
250  *buf = '\0';
251 
252  if (data)
253  ret = getenv(data);
254 
255  if (ret)
256  ast_copy_string(buf, ret, len);
257 
258  return 0;
259 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define NULL
Definition: resample.c:96
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ env_write()

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

Definition at line 261 of file func_env.c.

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

263 {
264  if (!ast_strlen_zero(data) && strncmp(data, "AST_", 4)) {
265  if (!ast_strlen_zero(value)) {
266  setenv(data, value, 1);
267  } else {
268  unsetenv(data);
269  }
270  }
271 
272  return 0;
273 }
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
int setenv(const char *name, const char *value, int overwrite)
int unsetenv(const char *name)

◆ file2format()

static enum file_format file2format ( const char *  filename)
static

Definition at line 439 of file func_env.c.

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

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

440 {
441  FILE *ff;
442  char fbuf[4096];
443  char *first_cr, *first_nl;
444  enum file_format newline_format = FF_UNKNOWN;
445 
446  if (!(ff = fopen(filename, "r"))) {
447  ast_log(LOG_ERROR, "Cannot open '%s': %s\n", filename, strerror(errno));
448  return -1;
449  }
450 
451  while (fgets(fbuf, sizeof(fbuf), ff)) {
452  first_cr = strchr(fbuf, '\r');
453  first_nl = strchr(fbuf, '\n');
454 
455  if (!first_cr && !first_nl) {
456  continue;
457  }
458 
459  if ((first_cr && !first_nl) || (first_cr && first_cr < first_nl)) {
460 
461  if (first_nl && first_nl == first_cr + 1) {
462  newline_format = FF_DOS;
463  } else if (first_cr && first_cr == &fbuf[sizeof(fbuf) - 2]) {
464  /* Edge case: get it on the next pass */
465  fseek(ff, -1, SEEK_CUR);
466  continue;
467  } else {
468  newline_format = FF_MAC;
469  }
470  } else {
471  newline_format = FF_UNIX;
472  }
473  break;
474  }
475  fclose(ff);
476  return newline_format;
477 }
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
file_format
Definition: func_env.c:318
int errno

◆ file_count_line()

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 400 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, and format.

401 {
402  enum file_format newline_format = FF_UNKNOWN;
403  int64_t count;
405  AST_APP_ARG(filename);
407  );
408 
410  if (args.argc > 1) {
411  if (tolower(args.format[0]) == 'd') {
412  newline_format = FF_DOS;
413  } else if (tolower(args.format[0]) == 'm') {
414  newline_format = FF_MAC;
415  } else if (tolower(args.format[0]) == 'u') {
416  newline_format = FF_UNIX;
417  }
418  }
419 
420  count = count_lines(args.filename, newline_format);
421  ast_str_set(buf, len, "%" PRId64, count);
422  return 0;
423 }
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
const char * args
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
static int64_t count_lines(const char *filename, enum file_format newline_format)
Definition: func_env.c:325
file_format
Definition: func_env.c:318
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static snd_pcm_format_t format
Definition: chan_alsa.c:102
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ file_format()

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

Definition at line 479 of file func_env.c.

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

480 {
481  enum file_format newline_format = file2format(data);
482  ast_str_set(buf, len, "%c", newline_format == FF_UNIX ? 'u' : newline_format == FF_DOS ? 'd' : newline_format == FF_MAC ? 'm' : 'x');
483  return 0;
484 }
static enum file_format file2format(const char *filename)
Definition: func_env.c:439
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
file_format
Definition: func_env.c:318
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ file_read()

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

Definition at line 486 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(), end, errno, FF_DOS, FF_MAC, FF_UNIX, FF_UNKNOWN, file2format(), format, format2term(), LINE_COUNTER, LLONG_MAX, LOG_ERROR, LOG_WARNING, MIN, and options.

487 {
488  FILE *ff;
489  int64_t offset = 0, length = LLONG_MAX;
491  char fbuf[4096];
492  int64_t flength, i; /* iterator needs to be signed, so it can go negative and terminate the loop */
493  int64_t offset_offset = -1, length_offset = -1;
494  char dos_state = 0;
496  AST_APP_ARG(filename);
497  AST_APP_ARG(offset);
498  AST_APP_ARG(length);
500  AST_APP_ARG(fileformat);
501  );
502 
504 
505  if (args.argc > 1) {
506  sscanf(args.offset, "%" SCNd64, &offset);
507  }
508  if (args.argc > 2) {
509  sscanf(args.length, "%" SCNd64, &length);
510  }
511 
512  if (args.argc < 4 || !strchr(args.options, 'l')) {
513  /* Character-based mode */
514  off_t off_i;
515 
516  if (!(ff = fopen(args.filename, "r"))) {
517  ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", args.filename, strerror(errno));
518  return 0;
519  }
520 
521  if (fseeko(ff, 0, SEEK_END) < 0) {
522  ast_log(LOG_ERROR, "Cannot seek to end of '%s': %s\n", args.filename, strerror(errno));
523  fclose(ff);
524  return -1;
525  }
526  flength = ftello(ff);
527 
528  if (offset < 0) {
529  fseeko(ff, offset, SEEK_END);
530  if ((offset = ftello(ff)) < 0) {
531  ast_log(AST_LOG_ERROR, "Cannot determine offset position of '%s': %s\n", args.filename, strerror(errno));
532  fclose(ff);
533  return -1;
534  }
535  }
536  if (length < 0) {
537  fseeko(ff, length, SEEK_END);
538  if ((length = ftello(ff)) - offset < 0) {
539  /* Eliminates all results */
540  fclose(ff);
541  return -1;
542  }
543  } else if (length == LLONG_MAX) {
544  fseeko(ff, 0, SEEK_END);
545  length = ftello(ff);
546  }
547 
548  ast_str_reset(*buf);
549 
550  fseeko(ff, offset, SEEK_SET);
551  for (off_i = ftello(ff); off_i < flength && off_i < offset + length; off_i += sizeof(fbuf)) {
552  /* Calculate if we need to retrieve just a portion of the file in memory */
553  size_t toappend = sizeof(fbuf);
554 
555  if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
556  ast_log(LOG_ERROR, "Short read?!!\n");
557  break;
558  }
559 
560  /* Don't go past the length requested */
561  if (off_i + toappend > offset + length) {
562  toappend = MIN(offset + length - off_i, flength - off_i);
563  }
564 
565  ast_str_append_substr(buf, len, fbuf, toappend);
566  }
567  fclose(ff);
568  return 0;
569  }
570 
571  /* Line-based read */
572  if (args.argc == 5) {
573  if (tolower(args.fileformat[0]) == 'd') {
574  format = FF_DOS;
575  } else if (tolower(args.fileformat[0]) == 'm') {
576  format = FF_MAC;
577  } else if (tolower(args.fileformat[0]) == 'u') {
578  format = FF_UNIX;
579  }
580  }
581 
582  if (format == FF_UNKNOWN) {
583  if ((format = file2format(args.filename)) == FF_UNKNOWN) {
584  ast_log(LOG_WARNING, "'%s' is not a line-based file\n", args.filename);
585  return -1;
586  }
587  }
588 
589  if (offset < 0 && length <= offset) {
590  /* Length eliminates all content */
591  return -1;
592  } else if (offset == 0) {
593  offset_offset = 0;
594  }
595 
596  if (!(ff = fopen(args.filename, "r"))) {
597  ast_log(LOG_ERROR, "Cannot open '%s': %s\n", args.filename, strerror(errno));
598  return -1;
599  }
600 
601  if (fseek(ff, 0, SEEK_END)) {
602  ast_log(LOG_ERROR, "Cannot seek to end of file '%s': %s\n", args.filename, strerror(errno));
603  fclose(ff);
604  return -1;
605  }
606 
607  flength = ftello(ff);
608 
609  if (length == LLONG_MAX) {
610  length_offset = flength;
611  }
612 
613  /* For negative offset and/or negative length */
614  if (offset < 0 || length < 0) {
615  int64_t count = 0;
616  /* Start with an even multiple of fbuf, so at the end of reading with a
617  * 0 offset, we don't try to go past the beginning of the file. */
618  for (i = (flength / sizeof(fbuf)) * sizeof(fbuf); i >= 0; i -= sizeof(fbuf)) {
619  size_t end;
620  char *pos;
621  if (fseeko(ff, i, SEEK_SET)) {
622  ast_log(LOG_ERROR, "Cannot seek to offset %" PRId64 ": %s\n", i, strerror(errno));
623  }
624  end = fread(fbuf, 1, sizeof(fbuf), ff);
625  for (pos = (end < sizeof(fbuf) ? fbuf + end - 1 : fbuf + sizeof(fbuf) - 1); pos >= fbuf; pos--) {
626  LINE_COUNTER(pos, format, count);
627 
628  if (length < 0 && count * -1 == length) {
629  length_offset = i + (pos - fbuf);
630  } else if (offset < 0 && count * -1 == (offset - 1)) {
631  /* Found our initial offset. We're done with reverse motion! */
632  if (format == FF_DOS) {
633  offset_offset = i + (pos - fbuf) + 2;
634  } else {
635  offset_offset = i + (pos - fbuf) + 1;
636  }
637  break;
638  }
639  }
640  if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
641  break;
642  }
643  }
644  /* We're at the beginning, and the negative offset indicates the exact number of lines in the file */
645  if (offset < 0 && offset_offset < 0 && offset == count * -1) {
646  offset_offset = 0;
647  }
648  }
649 
650  /* Positve line offset */
651  if (offset > 0) {
652  int64_t count = 0;
653  fseek(ff, 0, SEEK_SET);
654  for (i = 0; i < flength; i += sizeof(fbuf)) {
655  char *pos;
656  if (i + sizeof(fbuf) <= flength) {
657  /* Don't let previous values influence current counts, due to short reads */
658  memset(fbuf, 0, sizeof(fbuf));
659  }
660  if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
661  ast_log(LOG_ERROR, "Short read?!!\n");
662  fclose(ff);
663  return -1;
664  }
665  for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
666  LINE_COUNTER(pos, format, count);
667 
668  if (count == offset) {
669  offset_offset = i + (pos - fbuf) + 1;
670  break;
671  }
672  }
673  if (offset_offset >= 0) {
674  break;
675  }
676  }
677  }
678 
679  if (offset_offset < 0) {
680  ast_log(LOG_ERROR, "Offset '%s' refers to before the beginning of the file!\n", args.offset);
681  fclose(ff);
682  return -1;
683  }
684 
685  ast_str_reset(*buf);
686  if (fseeko(ff, offset_offset, SEEK_SET)) {
687  ast_log(LOG_ERROR, "fseeko failed: %s\n", strerror(errno));
688  }
689 
690  /* If we have both offset_offset and length_offset, then grabbing the
691  * buffer is simply a matter of just retrieving the file and adding it
692  * to buf. Otherwise, we need to run byte-by-byte forward until the
693  * length is complete. */
694  if (length_offset >= 0) {
695  ast_debug(3, "offset=%" PRId64 ", length=%" PRId64 ", offset_offset=%" PRId64 ", length_offset=%" PRId64 "\n", offset, length, offset_offset, length_offset);
696  for (i = offset_offset; i < length_offset; i += sizeof(fbuf)) {
697  if (fread(fbuf, 1, i + sizeof(fbuf) > flength ? flength - i : sizeof(fbuf), ff) < (i + sizeof(fbuf) > flength ? flength - i : sizeof(fbuf))) {
698  ast_log(LOG_ERROR, "Short read?!!\n");
699  }
700  ast_debug(3, "Appending first %" PRId64" bytes of fbuf=%s\n", (int64_t)(i + sizeof(fbuf) > length_offset ? length_offset - i : sizeof(fbuf)), fbuf);
701  ast_str_append_substr(buf, len, fbuf, i + sizeof(fbuf) > length_offset ? length_offset - i : sizeof(fbuf));
702  }
703  } else if (length == 0) {
704  /* Nothing to do */
705  } else {
706  /* Positive line offset */
707  int64_t current_length = 0;
708  char dos_state = 0;
709  ast_debug(3, "offset=%" PRId64 ", length=%" PRId64 ", offset_offset=%" PRId64 ", length_offset=%" PRId64 "\n", offset, length, offset_offset, length_offset);
710  for (i = offset_offset; i < flength; i += sizeof(fbuf)) {
711  char *pos;
712  size_t bytes_read;
713  if ((bytes_read = fread(fbuf, 1, sizeof(fbuf), ff)) < sizeof(fbuf) && !feof(ff)) {
714  ast_log(LOG_ERROR, "Short read?!!\n");
715  fclose(ff);
716  return -1;
717  }
718  for (pos = fbuf; pos < fbuf + bytes_read; pos++) {
719  LINE_COUNTER(pos, format, current_length);
720 
721  if (current_length == length) {
722  length_offset = i + (pos - fbuf) + 1;
723  break;
724  }
725  }
726  ast_debug(3, "length_offset=%" PRId64 ", length_offset - i=%" PRId64 "\n", length_offset, length_offset - i);
727  ast_str_append_substr(buf, len, fbuf, (length_offset >= 0) ? length_offset - i : (flength > i + sizeof(fbuf)) ? sizeof(fbuf) : flength - i);
728 
729  if (length_offset >= 0) {
730  break;
731  }
732  }
733  }
734 
735  fclose(ff);
736  return 0;
737 }
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
const char * args
char * end
Definition: eagi_proxy.c:73
static enum file_format file2format(const char *filename)
Definition: func_env.c:439
#define MIN(a, b)
Definition: utils.h:226
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
char * ast_str_append_substr(struct ast_str **buf, ssize_t maxlen, const char *src, size_t maxsrc)
Append a non-NULL terminated substring to the end of a dynamic string.
Definition: strings.h:1014
#define LOG_ERROR
Definition: logger.h:285
file_format
Definition: func_env.c:318
#define LINE_COUNTER(cptr, term, counter)
Definition: func_env.c:425
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int errno
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:653
#define LLONG_MAX
static struct test_options options
static snd_pcm_format_t format
Definition: chan_alsa.c:102
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ file_write()

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

Definition at line 746 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(), format, format2term(), LINE_COUNTER, LLONG_MAX, LOG_ERROR, LOG_WARNING, options, and S_OR.

747 {
749  AST_APP_ARG(filename);
750  AST_APP_ARG(offset);
751  AST_APP_ARG(length);
754  );
755  int64_t offset = 0, length = LLONG_MAX;
756  off_t flength, vlength;
757  size_t foplen = 0;
758  FILE *ff;
759 
761 
762  if (args.argc > 1) {
763  sscanf(args.offset, "%" SCNd64, &offset);
764  }
765  if (args.argc > 2) {
766  sscanf(args.length, "%" SCNd64, &length);
767  }
768 
769  vlength = strlen(value);
770 
771  if (args.argc < 4 || !strchr(args.options, 'l')) {
772  /* Character-based mode */
773 
774  if (args.argc > 3 && strchr(args.options, 'a')) {
775  /* Append mode */
776  if (!(ff = fopen(args.filename, "a"))) {
777  ast_log(LOG_WARNING, "Cannot open file '%s' for appending: %s\n", args.filename, strerror(errno));
778  return 0;
779  }
780  if (fwrite(value, 1, vlength, ff) < vlength) {
781  ast_log(LOG_ERROR, "Short write?!!\n");
782  }
783  fclose(ff);
784  return 0;
785  } else if (offset == 0 && length == LLONG_MAX) {
786  if (!(ff = fopen(args.filename, "w"))) {
787  ast_log(LOG_WARNING, "Cannot open file '%s' for writing: %s\n", args.filename, strerror(errno));
788  return 0;
789  }
790  if (fwrite(value, 1, vlength, ff) < vlength) {
791  ast_log(LOG_ERROR, "Short write?!!\n");
792  }
793  fclose(ff);
794  return 0;
795  }
796 
797  if (!(ff = fopen(args.filename, "r+"))) {
798  ast_log(LOG_WARNING, "Cannot open file '%s' for modification: %s\n", args.filename, strerror(errno));
799  return 0;
800  }
801  fseeko(ff, 0, SEEK_END);
802  flength = ftello(ff);
803 
804  if (offset < 0) {
805  if (fseeko(ff, offset, SEEK_END)) {
806  ast_log(LOG_ERROR, "Cannot seek to offset of '%s': %s\n", args.filename, strerror(errno));
807  fclose(ff);
808  return -1;
809  }
810  if ((offset = ftello(ff)) < 0) {
811  ast_log(AST_LOG_ERROR, "Cannot determine offset position of '%s': %s\n", args.filename, strerror(errno));
812  fclose(ff);
813  return -1;
814  }
815  }
816 
817  if (length < 0) {
818  length = flength - offset + length;
819  if (length < 0) {
820  ast_log(LOG_ERROR, "Length '%s' exceeds the file length. No data will be written.\n", args.length);
821  fclose(ff);
822  return -1;
823  }
824  }
825 
826  fseeko(ff, offset, SEEK_SET);
827 
828  ast_debug(3, "offset=%s/%" PRId64 ", length=%s/%" PRId64 ", vlength=%" PRId64 ", flength=%" PRId64 "\n",
829  S_OR(args.offset, "(null)"), offset, S_OR(args.length, "(null)"), length, vlength, flength);
830 
831  if (length == vlength) {
832  /* Simplest case, a straight replace */
833  if (fwrite(value, 1, vlength, ff) < vlength) {
834  ast_log(LOG_ERROR, "Short write?!!\n");
835  }
836  fclose(ff);
837  } else if (length == LLONG_MAX) {
838  /* Simple truncation */
839  if (fwrite(value, 1, vlength, ff) < vlength) {
840  ast_log(LOG_ERROR, "Short write?!!\n");
841  }
842  fclose(ff);
843  if (truncate(args.filename, offset + vlength)) {
844  ast_log(LOG_ERROR, "Unable to truncate the file: %s\n", strerror(errno));
845  }
846  } else if (length > vlength) {
847  /* More complex -- need to close a gap */
848  char fbuf[4096];
849  off_t cur;
850  if (fwrite(value, 1, vlength, ff) < vlength) {
851  ast_log(LOG_ERROR, "Short write?!!\n");
852  }
853  fseeko(ff, length - vlength, SEEK_CUR);
854  while ((cur = ftello(ff)) < flength) {
855  if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
856  ast_log(LOG_ERROR, "Short read?!!\n");
857  }
858  fseeko(ff, cur + vlength - length, SEEK_SET);
859  if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
860  ast_log(LOG_ERROR, "Short write?!!\n");
861  }
862  /* Seek to where we stopped reading */
863  if (fseeko(ff, cur + sizeof(fbuf), SEEK_SET) < 0) {
864  /* Only reason for seek to fail is EOF */
865  break;
866  }
867  }
868  fclose(ff);
869  if (truncate(args.filename, flength - (length - vlength))) {
870  ast_log(LOG_ERROR, "Unable to truncate the file: %s\n", strerror(errno));
871  }
872  } else {
873  /* Most complex -- need to open a gap */
874  char fbuf[4096];
875  off_t lastwritten = flength + vlength - length;
876 
877  /* Start reading exactly the buffer size back from the end. */
878  fseeko(ff, flength - sizeof(fbuf), SEEK_SET);
879  while (offset < ftello(ff)) {
880  if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
881  ast_log(LOG_ERROR, "Short read?!!\n");
882  fclose(ff);
883  return -1;
884  }
885  /* Since the read moved our file ptr forward, we reverse, but
886  * seek an offset equal to the amount we want to extend the
887  * file by */
888  fseeko(ff, vlength - length - sizeof(fbuf), SEEK_CUR);
889 
890  /* Note the location of this buffer -- we must not overwrite this position. */
891  lastwritten = ftello(ff);
892 
893  if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
894  ast_log(LOG_ERROR, "Short write?!!\n");
895  fclose(ff);
896  return -1;
897  }
898 
899  if (lastwritten < offset + sizeof(fbuf)) {
900  break;
901  }
902  /* Our file pointer is now either pointing to the end of the
903  * file (new position) or a multiple of the fbuf size back from
904  * that point. Move back to where we want to start reading
905  * again. We never actually try to read beyond the end of the
906  * file, so we don't have do deal with short reads, as we would
907  * when we're shortening the file. */
908  fseeko(ff, 2 * sizeof(fbuf) + vlength - length, SEEK_CUR);
909  }
910 
911  /* Last part of the file that we need to preserve */
912  if (fseeko(ff, offset + length, SEEK_SET)) {
913  ast_log(LOG_WARNING, "Unable to seek to %" PRId64 " + %" PRId64 " != %" PRId64 "?)\n", offset, length, ftello(ff));
914  }
915 
916  /* Doesn't matter how much we read -- just need to restrict the write */
917  ast_debug(1, "Reading at %" PRId64 "\n", ftello(ff));
918  if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
919  ast_log(LOG_ERROR, "Short read?!!\n");
920  }
921  fseek(ff, offset, SEEK_SET);
922  /* Write out the value, then write just up until where we last moved some data */
923  if (fwrite(value, 1, vlength, ff) < vlength) {
924  ast_log(LOG_ERROR, "Short write?!!\n");
925  } else {
926  off_t curpos = ftello(ff);
927  foplen = lastwritten - curpos;
928  if (fwrite(fbuf, 1, foplen, ff) < foplen) {
929  ast_log(LOG_ERROR, "Short write?!!\n");
930  }
931  }
932  fclose(ff);
933  }
934  } else {
935  enum file_format newline_format = FF_UNKNOWN;
936 
937  /* Line mode */
938  if (args.argc == 5) {
939  if (tolower(args.format[0]) == 'u') {
940  newline_format = FF_UNIX;
941  } else if (tolower(args.format[0]) == 'm') {
942  newline_format = FF_MAC;
943  } else if (tolower(args.format[0]) == 'd') {
944  newline_format = FF_DOS;
945  }
946  }
947  if (newline_format == FF_UNKNOWN && (newline_format = file2format(args.filename)) == FF_UNKNOWN) {
948  ast_log(LOG_ERROR, "File '%s' not in line format\n", args.filename);
949  return -1;
950  }
951 
952  if (strchr(args.options, 'a')) {
953  /* Append to file */
954  if (!(ff = fopen(args.filename, "a"))) {
955  ast_log(LOG_ERROR, "Unable to open '%s' for appending: %s\n", args.filename, strerror(errno));
956  return -1;
957  }
958  if (fwrite(value, 1, vlength, ff) < vlength) {
959  ast_log(LOG_ERROR, "Short write?!!\n");
960  } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, strlen(format2term(newline_format)), ff) < strlen(format2term(newline_format))) {
961  ast_log(LOG_ERROR, "Short write?!!\n");
962  }
963  fclose(ff);
964  } else if (offset == 0 && length == LLONG_MAX) {
965  /* Overwrite file */
966  off_t truncsize;
967  if (!(ff = fopen(args.filename, "w"))) {
968  ast_log(LOG_ERROR, "Unable to open '%s' for writing: %s\n", args.filename, strerror(errno));
969  return -1;
970  }
971  if (fwrite(value, 1, vlength, ff) < vlength) {
972  ast_log(LOG_ERROR, "Short write?!!\n");
973  } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, strlen(format2term(newline_format)), ff) < strlen(format2term(newline_format))) {
974  ast_log(LOG_ERROR, "Short write?!!\n");
975  }
976  if ((truncsize = ftello(ff)) < 0) {
977  ast_log(AST_LOG_ERROR, "Unable to determine truncate position of '%s': %s\n", args.filename, strerror(errno));
978  }
979  fclose(ff);
980  if (truncsize >= 0 && truncate(args.filename, truncsize)) {
981  ast_log(LOG_ERROR, "Unable to truncate file '%s': %s\n", args.filename, strerror(errno));
982  return -1;
983  }
984  } else {
985  int64_t offset_offset = (offset == 0 ? 0 : -1), length_offset = -1, flength, i, current_length = 0;
986  char dos_state = 0, fbuf[4096];
987 
988  if (offset < 0 && length < offset) {
989  /* Nonsense! */
990  ast_log(LOG_ERROR, "Length cannot specify a position prior to the offset\n");
991  return -1;
992  }
993 
994  if (!(ff = fopen(args.filename, "r+"))) {
995  ast_log(LOG_ERROR, "Cannot open '%s' for modification: %s\n", args.filename, strerror(errno));
996  return -1;
997  }
998 
999  if (fseek(ff, 0, SEEK_END)) {
1000  ast_log(LOG_ERROR, "Cannot seek to end of file '%s': %s\n", args.filename, strerror(errno));
1001  fclose(ff);
1002  return -1;
1003  }
1004  if ((flength = ftello(ff)) < 0) {
1005  ast_log(AST_LOG_ERROR, "Cannot determine end position of file '%s': %s\n", args.filename, strerror(errno));
1006  fclose(ff);
1007  return -1;
1008  }
1009 
1010  /* For negative offset and/or negative length */
1011  if (offset < 0 || length < 0) {
1012  int64_t count = 0;
1013  for (i = (flength / sizeof(fbuf)) * sizeof(fbuf); i >= 0; i -= sizeof(fbuf)) {
1014  char *pos;
1015  if (fseeko(ff, i, SEEK_SET)) {
1016  ast_log(LOG_ERROR, "Cannot seek to offset %" PRId64 ": %s\n", i, strerror(errno));
1017  }
1018  if (i + sizeof(fbuf) >= flength) {
1019  memset(fbuf, 0, sizeof(fbuf));
1020  }
1021  if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1022  ast_log(LOG_ERROR, "Short read: %s\n", strerror(errno));
1023  fclose(ff);
1024  return -1;
1025  }
1026  for (pos = fbuf + sizeof(fbuf) - 1; pos >= fbuf; pos--) {
1027  LINE_COUNTER(pos, newline_format, count);
1028 
1029  if (length < 0 && count * -1 == length) {
1030  length_offset = i + (pos - fbuf);
1031  } else if (offset < 0 && count * -1 == (offset - 1)) {
1032  /* Found our initial offset. We're done with reverse motion! */
1033  if (newline_format == FF_DOS) {
1034  offset_offset = i + (pos - fbuf) + 2;
1035  } else {
1036  offset_offset = i + (pos - fbuf) + 1;
1037  }
1038  break;
1039  }
1040  }
1041  if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
1042  break;
1043  }
1044  }
1045  /* We're at the beginning, and the negative offset indicates the exact number of lines in the file */
1046  if (offset < 0 && offset_offset < 0 && offset == count * -1) {
1047  offset_offset = 0;
1048  }
1049  }
1050 
1051  /* Positve line offset */
1052  if (offset > 0) {
1053  int64_t count = 0;
1054  fseek(ff, 0, SEEK_SET);
1055  for (i = 0; i < flength; i += sizeof(fbuf)) {
1056  char *pos;
1057  if (i + sizeof(fbuf) >= flength) {
1058  memset(fbuf, 0, sizeof(fbuf));
1059  }
1060  if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1061  ast_log(LOG_ERROR, "Short read?!!\n");
1062  fclose(ff);
1063  return -1;
1064  }
1065  for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
1066  LINE_COUNTER(pos, newline_format, count);
1067 
1068  if (count == offset) {
1069  offset_offset = i + (pos - fbuf) + 1;
1070  break;
1071  }
1072  }
1073  if (offset_offset >= 0) {
1074  break;
1075  }
1076  }
1077  }
1078 
1079  if (offset_offset < 0) {
1080  ast_log(LOG_ERROR, "Offset '%s' refers to before the beginning of the file!\n", args.offset);
1081  fclose(ff);
1082  return -1;
1083  }
1084 
1085  if (length == 0) {
1086  length_offset = offset_offset;
1087  } else if (length == LLONG_MAX) {
1088  length_offset = flength;
1089  }
1090 
1091  /* Positive line length */
1092  if (length_offset < 0) {
1093  fseeko(ff, offset_offset, SEEK_SET);
1094  for (i = offset_offset; i < flength; i += sizeof(fbuf)) {
1095  char *pos;
1096  if (i + sizeof(fbuf) >= flength) {
1097  memset(fbuf, 0, sizeof(fbuf));
1098  }
1099  if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1100  ast_log(LOG_ERROR, "Short read?!!\n");
1101  fclose(ff);
1102  return -1;
1103  }
1104  for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
1105  LINE_COUNTER(pos, newline_format, current_length);
1106 
1107  if (current_length == length) {
1108  length_offset = i + (pos - fbuf) + 1;
1109  break;
1110  }
1111  }
1112  if (length_offset >= 0) {
1113  break;
1114  }
1115  }
1116  if (length_offset < 0) {
1117  /* Exceeds length of file */
1118  ast_debug(3, "Exceeds length of file? length=%" PRId64 ", count=%" PRId64 ", flength=%" PRId64 "\n", length, current_length, flength);
1119  length_offset = flength;
1120  }
1121  }
1122 
1123  /* Have offset_offset and length_offset now */
1124  if (length_offset - offset_offset == vlength + (strchr(args.options, 'd') ? 0 : strlen(format2term(newline_format)))) {
1125  /* Simple case - replacement of text inline */
1126  fseeko(ff, offset_offset, SEEK_SET);
1127  if (fwrite(value, 1, vlength, ff) < vlength) {
1128  ast_log(LOG_ERROR, "Short write?!!\n");
1129  } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, strlen(format2term(newline_format)), ff) < strlen(format2term(newline_format))) {
1130  ast_log(LOG_ERROR, "Short write?!!\n");
1131  }
1132  fclose(ff);
1133  } else if (length_offset - offset_offset > vlength + (strchr(args.options, 'd') ? 0 : strlen(format2term(newline_format)))) {
1134  /* More complex case - need to shorten file */
1135  off_t cur;
1136  int64_t length_length = length_offset - offset_offset;
1137  size_t vlen = vlength + (strchr(args.options, 'd') ? 0 : strlen(format2term(newline_format)));
1138 
1139  ast_debug(3, "offset=%s/%" PRId64 ", length=%s/%" PRId64 " (%" PRId64 "), vlength=%" PRId64 ", flength=%" PRId64 "\n",
1140  args.offset, offset_offset, args.length, length_offset, length_length, vlength, flength);
1141 
1142  fseeko(ff, offset_offset, SEEK_SET);
1143  if (fwrite(value, 1, vlength, ff) < vlength) {
1144  ast_log(LOG_ERROR, "Short write?!!\n");
1145  fclose(ff);
1146  return -1;
1147  } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, vlen - vlength, ff) < vlen - vlength) {
1148  ast_log(LOG_ERROR, "Short write?!!\n");
1149  fclose(ff);
1150  return -1;
1151  }
1152  while ((cur = ftello(ff)) < flength) {
1153  if (cur < 0) {
1154  ast_log(AST_LOG_ERROR, "Unable to determine last write position for '%s': %s\n", args.filename, strerror(errno));
1155  fclose(ff);
1156  return -1;
1157  }
1158  fseeko(ff, length_length - vlen, SEEK_CUR);
1159  if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1160  ast_log(LOG_ERROR, "Short read?!!\n");
1161  fclose(ff);
1162  return -1;
1163  }
1164  /* Seek to where we last stopped writing */
1165  fseeko(ff, cur, SEEK_SET);
1166  if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1167  ast_log(LOG_ERROR, "Short write?!!\n");
1168  fclose(ff);
1169  return -1;
1170  }
1171  }
1172  fclose(ff);
1173  if (truncate(args.filename, flength - (length_length - vlen))) {
1174  ast_log(LOG_ERROR, "Truncation of file failed: %s\n", strerror(errno));
1175  }
1176  } else {
1177  /* Most complex case - need to lengthen file */
1178  size_t vlen = vlength + (strchr(args.options, 'd') ? 0 : strlen(format2term(newline_format)));
1179  int64_t origlen = length_offset - offset_offset;
1180  off_t lastwritten = flength + vlen - origlen;
1181 
1182  ast_debug(3, "offset=%s/%" PRId64 ", length=%s/%" PRId64 ", vlength=%" PRId64 ", flength=%" PRId64 "\n",
1183  args.offset, offset_offset, args.length, length_offset, vlength, flength);
1184 
1185  fseeko(ff, flength - sizeof(fbuf), SEEK_SET);
1186  while (offset_offset + sizeof(fbuf) < ftello(ff)) {
1187  if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1188  ast_log(LOG_ERROR, "Short read?!!\n");
1189  fclose(ff);
1190  return -1;
1191  }
1192  fseeko(ff, sizeof(fbuf) - vlen - origlen, SEEK_CUR);
1193  if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1194  ast_log(LOG_ERROR, "Short write?!!\n");
1195  fclose(ff);
1196  return -1;
1197  }
1198  if ((lastwritten = ftello(ff) - sizeof(fbuf)) < offset_offset + sizeof(fbuf)) {
1199  break;
1200  }
1201  fseeko(ff, 2 * sizeof(fbuf) + vlen - origlen, SEEK_CUR);
1202  }
1203  fseek(ff, length_offset, SEEK_SET);
1204  if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1205  ast_log(LOG_ERROR, "Short read?!!\n");
1206  fclose(ff);
1207  return -1;
1208  }
1209  fseek(ff, offset_offset, SEEK_SET);
1210  if (fwrite(value, 1, vlength, ff) < vlength) {
1211  ast_log(LOG_ERROR, "Short write?!!\n");
1212  fclose(ff);
1213  return -1;
1214  } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, strlen(format2term(newline_format)), ff) < strlen(format2term(newline_format))) {
1215  ast_log(LOG_ERROR, "Short write?!!\n");
1216  fclose(ff);
1217  return -1;
1218  } else {
1219  off_t curpos = ftello(ff);
1220  foplen = lastwritten - curpos;
1221  if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1222  ast_log(LOG_ERROR, "Short write?!!\n");
1223  }
1224  }
1225  fclose(ff);
1226  }
1227  }
1228  }
1229 
1230  return 0;
1231 }
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
const char * format2term(enum file_format f)
Definition: func_env.c:740
const char * args
int value
Definition: syslog.c:37
static enum file_format file2format(const char *filename)
Definition: func_env.c:439
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
#define LOG_ERROR
Definition: logger.h:285
file_format
Definition: func_env.c:318
#define LINE_COUNTER(cptr, term, counter)
Definition: func_env.c:425
int errno
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
#define LLONG_MAX
static struct test_options options
static snd_pcm_format_t format
Definition: chan_alsa.c:102
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ format2term()

const char * format2term ( enum file_format  f)

Definition at line 740 of file func_env.c.

Referenced by file_read(), and file_write().

741 {
742  const char *term[] = { "", "\n", "\r\n", "\r" };
743  return term[f + 1];
744 }

◆ load_module()

static int load_module ( void  )
static

Definition at line 1276 of file func_env.c.

References AST_CFE_BOTH, AST_CFE_READ, ast_custom_function_register, and ast_custom_function_register_escalating.

1277 {
1278  int res = 0;
1279 
1285 
1286  return res;
1287 }
static struct ast_custom_function file_function
Definition: func_env.c:1245
static struct ast_custom_function file_count_line_function
Definition: func_env.c:1251
static struct ast_custom_function file_format_function
Definition: func_env.c:1257
#define ast_custom_function_register_escalating(acf, escalation)
Register a custom function which requires escalated privileges.
Definition: pbx.h:1517
static struct ast_custom_function env_function
Definition: func_env.c:1233
static struct ast_custom_function stat_function
Definition: func_env.c:1239
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508

◆ stat_read()

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

Definition at line 275 of file func_env.c.

References ast_copy_string(), and strsep().

277 {
278  char *action;
279  struct stat s;
280 
281  ast_copy_string(buf, "0", len);
282 
283  action = strsep(&data, ",");
284  if (stat(data, &s)) {
285  return 0;
286  } else {
287  switch (*action) {
288  case 'e':
289  strcpy(buf, "1");
290  break;
291  case 's':
292  snprintf(buf, len, "%u", (unsigned int) s.st_size);
293  break;
294  case 'f':
295  snprintf(buf, len, "%d", S_ISREG(s.st_mode) ? 1 : 0);
296  break;
297  case 'd':
298  snprintf(buf, len, "%d", S_ISDIR(s.st_mode) ? 1 : 0);
299  break;
300  case 'M':
301  snprintf(buf, len, "%d", (int) s.st_mtime);
302  break;
303  case 'A':
304  snprintf(buf, len, "%d", (int) s.st_mtime);
305  break;
306  case 'C':
307  snprintf(buf, len, "%d", (int) s.st_ctime);
308  break;
309  case 'm':
310  snprintf(buf, len, "%o", (unsigned int) s.st_mode);
311  break;
312  }
313  }
314 
315  return 0;
316 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * strsep(char **str, const char *delims)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1263 of file func_env.c.

References ast_custom_function_unregister().

1264 {
1265  int res = 0;
1266 
1272 
1273  return res;
1274 }
static struct ast_custom_function file_function
Definition: func_env.c:1245
static struct ast_custom_function file_count_line_function
Definition: func_env.c:1251
static struct ast_custom_function file_format_function
Definition: func_env.c:1257
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static struct ast_custom_function env_function
Definition: func_env.c:1233
static struct ast_custom_function stat_function
Definition: func_env.c:1239

Variable Documentation

◆ __mod_info

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 1289 of file func_env.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1289 of file func_env.c.

◆ env_function

struct ast_custom_function env_function
static
Initial value:
= {
.name = "ENV",
.read = env_read,
.write = env_write
}
static int env_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_env.c:245
static int env_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: func_env.c:261

Definition at line 1233 of file func_env.c.

◆ file_count_line_function

struct ast_custom_function file_count_line_function
static
Initial value:
= {
.name = "FILE_COUNT_LINE",
.read2 = file_count_line,
.read_max = 12,
}
static int file_count_line(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_env.c:400

Definition at line 1251 of file func_env.c.

◆ file_format_function

struct ast_custom_function file_format_function
static
Initial value:
= {
.name = "FILE_FORMAT",
.read2 = file_format,
.read_max = 2,
}
file_format
Definition: func_env.c:318

Definition at line 1257 of file func_env.c.

◆ file_function

struct ast_custom_function file_function
static
Initial value:
= {
.name = "FILE",
.read2 = file_read,
.write = file_write,
}
static int file_read(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_env.c:486
static int file_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: func_env.c:746

Definition at line 1245 of file func_env.c.

◆ stat_function

struct ast_custom_function stat_function
static
Initial value:
= {
.name = "STAT",
.read = stat_read,
.read_max = 12,
}
static int stat_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_env.c:275

Definition at line 1239 of file func_env.c.