Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 = "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 = 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 547 of file func_env.c.

Enumeration Type Documentation

◆ file_format

Enumerator
FF_UNKNOWN 
FF_UNIX 
FF_DOS 
FF_MAC 

Definition at line 440 of file func_env.c.

440 {
441 FF_UNKNOWN = -1,
442 FF_UNIX,
443 FF_DOS,
444 FF_MAC,
445};
@ FF_UNKNOWN
Definition: func_env.c:441
@ FF_UNIX
Definition: func_env.c:442
@ FF_DOS
Definition: func_env.c:443
@ FF_MAC
Definition: func_env.c:444

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1461 of file func_env.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1461 of file func_env.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1461 of file func_env.c.

◆ count_lines()

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

Definition at line 447 of file func_env.c.

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

369{
370 char *ret = NULL;
371
372 *buf = '\0';
373
374 if (data)
375 ret = getenv(data);
376
377 if (ret)
378 ast_copy_string(buf, ret, len);
379
380 return 0;
381}
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 383 of file func_env.c.

385{
386 if (!ast_strlen_zero(data) && strncmp(data, "AST_", 4)) {
387 if (!ast_strlen_zero(value)) {
388 setenv(data, value, 1);
389 } else {
390 unsetenv(data);
391 }
392 }
393
394 return 0;
395}
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 561 of file func_env.c.

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

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

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

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

523{
524 enum file_format newline_format = FF_UNKNOWN;
525 int64_t count;
527 AST_APP_ARG(filename);
528 AST_APP_ARG(format);
529 );
530
532 if (args.argc > 1) {
533 if (tolower(args.format[0]) == 'd') {
534 newline_format = FF_DOS;
535 } else if (tolower(args.format[0]) == 'm') {
536 newline_format = FF_MAC;
537 } else if (tolower(args.format[0]) == 'u') {
538 newline_format = FF_UNIX;
539 }
540 }
541
542 count = count_lines(args.filename, newline_format);
543 ast_str_set(buf, len, "%" PRId64, count);
544 return 0;
545}
static int64_t count_lines(const char *filename, enum file_format newline_format)
Definition: func_env.c:447
#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.
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
const char * args

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

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

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

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

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

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

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

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

897{
898 const char *term[] = { "", "\n", "\r\n", "\r" };
899 return term[f + 1];
900}

Referenced by file_write().

◆ load_module()

static int load_module ( void  )
static

Definition at line 1446 of file func_env.c.

1447{
1448 int res = 0;
1449
1457
1458 return res;
1459}
static struct ast_custom_function file_format_function
Definition: func_env.c:1413
static struct ast_custom_function file_count_line_function
Definition: func_env.c:1407
static struct ast_custom_function env_function
Definition: func_env.c:1389
static struct ast_custom_function file_function
Definition: func_env.c:1401
static struct ast_custom_function file_basename_function
Definition: func_env.c:1425
static struct ast_custom_function stat_function
Definition: func_env.c:1395
static struct ast_custom_function file_dirname_function
Definition: func_env.c:1419
#define ast_custom_function_register_escalating(acf, escalation)
Register a custom function which requires escalated privileges.
Definition: pbx.h:1568
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1559
@ AST_CFE_READ
Definition: pbx.h:1551
@ AST_CFE_BOTH
Definition: pbx.h:1553

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

399{
400 char *action;
401 struct stat s;
402
403 ast_copy_string(buf, "0", len);
404
405 action = strsep(&data, ",");
406 if (stat(data, &s)) {
407 return 0;
408 } else {
409 switch (*action) {
410 case 'e':
411 strcpy(buf, "1");
412 break;
413 case 's':
414 snprintf(buf, len, "%u", (unsigned int) s.st_size);
415 break;
416 case 'f':
417 snprintf(buf, len, "%d", S_ISREG(s.st_mode) ? 1 : 0);
418 break;
419 case 'd':
420 snprintf(buf, len, "%d", S_ISDIR(s.st_mode) ? 1 : 0);
421 break;
422 case 'M':
423 snprintf(buf, len, "%d", (int) s.st_mtime);
424 break;
425 case 'A':
426 snprintf(buf, len, "%d", (int) s.st_mtime);
427 break;
428 case 'C':
429 snprintf(buf, len, "%d", (int) s.st_ctime);
430 break;
431 case 'm':
432 snprintf(buf, len, "%o", (unsigned int) s.st_mode);
433 break;
434 }
435 }
436
437 return 0;
438}
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 = "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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 1461 of file func_env.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

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

Definition at line 1389 of file func_env.c.

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

Definition at line 1425 of file func_env.c.

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

Definition at line 1407 of file func_env.c.

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

Definition at line 1419 of file func_env.c.

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

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:902
static int file_read(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_env.c:642

Definition at line 1401 of file func_env.c.

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

Definition at line 1395 of file func_env.c.

Referenced by load_module(), and unload_module().