Asterisk - The Open Source Telephony Project GIT-master-545c459
Loading...
Searching...
No Matches
Macros | Enumerations | Functions | Variables
func_env.c File Reference

Environment related dialplan functions. More...

#include "asterisk.h"
#include <sys/stat.h>
#include <libgen.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_basename (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int file_count_line (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
 
static int file_dirname (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_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 = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .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_basename_function
 
static struct ast_custom_function file_count_line_function
 
static struct ast_custom_function file_dirname_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 550 of file func_env.c.

551 { \
552 counter++; \
553 } else if (*cptr == '\r' && term == FF_DOS && dos_state == 0) { \
554 dos_state = 1; \
555 } else if (*cptr == '\n' && term == FF_DOS && dos_state == 1) { \
556 dos_state = 0; \
557 counter++; \
558 } else if (*cptr == '\r' && term == FF_MAC) { \
559 counter++; \
560 } else if (term == FF_DOS) { \
561 dos_state = 0; \
562 }
@ FF_DOS
Definition func_env.c:446
@ FF_MAC
Definition func_env.c:447

Enumeration Type Documentation

◆ file_format

Enumerator
FF_UNKNOWN 
FF_UNIX 
FF_DOS 
FF_MAC 

Definition at line 443 of file func_env.c.

443 {
444 FF_UNKNOWN = -1,
445 FF_UNIX,
446 FF_DOS,
447 FF_MAC,
448};
@ FF_UNKNOWN
Definition func_env.c:444
@ FF_UNIX
Definition func_env.c:445

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1464 of file func_env.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1464 of file func_env.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1464 of file func_env.c.

◆ count_lines()

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

Definition at line 450 of file func_env.c.

451{
452 int count = 0;
453 char fbuf[4096];
454 FILE *ff;
455
456 if (!(ff = fopen(filename, "r"))) {
457 ast_log(LOG_ERROR, "Unable to open '%s': %s\n", filename, strerror(errno));
458 return -1;
459 }
460
461 while (fgets(fbuf, sizeof(fbuf), ff)) {
462 char *next = fbuf, *first_cr = NULL, *first_nl = NULL;
463
464 /* Must do it this way, because if the fileformat is FF_MAC, then Unix
465 * assumptions about line-format will not come into play. */
466 while (next) {
467 if (newline_format == FF_DOS || newline_format == FF_MAC || newline_format == FF_UNKNOWN) {
468 first_cr = strchr(next, '\r');
469 }
470 if (newline_format == FF_UNIX || newline_format == FF_UNKNOWN) {
471 first_nl = strchr(next, '\n');
472 }
473
474 /* No terminators found in buffer */
475 if (!first_cr && !first_nl) {
476 break;
477 }
478
479 if (newline_format == FF_UNKNOWN) {
480 if ((first_cr && !first_nl) || (first_cr && first_cr < first_nl)) {
481 if (first_nl && first_nl == first_cr + 1) {
482 newline_format = FF_DOS;
483 } else if (first_cr && first_cr == &fbuf[sizeof(fbuf) - 2]) {
484 /* Get it on the next pass */
485 fseek(ff, -1, SEEK_CUR);
486 break;
487 } else {
488 newline_format = FF_MAC;
489 first_nl = NULL;
490 }
491 } else {
492 newline_format = FF_UNIX;
493 first_cr = NULL;
494 }
495 /* Jump down into next section */
496 }
497
498 if (newline_format == FF_DOS) {
499 if (first_nl && first_cr && first_nl == first_cr + 1) {
500 next = first_nl + 1;
501 count++;
502 } else if (first_cr == &fbuf[sizeof(fbuf) - 2]) {
503 /* Get it on the next pass */
504 fseek(ff, -1, SEEK_CUR);
505 break;
506 }
507 } else if (newline_format == FF_MAC) {
508 if (first_cr) {
509 next = first_cr + 1;
510 count++;
511 }
512 } else if (newline_format == FF_UNIX) {
513 if (first_nl) {
514 next = first_nl + 1;
515 count++;
516 }
517 }
518 }
519 }
520 fclose(ff);
521
522 return count;
523}
#define ast_log
Definition astobj2.c:42
#define LOG_ERROR
int errno
#define NULL
Definition resample.c:96

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

Referenced by file_count_line().

◆ env_read()

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

Definition at line 370 of file func_env.c.

372{
373 char *ret = NULL;
374
375 *buf = '\0';
376
377 if (data)
378 ret = getenv(data);
379
380 if (ret)
381 ast_copy_string(buf, ret, len);
382
383 return 0;
384}
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)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425

References ast_copy_string(), buf, len(), and NULL.

◆ env_write()

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

Definition at line 386 of file func_env.c.

388{
389 if (!ast_strlen_zero(data) && strncmp(data, "AST_", 4)) {
390 if (!ast_strlen_zero(value)) {
391 setenv(data, value, 1);
392 } else {
393 unsetenv(data);
394 }
395 }
396
397 return 0;
398}
int unsetenv(const char *name)
int setenv(const char *name, const char *value, int overwrite)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
int value
Definition syslog.c:37

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

◆ file2format()

static enum file_format file2format ( const char *  filename)
static

Definition at line 564 of file func_env.c.

565{
566 FILE *ff;
567 char fbuf[4096];
568 char *first_cr, *first_nl;
569 enum file_format newline_format = FF_UNKNOWN;
570
571 if (!(ff = fopen(filename, "r"))) {
572 ast_log(LOG_ERROR, "Cannot open '%s': %s\n", filename, strerror(errno));
573 return -1;
574 }
575
576 while (fgets(fbuf, sizeof(fbuf), ff)) {
577 first_cr = strchr(fbuf, '\r');
578 first_nl = strchr(fbuf, '\n');
579
580 if (!first_cr && !first_nl) {
581 continue;
582 }
583
584 if ((first_cr && !first_nl) || (first_cr && first_cr < first_nl)) {
585
586 if (first_nl && first_nl == first_cr + 1) {
587 newline_format = FF_DOS;
588 } else if (first_cr && first_cr == &fbuf[sizeof(fbuf) - 2]) {
589 /* Edge case: get it on the next pass */
590 fseek(ff, -1, SEEK_CUR);
591 continue;
592 } else {
593 newline_format = FF_MAC;
594 }
595 } else {
596 newline_format = FF_UNIX;
597 }
598 break;
599 }
600 fclose(ff);
601 return newline_format;
602}
file_format
Definition func_env.c:443

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

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

◆ file_basename()

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

Definition at line 628 of file func_env.c.

629{
630 char *ret = NULL;
631
632 *buf = '\0';
633
634 if (data) {
635 ret = basename(data);
636 }
637
638 if (ret) {
639 ast_copy_string(buf, ret, len);
640 }
641
642 return 0;
643}

References ast_copy_string(), buf, len(), and NULL.

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

526{
527 enum file_format newline_format = FF_UNKNOWN;
528 int64_t count;
530 AST_APP_ARG(filename);
531 AST_APP_ARG(format);
532 );
533
535 if (args.argc > 1) {
536 if (tolower(args.format[0]) == 'd') {
537 newline_format = FF_DOS;
538 } else if (tolower(args.format[0]) == 'm') {
539 newline_format = FF_MAC;
540 } else if (tolower(args.format[0]) == 'u') {
541 newline_format = FF_UNIX;
542 }
543 }
544
545 count = count_lines(args.filename, newline_format);
546 ast_str_set(buf, len, "%" PRId64, count);
547 return 0;
548}
static int64_t count_lines(const char *filename, enum file_format newline_format)
Definition func_env.c:450
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
static struct @523 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:1113

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

◆ file_dirname()

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

Definition at line 611 of file func_env.c.

612{
613 char *ret = NULL;
614
615 *buf = '\0';
616
617 if (data) {
618 ret = dirname(data);
619 }
620
621 if (ret) {
622 ast_copy_string(buf, ret, len);
623 }
624
625 return 0;
626}

References ast_copy_string(), buf, len(), and NULL.

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

605{
606 enum file_format newline_format = file2format(data);
607 ast_str_set(buf, len, "%c", newline_format == FF_UNIX ? 'u' : newline_format == FF_DOS ? 'd' : newline_format == FF_MAC ? 'm' : 'x');
608 return 0;
609}
static enum file_format file2format(const char *filename)
Definition func_env.c:564

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

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

646{
647 FILE *ff;
648 int64_t offset = 0, length = LLONG_MAX;
649 enum file_format format = FF_UNKNOWN;
650 char fbuf[4096];
651 int64_t flength, i; /* iterator needs to be signed, so it can go negative and terminate the loop */
652 int64_t offset_offset = -1, length_offset = -1;
653 char dos_state = 0;
655 AST_APP_ARG(filename);
656 AST_APP_ARG(offset);
657 AST_APP_ARG(length);
659 AST_APP_ARG(fileformat);
660 );
661
663
664 if (args.argc > 1) {
665 sscanf(args.offset, "%" SCNd64, &offset);
666 }
667 if (args.argc > 2) {
668 sscanf(args.length, "%" SCNd64, &length);
669 }
670
671 if (args.argc < 4 || !strchr(args.options, 'l')) {
672 /* Character-based mode */
673 off_t off_i;
674
675 if (!(ff = fopen(args.filename, "r"))) {
676 ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", args.filename, strerror(errno));
677 return 0;
678 }
679
680 if (fseeko(ff, 0, SEEK_END) < 0) {
681 ast_log(LOG_ERROR, "Cannot seek to end of '%s': %s\n", args.filename, strerror(errno));
682 fclose(ff);
683 return -1;
684 }
685 flength = ftello(ff);
686
687 if (offset < 0) {
688 fseeko(ff, offset, SEEK_END);
689 if ((offset = ftello(ff)) < 0) {
690 ast_log(AST_LOG_ERROR, "Cannot determine offset position of '%s': %s\n", args.filename, strerror(errno));
691 fclose(ff);
692 return -1;
693 }
694 }
695 if (length < 0) {
696 fseeko(ff, length, SEEK_END);
697 if ((length = ftello(ff)) - offset < 0) {
698 /* Eliminates all results */
699 fclose(ff);
700 return -1;
701 }
702 } else if (length == LLONG_MAX) {
703 fseeko(ff, 0, SEEK_END);
704 length = ftello(ff);
705 }
706
708
709 fseeko(ff, offset, SEEK_SET);
710 for (off_i = ftello(ff); off_i < flength && off_i < offset + length; off_i += sizeof(fbuf)) {
711 /* Calculate if we need to retrieve just a portion of the file in memory */
712 size_t toappend = sizeof(fbuf);
713
714 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
715 ast_log(LOG_ERROR, "Short read?!!\n");
716 break;
717 }
718
719 /* Don't go past the length requested */
720 if (off_i + toappend > offset + length) {
721 toappend = MIN(offset + length - off_i, flength - off_i);
722 }
723
724 ast_str_append_substr(buf, len, fbuf, toappend);
725 }
726 fclose(ff);
727 return 0;
728 }
729
730 /* Line-based read */
731 if (args.argc == 5) {
732 if (tolower(args.fileformat[0]) == 'd') {
733 format = FF_DOS;
734 } else if (tolower(args.fileformat[0]) == 'm') {
735 format = FF_MAC;
736 } else if (tolower(args.fileformat[0]) == 'u') {
737 format = FF_UNIX;
738 }
739 }
740
741 if (format == FF_UNKNOWN) {
742 if ((format = file2format(args.filename)) == FF_UNKNOWN) {
743 ast_log(LOG_WARNING, "'%s' is not a line-based file\n", args.filename);
744 return -1;
745 }
746 }
747
748 if (offset < 0 && length <= offset) {
749 /* Length eliminates all content */
750 return -1;
751 } else if (offset == 0) {
752 offset_offset = 0;
753 }
754
755 if (!(ff = fopen(args.filename, "r"))) {
756 ast_log(LOG_ERROR, "Cannot open '%s': %s\n", args.filename, strerror(errno));
757 return -1;
758 }
759
760 if (fseek(ff, 0, SEEK_END)) {
761 ast_log(LOG_ERROR, "Cannot seek to end of file '%s': %s\n", args.filename, strerror(errno));
762 fclose(ff);
763 return -1;
764 }
765
766 flength = ftello(ff);
767
768 if (length == LLONG_MAX) {
769 length_offset = flength;
770 }
771
772 /* For negative offset and/or negative length */
773 if (offset < 0 || length < 0) {
774 int64_t count = 0;
775 /* Start with an even multiple of fbuf, so at the end of reading with a
776 * 0 offset, we don't try to go past the beginning of the file. */
777 for (i = (flength / sizeof(fbuf)) * sizeof(fbuf); i >= 0; i -= sizeof(fbuf)) {
778 size_t end;
779 char *pos;
780 if (fseeko(ff, i, SEEK_SET)) {
781 ast_log(LOG_ERROR, "Cannot seek to offset %" PRId64 ": %s\n", i, strerror(errno));
782 }
783 end = fread(fbuf, 1, sizeof(fbuf), ff);
784 for (pos = (end < sizeof(fbuf) ? fbuf + end - 1 : fbuf + sizeof(fbuf) - 1); pos >= fbuf; pos--) {
785 LINE_COUNTER(pos, format, count);
786
787 if (length < 0 && count * -1 == length) {
788 length_offset = i + (pos - fbuf);
789 } else if (offset < 0 && count * -1 == (offset - 1)) {
790 /* Found our initial offset. We're done with reverse motion! */
791 if (format == FF_DOS) {
792 offset_offset = i + (pos - fbuf) + 2;
793 } else {
794 offset_offset = i + (pos - fbuf) + 1;
795 }
796 break;
797 }
798 }
799 if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
800 break;
801 }
802 }
803 /* We're at the beginning, and the negative offset indicates the exact number of lines in the file */
804 if (offset < 0 && offset_offset < 0 && offset == count * -1) {
805 offset_offset = 0;
806 }
807 }
808
809 /* Positve line offset */
810 if (offset > 0) {
811 int64_t count = 0;
812 fseek(ff, 0, SEEK_SET);
813 for (i = 0; i < flength; i += sizeof(fbuf)) {
814 char *pos;
815 if (i + sizeof(fbuf) <= flength) {
816 /* Don't let previous values influence current counts, due to short reads */
817 memset(fbuf, 0, sizeof(fbuf));
818 }
819 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
820 ast_log(LOG_ERROR, "Short read?!!\n");
821 fclose(ff);
822 return -1;
823 }
824 for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
825 LINE_COUNTER(pos, format, count);
826
827 if (count == offset) {
828 offset_offset = i + (pos - fbuf) + 1;
829 break;
830 }
831 }
832 if (offset_offset >= 0) {
833 break;
834 }
835 }
836 }
837
838 if (offset_offset < 0) {
839 ast_log(LOG_ERROR, "Offset '%s' refers to before the beginning of the file!\n", args.offset);
840 fclose(ff);
841 return -1;
842 }
843
845 if (fseeko(ff, offset_offset, SEEK_SET)) {
846 ast_log(LOG_ERROR, "fseeko failed: %s\n", strerror(errno));
847 }
848
849 /* If we have both offset_offset and length_offset, then grabbing the
850 * buffer is simply a matter of just retrieving the file and adding it
851 * to buf. Otherwise, we need to run byte-by-byte forward until the
852 * length is complete. */
853 if (length_offset >= 0) {
854 ast_debug(3, "offset=%" PRId64 ", length=%" PRId64 ", offset_offset=%" PRId64 ", length_offset=%" PRId64 "\n", offset, length, offset_offset, length_offset);
855 for (i = offset_offset; i < length_offset; i += sizeof(fbuf)) {
856 if (fread(fbuf, 1, i + sizeof(fbuf) > flength ? flength - i : sizeof(fbuf), ff) < (i + sizeof(fbuf) > flength ? flength - i : sizeof(fbuf))) {
857 ast_log(LOG_ERROR, "Short read?!!\n");
858 }
859 ast_debug(3, "Appending first %" PRId64" bytes of fbuf=%s\n", (int64_t)(i + sizeof(fbuf) > length_offset ? length_offset - i : sizeof(fbuf)), fbuf);
860 ast_str_append_substr(buf, len, fbuf, i + sizeof(fbuf) > length_offset ? length_offset - i : sizeof(fbuf));
861 }
862 } else if (length == 0) {
863 /* Nothing to do */
864 } else {
865 /* Positive line offset */
866 int64_t current_length = 0;
867 char dos_state = 0;
868 ast_debug(3, "offset=%" PRId64 ", length=%" PRId64 ", offset_offset=%" PRId64 ", length_offset=%" PRId64 "\n", offset, length, offset_offset, length_offset);
869 for (i = offset_offset; i < flength; i += sizeof(fbuf)) {
870 char *pos;
871 size_t bytes_read;
872 if ((bytes_read = fread(fbuf, 1, sizeof(fbuf), ff)) < sizeof(fbuf) && !feof(ff)) {
873 ast_log(LOG_ERROR, "Short read?!!\n");
874 fclose(ff);
875 return -1;
876 }
877 for (pos = fbuf; pos < fbuf + bytes_read; pos++) {
878 LINE_COUNTER(pos, format, current_length);
879
880 if (current_length == length) {
881 length_offset = i + (pos - fbuf) + 1;
882 break;
883 }
884 }
885 ast_debug(3, "length_offset=%" PRId64 ", length_offset - i=%" PRId64 "\n", length_offset, length_offset - i);
886 ast_str_append_substr(buf, len, fbuf, (length_offset >= 0) ? length_offset - i : (flength > i + sizeof(fbuf)) ? sizeof(fbuf) : flength - i);
887
888 if (length_offset >= 0) {
889 break;
890 }
891 }
892 }
893
894 fclose(ff);
895 return 0;
896}
#define LLONG_MAX
char * end
Definition eagi_proxy.c:73
#define LINE_COUNTER(cptr, term, counter)
Definition func_env.c:550
#define AST_LOG_ERROR
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
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:1062
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:693
static struct test_options options
#define MIN(a, b)
Definition utils.h:252

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(), buf, end, errno, FF_DOS, FF_MAC, FF_UNIX, FF_UNKNOWN, file2format(), len(), LINE_COUNTER, LLONG_MAX, LOG_ERROR, LOG_WARNING, MIN, and options.

◆ file_write()

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

Definition at line 905 of file func_env.c.

906{
908 AST_APP_ARG(filename);
909 AST_APP_ARG(offset);
910 AST_APP_ARG(length);
912 AST_APP_ARG(format);
913 );
914 int64_t offset = 0, length = LLONG_MAX;
915 off_t flength, vlength;
916 size_t foplen = 0;
917 FILE *ff;
918
920
921 if (args.argc > 1) {
922 sscanf(args.offset, "%" SCNd64, &offset);
923 }
924 if (args.argc > 2) {
925 sscanf(args.length, "%" SCNd64, &length);
926 }
927
928 vlength = strlen(value);
929
930 if (args.argc < 4 || !strchr(args.options, 'l')) {
931 /* Character-based mode */
932
933 if (args.argc > 3 && strchr(args.options, 'a')) {
934 /* Append mode */
935 if (!(ff = fopen(args.filename, "a"))) {
936 ast_log(LOG_WARNING, "Cannot open file '%s' for appending: %s\n", args.filename, strerror(errno));
937 return 0;
938 }
939 if (fwrite(value, 1, vlength, ff) < vlength) {
940 ast_log(LOG_ERROR, "Short write?!!\n");
941 }
942 fclose(ff);
943 return 0;
944 } else if (offset == 0 && length == LLONG_MAX) {
945 if (!(ff = fopen(args.filename, "w"))) {
946 ast_log(LOG_WARNING, "Cannot open file '%s' for writing: %s\n", args.filename, strerror(errno));
947 return 0;
948 }
949 if (fwrite(value, 1, vlength, ff) < vlength) {
950 ast_log(LOG_ERROR, "Short write?!!\n");
951 }
952 fclose(ff);
953 return 0;
954 }
955
956 if (!(ff = fopen(args.filename, "r+"))) {
957 ast_log(LOG_WARNING, "Cannot open file '%s' for modification: %s\n", args.filename, strerror(errno));
958 return 0;
959 }
960 fseeko(ff, 0, SEEK_END);
961 flength = ftello(ff);
962
963 if (offset < 0) {
964 if (fseeko(ff, offset, SEEK_END)) {
965 ast_log(LOG_ERROR, "Cannot seek to offset of '%s': %s\n", args.filename, strerror(errno));
966 fclose(ff);
967 return -1;
968 }
969 if ((offset = ftello(ff)) < 0) {
970 ast_log(AST_LOG_ERROR, "Cannot determine offset position of '%s': %s\n", args.filename, strerror(errno));
971 fclose(ff);
972 return -1;
973 }
974 }
975
976 if (length < 0) {
977 length = flength - offset + length;
978 if (length < 0) {
979 ast_log(LOG_ERROR, "Length '%s' exceeds the file length. No data will be written.\n", args.length);
980 fclose(ff);
981 return -1;
982 }
983 }
984
985 fseeko(ff, offset, SEEK_SET);
986
987 ast_debug(3, "offset=%s/%" PRId64 ", length=%s/%" PRId64 ", vlength=%" PRId64 ", flength=%" PRId64 "\n",
988 S_OR(args.offset, "(null)"), offset, S_OR(args.length, "(null)"), length, vlength, flength);
989
990 if (length == vlength) {
991 /* Simplest case, a straight replace */
992 if (fwrite(value, 1, vlength, ff) < vlength) {
993 ast_log(LOG_ERROR, "Short write?!!\n");
994 }
995 fclose(ff);
996 } else if (length == LLONG_MAX) {
997 /* Simple truncation */
998 if (fwrite(value, 1, vlength, ff) < vlength) {
999 ast_log(LOG_ERROR, "Short write?!!\n");
1000 }
1001 fclose(ff);
1002 if (truncate(args.filename, offset + vlength)) {
1003 ast_log(LOG_ERROR, "Unable to truncate the file: %s\n", strerror(errno));
1004 }
1005 } else if (length > vlength) {
1006 /* More complex -- need to close a gap */
1007 char fbuf[4096];
1008 off_t cur;
1009 if (fwrite(value, 1, vlength, ff) < vlength) {
1010 ast_log(LOG_ERROR, "Short write?!!\n");
1011 }
1012 fseeko(ff, length - vlength, SEEK_CUR);
1013 while ((cur = ftello(ff)) < flength) {
1014 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1015 ast_log(LOG_ERROR, "Short read?!!\n");
1016 }
1017 fseeko(ff, cur + vlength - length, SEEK_SET);
1018 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1019 ast_log(LOG_ERROR, "Short write?!!\n");
1020 }
1021 /* Seek to where we stopped reading */
1022 if (fseeko(ff, cur + sizeof(fbuf), SEEK_SET) < 0) {
1023 /* Only reason for seek to fail is EOF */
1024 break;
1025 }
1026 }
1027 fclose(ff);
1028 if (truncate(args.filename, flength - (length - vlength))) {
1029 ast_log(LOG_ERROR, "Unable to truncate the file: %s\n", strerror(errno));
1030 }
1031 } else {
1032 /* Most complex -- need to open a gap */
1033 char fbuf[4096];
1034 off_t lastwritten = flength + vlength - length;
1035
1036 /* Start reading exactly the buffer size back from the end. */
1037 fseeko(ff, flength - sizeof(fbuf), SEEK_SET);
1038 while (offset < ftello(ff)) {
1039 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1040 ast_log(LOG_ERROR, "Short read?!!\n");
1041 fclose(ff);
1042 return -1;
1043 }
1044 /* Since the read moved our file ptr forward, we reverse, but
1045 * seek an offset equal to the amount we want to extend the
1046 * file by */
1047 fseeko(ff, vlength - length - sizeof(fbuf), SEEK_CUR);
1048
1049 /* Note the location of this buffer -- we must not overwrite this position. */
1050 lastwritten = ftello(ff);
1051
1052 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1053 ast_log(LOG_ERROR, "Short write?!!\n");
1054 fclose(ff);
1055 return -1;
1056 }
1057
1058 if (lastwritten < offset + sizeof(fbuf)) {
1059 break;
1060 }
1061 /* Our file pointer is now either pointing to the end of the
1062 * file (new position) or a multiple of the fbuf size back from
1063 * that point. Move back to where we want to start reading
1064 * again. We never actually try to read beyond the end of the
1065 * file, so we don't have do deal with short reads, as we would
1066 * when we're shortening the file. */
1067 fseeko(ff, 2 * sizeof(fbuf) + vlength - length, SEEK_CUR);
1068 }
1069
1070 /* Last part of the file that we need to preserve */
1071 if (fseeko(ff, offset + length, SEEK_SET)) {
1072 ast_log(LOG_WARNING, "Unable to seek to %" PRId64 " + %" PRId64 " != %" PRId64 "?)\n", offset, length, ftello(ff));
1073 }
1074
1075 /* Doesn't matter how much we read -- just need to restrict the write */
1076 ast_debug(1, "Reading at %" PRId64 "\n", ftello(ff));
1077 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1078 ast_log(LOG_ERROR, "Short read?!!\n");
1079 }
1080 fseek(ff, offset, SEEK_SET);
1081 /* Write out the value, then write just up until where we last moved some data */
1082 if (fwrite(value, 1, vlength, ff) < vlength) {
1083 ast_log(LOG_ERROR, "Short write?!!\n");
1084 } else {
1085 off_t curpos = ftello(ff);
1086 foplen = lastwritten - curpos;
1087 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1088 ast_log(LOG_ERROR, "Short write?!!\n");
1089 }
1090 }
1091 fclose(ff);
1092 }
1093 } else {
1094 enum file_format newline_format = FF_UNKNOWN;
1095
1096 /* Line mode */
1097 if (args.argc == 5) {
1098 if (tolower(args.format[0]) == 'u') {
1099 newline_format = FF_UNIX;
1100 } else if (tolower(args.format[0]) == 'm') {
1101 newline_format = FF_MAC;
1102 } else if (tolower(args.format[0]) == 'd') {
1103 newline_format = FF_DOS;
1104 }
1105 }
1106 if (newline_format == FF_UNKNOWN && (newline_format = file2format(args.filename)) == FF_UNKNOWN) {
1107 ast_log(LOG_ERROR, "File '%s' not in line format\n", args.filename);
1108 return -1;
1109 }
1110
1111 if (strchr(args.options, 'a')) {
1112 /* Append to file */
1113 if (!(ff = fopen(args.filename, "a"))) {
1114 ast_log(LOG_ERROR, "Unable to open '%s' for appending: %s\n", args.filename, strerror(errno));
1115 return -1;
1116 }
1117 if (fwrite(value, 1, vlength, ff) < vlength) {
1118 ast_log(LOG_ERROR, "Short write?!!\n");
1119 } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, strlen(format2term(newline_format)), ff) < strlen(format2term(newline_format))) {
1120 ast_log(LOG_ERROR, "Short write?!!\n");
1121 }
1122 fclose(ff);
1123 } else if (offset == 0 && length == LLONG_MAX) {
1124 /* Overwrite file */
1125 off_t truncsize;
1126 if (!(ff = fopen(args.filename, "w"))) {
1127 ast_log(LOG_ERROR, "Unable to open '%s' for writing: %s\n", args.filename, strerror(errno));
1128 return -1;
1129 }
1130 if (fwrite(value, 1, vlength, ff) < vlength) {
1131 ast_log(LOG_ERROR, "Short write?!!\n");
1132 } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, strlen(format2term(newline_format)), ff) < strlen(format2term(newline_format))) {
1133 ast_log(LOG_ERROR, "Short write?!!\n");
1134 }
1135 if ((truncsize = ftello(ff)) < 0) {
1136 ast_log(AST_LOG_ERROR, "Unable to determine truncate position of '%s': %s\n", args.filename, strerror(errno));
1137 }
1138 fclose(ff);
1139 if (truncsize >= 0 && truncate(args.filename, truncsize)) {
1140 ast_log(LOG_ERROR, "Unable to truncate file '%s': %s\n", args.filename, strerror(errno));
1141 return -1;
1142 }
1143 } else {
1144 int64_t offset_offset = (offset == 0 ? 0 : -1), length_offset = -1, flength, i, current_length = 0;
1145 char dos_state = 0, fbuf[4096];
1146
1147 if (offset < 0 && length < offset) {
1148 /* Nonsense! */
1149 ast_log(LOG_ERROR, "Length cannot specify a position prior to the offset\n");
1150 return -1;
1151 }
1152
1153 if (!(ff = fopen(args.filename, "r+"))) {
1154 ast_log(LOG_ERROR, "Cannot open '%s' for modification: %s\n", args.filename, strerror(errno));
1155 return -1;
1156 }
1157
1158 if (fseek(ff, 0, SEEK_END)) {
1159 ast_log(LOG_ERROR, "Cannot seek to end of file '%s': %s\n", args.filename, strerror(errno));
1160 fclose(ff);
1161 return -1;
1162 }
1163 if ((flength = ftello(ff)) < 0) {
1164 ast_log(AST_LOG_ERROR, "Cannot determine end position of file '%s': %s\n", args.filename, strerror(errno));
1165 fclose(ff);
1166 return -1;
1167 }
1168
1169 /* For negative offset and/or negative length */
1170 if (offset < 0 || length < 0) {
1171 int64_t count = 0;
1172 for (i = (flength / sizeof(fbuf)) * sizeof(fbuf); i >= 0; i -= sizeof(fbuf)) {
1173 char *pos;
1174 if (fseeko(ff, i, SEEK_SET)) {
1175 ast_log(LOG_ERROR, "Cannot seek to offset %" PRId64 ": %s\n", i, strerror(errno));
1176 }
1177 if (i + sizeof(fbuf) >= flength) {
1178 memset(fbuf, 0, sizeof(fbuf));
1179 }
1180 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1181 ast_log(LOG_ERROR, "Short read: %s\n", strerror(errno));
1182 fclose(ff);
1183 return -1;
1184 }
1185 for (pos = fbuf + sizeof(fbuf) - 1; pos >= fbuf; pos--) {
1186 LINE_COUNTER(pos, newline_format, count);
1187
1188 if (length < 0 && count * -1 == length) {
1189 length_offset = i + (pos - fbuf);
1190 } else if (offset < 0 && count * -1 == (offset - 1)) {
1191 /* Found our initial offset. We're done with reverse motion! */
1192 if (newline_format == FF_DOS) {
1193 offset_offset = i + (pos - fbuf) + 2;
1194 } else {
1195 offset_offset = i + (pos - fbuf) + 1;
1196 }
1197 break;
1198 }
1199 }
1200 if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
1201 break;
1202 }
1203 }
1204 /* We're at the beginning, and the negative offset indicates the exact number of lines in the file */
1205 if (offset < 0 && offset_offset < 0 && offset == count * -1) {
1206 offset_offset = 0;
1207 }
1208 }
1209
1210 /* Positve line offset */
1211 if (offset > 0) {
1212 int64_t count = 0;
1213 fseek(ff, 0, SEEK_SET);
1214 for (i = 0; i < flength; i += sizeof(fbuf)) {
1215 char *pos;
1216 if (i + sizeof(fbuf) >= flength) {
1217 memset(fbuf, 0, sizeof(fbuf));
1218 }
1219 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1220 ast_log(LOG_ERROR, "Short read?!!\n");
1221 fclose(ff);
1222 return -1;
1223 }
1224 for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
1225 LINE_COUNTER(pos, newline_format, count);
1226
1227 if (count == offset) {
1228 offset_offset = i + (pos - fbuf) + 1;
1229 break;
1230 }
1231 }
1232 if (offset_offset >= 0) {
1233 break;
1234 }
1235 }
1236 }
1237
1238 if (offset_offset < 0) {
1239 ast_log(LOG_ERROR, "Offset '%s' refers to before the beginning of the file!\n", args.offset);
1240 fclose(ff);
1241 return -1;
1242 }
1243
1244 if (length == 0) {
1245 length_offset = offset_offset;
1246 } else if (length == LLONG_MAX) {
1247 length_offset = flength;
1248 }
1249
1250 /* Positive line length */
1251 if (length_offset < 0) {
1252 fseeko(ff, offset_offset, SEEK_SET);
1253 for (i = offset_offset; i < flength; i += sizeof(fbuf)) {
1254 char *pos;
1255 if (i + sizeof(fbuf) >= flength) {
1256 memset(fbuf, 0, sizeof(fbuf));
1257 }
1258 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1259 ast_log(LOG_ERROR, "Short read?!!\n");
1260 fclose(ff);
1261 return -1;
1262 }
1263 for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
1264 LINE_COUNTER(pos, newline_format, current_length);
1265
1266 if (current_length == length) {
1267 length_offset = i + (pos - fbuf) + 1;
1268 break;
1269 }
1270 }
1271 if (length_offset >= 0) {
1272 break;
1273 }
1274 }
1275 if (length_offset < 0) {
1276 /* Exceeds length of file */
1277 ast_debug(3, "Exceeds length of file? length=%" PRId64 ", count=%" PRId64 ", flength=%" PRId64 "\n", length, current_length, flength);
1278 length_offset = flength;
1279 }
1280 }
1281
1282 /* Have offset_offset and length_offset now */
1283 if (length_offset - offset_offset == vlength + (strchr(args.options, 'd') ? 0 : strlen(format2term(newline_format)))) {
1284 /* Simple case - replacement of text inline */
1285 fseeko(ff, offset_offset, SEEK_SET);
1286 if (fwrite(value, 1, vlength, ff) < vlength) {
1287 ast_log(LOG_ERROR, "Short write?!!\n");
1288 } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, strlen(format2term(newline_format)), ff) < strlen(format2term(newline_format))) {
1289 ast_log(LOG_ERROR, "Short write?!!\n");
1290 }
1291 fclose(ff);
1292 } else if (length_offset - offset_offset > vlength + (strchr(args.options, 'd') ? 0 : strlen(format2term(newline_format)))) {
1293 /* More complex case - need to shorten file */
1294 off_t cur;
1295 int64_t length_length = length_offset - offset_offset;
1296 size_t vlen = vlength + (strchr(args.options, 'd') ? 0 : strlen(format2term(newline_format)));
1297
1298 ast_debug(3, "offset=%s/%" PRId64 ", length=%s/%" PRId64 " (%" PRId64 "), vlength=%" PRId64 ", flength=%" PRId64 "\n",
1299 args.offset, offset_offset, args.length, length_offset, length_length, vlength, flength);
1300
1301 fseeko(ff, offset_offset, SEEK_SET);
1302 if (fwrite(value, 1, vlength, ff) < vlength) {
1303 ast_log(LOG_ERROR, "Short write?!!\n");
1304 fclose(ff);
1305 return -1;
1306 } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, vlen - vlength, ff) < vlen - vlength) {
1307 ast_log(LOG_ERROR, "Short write?!!\n");
1308 fclose(ff);
1309 return -1;
1310 }
1311 while ((cur = ftello(ff)) < flength) {
1312 if (cur < 0) {
1313 ast_log(AST_LOG_ERROR, "Unable to determine last write position for '%s': %s\n", args.filename, strerror(errno));
1314 fclose(ff);
1315 return -1;
1316 }
1317 fseeko(ff, length_length - vlen, SEEK_CUR);
1318 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1319 ast_log(LOG_ERROR, "Short read?!!\n");
1320 fclose(ff);
1321 return -1;
1322 }
1323 /* Seek to where we last stopped writing */
1324 fseeko(ff, cur, SEEK_SET);
1325 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1326 ast_log(LOG_ERROR, "Short write?!!\n");
1327 fclose(ff);
1328 return -1;
1329 }
1330 }
1331 fclose(ff);
1332 if (truncate(args.filename, flength - (length_length - vlen))) {
1333 ast_log(LOG_ERROR, "Truncation of file failed: %s\n", strerror(errno));
1334 }
1335 } else {
1336 /* Most complex case - need to lengthen file */
1337 size_t vlen = vlength + (strchr(args.options, 'd') ? 0 : strlen(format2term(newline_format)));
1338 int64_t origlen = length_offset - offset_offset;
1339 off_t lastwritten = flength + vlen - origlen;
1340
1341 ast_debug(3, "offset=%s/%" PRId64 ", length=%s/%" PRId64 ", vlength=%" PRId64 ", flength=%" PRId64 "\n",
1342 args.offset, offset_offset, args.length, length_offset, vlength, flength);
1343
1344 fseeko(ff, flength - sizeof(fbuf), SEEK_SET);
1345 while (offset_offset + sizeof(fbuf) < ftello(ff)) {
1346 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1347 ast_log(LOG_ERROR, "Short read?!!\n");
1348 fclose(ff);
1349 return -1;
1350 }
1351 fseeko(ff, sizeof(fbuf) - vlen - origlen, SEEK_CUR);
1352 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1353 ast_log(LOG_ERROR, "Short write?!!\n");
1354 fclose(ff);
1355 return -1;
1356 }
1357 if ((lastwritten = ftello(ff) - sizeof(fbuf)) < offset_offset + sizeof(fbuf)) {
1358 break;
1359 }
1360 fseeko(ff, 2 * sizeof(fbuf) + vlen - origlen, SEEK_CUR);
1361 }
1362 fseek(ff, length_offset, SEEK_SET);
1363 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1364 ast_log(LOG_ERROR, "Short read?!!\n");
1365 fclose(ff);
1366 return -1;
1367 }
1368 fseek(ff, offset_offset, SEEK_SET);
1369 if (fwrite(value, 1, vlength, ff) < vlength) {
1370 ast_log(LOG_ERROR, "Short write?!!\n");
1371 fclose(ff);
1372 return -1;
1373 } else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, strlen(format2term(newline_format)), ff) < strlen(format2term(newline_format))) {
1374 ast_log(LOG_ERROR, "Short write?!!\n");
1375 fclose(ff);
1376 return -1;
1377 } else {
1378 off_t curpos = ftello(ff);
1379 foplen = lastwritten - curpos;
1380 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1381 ast_log(LOG_ERROR, "Short write?!!\n");
1382 }
1383 }
1384 fclose(ff);
1385 }
1386 }
1387 }
1388
1389 return 0;
1390}
const char * format2term(enum file_format f)
Definition func_env.c:899
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80

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(), format2term(), LINE_COUNTER, LLONG_MAX, LOG_ERROR, LOG_WARNING, options, S_OR, and value.

◆ format2term()

const char * format2term ( enum file_format  f)

Definition at line 899 of file func_env.c.

900{
901 const char *term[] = { "", "\n", "\r\n", "\r" };
902 return term[f + 1];
903}

Referenced by file_write().

◆ load_module()

static int load_module ( void  )
static

Definition at line 1449 of file func_env.c.

1450{
1451 int res = 0;
1452
1460
1461 return res;
1462}
static struct ast_custom_function file_format_function
Definition func_env.c:1416
static struct ast_custom_function file_count_line_function
Definition func_env.c:1410
static struct ast_custom_function env_function
Definition func_env.c:1392
static struct ast_custom_function file_function
Definition func_env.c:1404
static struct ast_custom_function file_basename_function
Definition func_env.c:1428
static struct ast_custom_function stat_function
Definition func_env.c:1398
static struct ast_custom_function file_dirname_function
Definition func_env.c:1422
#define ast_custom_function_register_escalating(acf, escalation)
Register a custom function which requires escalated privileges.
Definition pbx.h:1572
#define ast_custom_function_register(acf)
Register a custom function.
Definition pbx.h:1563
@ AST_CFE_READ
Definition pbx.h:1555
@ AST_CFE_BOTH
Definition pbx.h:1557

References AST_CFE_BOTH, AST_CFE_READ, ast_custom_function_register, ast_custom_function_register_escalating, env_function, file_basename_function, file_count_line_function, file_dirname_function, file_format_function, file_function, and stat_function.

◆ stat_read()

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

Definition at line 400 of file func_env.c.

402{
403 char *action;
404 struct stat s;
405
406 ast_copy_string(buf, "0", len);
407
408 action = strsep(&data, ",");
409 if (stat(data, &s)) {
410 return 0;
411 } else {
412 switch (*action) {
413 case 'e':
414 strcpy(buf, "1");
415 break;
416 case 's':
417 snprintf(buf, len, "%u", (unsigned int) s.st_size);
418 break;
419 case 'f':
420 snprintf(buf, len, "%d", S_ISREG(s.st_mode) ? 1 : 0);
421 break;
422 case 'd':
423 snprintf(buf, len, "%d", S_ISDIR(s.st_mode) ? 1 : 0);
424 break;
425 case 'M':
426 snprintf(buf, len, "%d", (int) s.st_mtime);
427 break;
428 case 'A':
429 snprintf(buf, len, "%d", (int) s.st_mtime);
430 break;
431 case 'C':
432 snprintf(buf, len, "%d", (int) s.st_ctime);
433 break;
434 case 'm':
435 snprintf(buf, len, "%o", (unsigned int) s.st_mode);
436 break;
437 }
438 }
439
440 return 0;
441}
char * strsep(char **str, const char *delims)

References ast_copy_string(), buf, len(), and strsep().

◆ unload_module()

static int unload_module ( void  )
static

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Environment/filesystem dialplan functions" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 1464 of file func_env.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1464 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_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition func_env.c:386
static int env_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition func_env.c:370

Definition at line 1392 of file func_env.c.

1392 {
1393 .name = "ENV",
1394 .read = env_read,
1395 .write = env_write
1396};

Referenced by load_module(), and unload_module().

◆ file_basename_function

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

Definition at line 1428 of file func_env.c.

1428 {
1429 .name = "BASENAME",
1430 .read = file_basename,
1431 .read_max = 12,
1432};

Referenced by load_module(), and unload_module().

◆ 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:525

Definition at line 1410 of file func_env.c.

1410 {
1411 .name = "FILE_COUNT_LINE",
1412 .read2 = file_count_line,
1413 .read_max = 12,
1414};

Referenced by load_module(), and unload_module().

◆ file_dirname_function

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

Definition at line 1422 of file func_env.c.

1422 {
1423 .name = "DIRNAME",
1424 .read = file_dirname,
1425 .read_max = 12,
1426};

Referenced by load_module(), and unload_module().

◆ file_format_function

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

Definition at line 1416 of file func_env.c.

1416 {
1417 .name = "FILE_FORMAT",
1418 .read2 = file_format,
1419 .read_max = 2,
1420};

Referenced by load_module(), and unload_module().

◆ file_function

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

Definition at line 1404 of file func_env.c.

1404 {
1405 .name = "FILE",
1406 .read2 = file_read,
1407 .write = file_write,
1408};

Referenced by load_module(), and unload_module().

◆ 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:400

Definition at line 1398 of file func_env.c.

1398 {
1399 .name = "STAT",
1400 .read = stat_read,
1401 .read_max = 12,
1402};

Referenced by load_module(), and unload_module().