Create ast_safe_system which closes off file descriptors before spawning system(...
authorMark Spencer <markster@digium.com>
Sun, 21 Mar 2004 18:15:37 +0000 (18:15 +0000)
committerMark Spencer <markster@digium.com>
Sun, 21 Mar 2004 18:15:37 +0000 (18:15 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2514 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_voicemail.c
asterisk.c
include/asterisk/app.h

index 5a4196b..f67d03c 100755 (executable)
@@ -825,7 +825,7 @@ static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *m
                }
                fclose(p);
                snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
-               system(tmp2);
+               ast_safe_system(tmp2);
                ast_log(LOG_DEBUG, "Sent mail to %s with command '%s'\n", who, mailcmd);
        } else {
                ast_log(LOG_WARNING, "Unable to launch '%s'\n", mailcmd);
@@ -836,16 +836,27 @@ static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *m
 
 static int sendpage(char *srcemail, char *pager, int msgnum, char *mailbox, char *callerid, long duration, struct ast_vm_user *vmu)
 {
-       FILE *p;
+       FILE *p=NULL;
+       int pfd;
        char date[256];
        char host[256];
        char who[256];
        char dur[256];
+       char tmp[80] = "/tmp/astmail-XXXXXX";
+       char tmp2[256];
        time_t t;
        struct tm tm;
        struct vm_zone *the_zone = NULL;
        p = popen(mailcmd, "w");
 
+       if (pfd > -1) {
+               p = fdopen(pfd, "w");
+               if (!p) {
+                       close(pfd);
+                       pfd = -1;
+               }
+       }
+
        if (p) {
                gethostname(host, sizeof(host));
                if (strchr(srcemail, '@'))
@@ -883,7 +894,9 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *mailbox, char
                strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
                fprintf(p, "New %s long msg in box %s\n"
                           "from %s, on %s", dur, mailbox, (callerid ? callerid : "unknown"), date);
-               pclose(p);
+               fclose(p);
+               snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
+               ast_safe_system(tmp2);
                ast_log(LOG_DEBUG, "Sent mail to %s with command '%s'\n", who, mailcmd);
        } else {
                ast_log(LOG_WARNING, "Unable to launch '%s'\n", mailcmd);
@@ -2296,7 +2309,7 @@ static int forward_message(struct ast_channel *chan, char *context, char *dir, i
                snprintf(todir, sizeof(todir), "%s/voicemail/%s/%s/INBOX",  (char *)ast_config_AST_SPOOL_DIR, vmtmp->context, vmtmp->mailbox);
                snprintf(sys, sizeof(sys), "mkdir -p %s\n", todir);
                ast_log(LOG_DEBUG, sys);
-               system(sys);
+               ast_safe_system(sys);
 
                todircount = count_messages(todir);
                strncpy(tmp, fmt, sizeof(tmp) - 1);
@@ -2307,11 +2320,11 @@ static int forward_message(struct ast_channel *chan, char *context, char *dir, i
                                s = "WAV";
                        snprintf(sys, sizeof(sys), "cp %s/msg%04d.%s %s/msg%04d.%s\n", dir, curmsg, s, todir, todircount, s);
                        ast_log(LOG_DEBUG, sys);
-                       system(sys);
+                       ast_safe_system(sys);
                }
                snprintf(sys, sizeof(sys), "cp %s/msg%04d.txt %s/msg%04d.txt\n", dir, curmsg, todir, todircount);
                ast_log(LOG_DEBUG, sys);
-               system(sys);
+               ast_safe_system(sys);
                snprintf(fn, sizeof(fn), "%s/msg%04d", todir,todircount);
 
                /* load the information on the source message so we can send an e-mail like a new message */
index 2811a7c..5e1d812 100755 (executable)
@@ -28,6 +28,7 @@
 #include <asterisk/pbx.h>
 #include <asterisk/enum.h>
 #include <asterisk/rtp.h>
+#include <asterisk/app.h>
 #include <sys/resource.h>
 #include <fcntl.h>
 #include <stdio.h>
@@ -153,6 +154,42 @@ static int fdprint(int fd, const char *s)
        return write(fd, s, strlen(s) + 1);
 }
 
+int ast_safe_system(const char *s)
+{
+       /* XXX This function needs some optimization work XXX */
+       pid_t pid;
+       int x;
+       int res;
+       struct rusage rusage;
+       int status;
+       pid = fork();
+       if (pid == 0) {
+               /* Close file descriptors and launch system command */
+               for (x=STDERR_FILENO + 1; x<4096;x++) {
+                       close(x);
+               }
+               res = system(s);
+               exit(res);
+       } else if (pid > 0) {
+               for(;;) {
+                       res = wait4(pid, &status, 0, &rusage);
+                       if (res > -1) {
+                               if (WIFEXITED(status))
+                                       res = WEXITSTATUS(status);
+                               else
+                                       res = -1;
+                       } else {
+                               if (errno != EINTR) 
+                                       break;
+                       }
+               }
+       } else {
+               ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
+               res = -1;
+       }
+       return res;
+}
+
 /*
  * write the string to all attached console clients
  */
@@ -607,9 +644,9 @@ static void consolehandler(char *s)
                /* The real handler for bang */
                if (s[0] == '!') {
                        if (s[1])
-                               system(s+1);
+                               ast_safe_system(s+1);
                        else
-                               system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
+                               ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
                } else 
                ast_cli_command(STDOUT_FILENO, s);
        } else
@@ -627,9 +664,9 @@ static int remoteconsolehandler(char *s)
                /* The real handler for bang */
                if (s[0] == '!') {
                        if (s[1])
-                               system(s+1);
+                               ast_safe_system(s+1);
                        else
-                               system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
+                               ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
                        ret = 1;
                }
                if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
index ef7b05c..d32575b 100755 (executable)
@@ -45,6 +45,9 @@ extern int ast_app_has_voicemail(const char *mailbox);
 //! Determine number of new/old messages in a mailbox
 extern int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs);
 
+//! Safely spawn an external program while closingn file descriptors
+extern int ast_safe_system(const char *s);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif