Wed Jan 8 2020 09:50:13

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.

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)
 
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.

Macro Definition Documentation

#define LINE_COUNTER (   cptr,
  term,
  counter 
)

Definition at line 427 of file func_env.c.

Referenced by file_read(), and file_write().

Enumeration Type Documentation

Enumerator
FF_UNKNOWN 
FF_UNIX 
FF_DOS 
FF_MAC 

Definition at line 320 of file func_env.c.

320  {
321  FF_UNKNOWN = -1,
322  FF_UNIX,
323  FF_DOS,
324  FF_MAC,
325 };

Function Documentation

static void __reg_module ( void  )
static

Definition at line 1289 of file func_env.c.

static void __unreg_module ( void  )
static

Definition at line 1289 of file func_env.c.

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

Definition at line 327 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().

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

Definition at line 247 of file func_env.c.

References ast_copy_string().

249 {
250  char *ret = NULL;
251 
252  *buf = '\0';
253 
254  if (data)
255  ret = getenv(data);
256 
257  if (ret)
258  ast_copy_string(buf, ret, len);
259 
260  return 0;
261 }
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:223
static int env_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
)
static

Definition at line 263 of file func_env.c.

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

265 {
266  if (!ast_strlen_zero(data) && strncmp(data, "AST_", 4)) {
267  if (!ast_strlen_zero(value)) {
268  setenv(data, value, 1);
269  } else {
270  unsetenv(data);
271  }
272  }
273 
274  return 0;
275 }
int value
Definition: syslog.c:39
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int setenv(const char *name, const char *value, int overwrite)
int unsetenv(const char *name)
static enum file_format file2format ( const char *  filename)
static

Definition at line 441 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().

442 {
443  FILE *ff;
444  char fbuf[4096];
445  char *first_cr, *first_nl;
446  enum file_format newline_format = FF_UNKNOWN;
447 
448  if (!(ff = fopen(filename, "r"))) {
449  ast_log(LOG_ERROR, "Cannot open '%s': %s\n", filename, strerror(errno));
450  return -1;
451  }
452 
453  while (fgets(fbuf, sizeof(fbuf), ff)) {
454  first_cr = strchr(fbuf, '\r');
455  first_nl = strchr(fbuf, '\n');
456 
457  if (!first_cr && !first_nl) {
458  continue;
459  }
460 
461  if ((first_cr && !first_nl) || (first_cr && first_cr < first_nl)) {
462 
463  if (first_nl && first_nl == first_cr + 1) {
464  newline_format = FF_DOS;
465  } else if (first_cr && first_cr == &fbuf[sizeof(fbuf) - 2]) {
466  /* Edge case: get it on the next pass */
467  fseek(ff, -1, SEEK_CUR);
468  continue;
469  } else {
470  newline_format = FF_MAC;
471  }
472  } else {
473  newline_format = FF_UNIX;
474  }
475  break;
476  }
477  fclose(ff);
478  return newline_format;
479 }
#define LOG_ERROR
Definition: logger.h:155
file_format
Definition: func_env.c:320
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
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 402 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.

403 {
404  enum file_format newline_format = FF_UNKNOWN;
405  int64_t count;
407  AST_APP_ARG(filename);
409  );
410 
412  if (args.argc > 1) {
413  if (tolower(args.format[0]) == 'd') {
414  newline_format = FF_DOS;
415  } else if (tolower(args.format[0]) == 'm') {
416  newline_format = FF_MAC;
417  } else if (tolower(args.format[0]) == 'u') {
418  newline_format = FF_UNIX;
419  }
420  }
421 
422  count = count_lines(args.filename, newline_format);
423  ast_str_set(buf, len, "%" PRId64, count);
424  return 0;
425 }
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
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:874
static int64_t count_lines(const char *filename, enum file_format newline_format)
Definition: func_env.c:327
file_format
Definition: func_env.c:320
static struct @350 args
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static snd_pcm_format_t format
Definition: chan_alsa.c:93
static int file_format ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
)
static

Definition at line 481 of file func_env.c.

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

482 {
483  enum file_format newline_format = file2format(data);
484  ast_str_set(buf, len, "%c", newline_format == FF_UNIX ? 'u' : newline_format == FF_DOS ? 'd' : newline_format == FF_MAC ? 'm' : 'x');
485  return 0;
486 }
static enum file_format file2format(const char *filename)
Definition: func_env.c:441
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:874
file_format
Definition: func_env.c:320
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int file_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
)
static

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

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

747 {
749  AST_APP_ARG(filename);
750  AST_APP_ARG(offset);
751  AST_APP_ARG(length);
752  AST_APP_ARG(options);
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 - 1; 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 LOG_WARNING
Definition: logger.h:144
const char * format2term(enum file_format f)
Definition: func_env.c:740
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
int value
Definition: syslog.c:39
static enum file_format file2format(const char *filename)
Definition: func_env.c:441
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define AST_LOG_ERROR
Definition: logger.h:160
#define LOG_ERROR
Definition: logger.h:155
file_format
Definition: func_env.c:320
static struct @350 args
#define LINE_COUNTER(cptr, term, counter)
Definition: func_env.c:427
#define LLONG_MAX
Definition: compat.h:77
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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:77
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static snd_pcm_format_t format
Definition: chan_alsa.c:93
const char * format2term ( enum file_format  f)

Definition at line 740 of file func_env.c.

Referenced by file_write().

741 {
742  const char *term[] = { "", "\n", "\r\n", "\r" };
743  return term[f + 1];
744 }
static struct ast_format f[]
Definition: format_g726.c:181
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:1173
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:1164
static int stat_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 277 of file func_env.c.

References ast_copy_string(), and strsep().

279 {
280  char *action;
281  struct stat s;
282 
283  ast_copy_string(buf, "0", len);
284 
285  action = strsep(&data, ",");
286  if (stat(data, &s)) {
287  return 0;
288  } else {
289  switch (*action) {
290  case 'e':
291  strcpy(buf, "1");
292  break;
293  case 's':
294  snprintf(buf, len, "%u", (unsigned int) s.st_size);
295  break;
296  case 'f':
297  snprintf(buf, len, "%d", S_ISREG(s.st_mode) ? 1 : 0);
298  break;
299  case 'd':
300  snprintf(buf, len, "%d", S_ISDIR(s.st_mode) ? 1 : 0);
301  break;
302  case 'M':
303  snprintf(buf, len, "%d", (int) s.st_mtime);
304  break;
305  case 'A':
306  snprintf(buf, len, "%d", (int) s.st_mtime);
307  break;
308  case 'C':
309  snprintf(buf, len, "%d", (int) s.st_ctime);
310  break;
311  case 'm':
312  snprintf(buf, len, "%o", s.st_mode);
313  break;
314  }
315  }
316 
317  return 0;
318 }
char * strsep(char **str, const char *delims)
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:223
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.
Definition: pbx.c:3814
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

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 1289 of file func_env.c.

Definition at line 1289 of file func_env.c.

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:247
static int env_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: func_env.c:263

Definition at line 1233 of file func_env.c.

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:402

Definition at line 1251 of file func_env.c.

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:320

Definition at line 1257 of file func_env.c.

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:488
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.

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:277

Definition at line 1239 of file func_env.c.