From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Lars Magne Ingebrigtsen Newsgroups: gmane.emacs.devel Subject: Re: Redirecting standard output Date: Thu, 21 Apr 2011 16:25:13 +0200 Organization: Programmerer Ingebrigtsen Message-ID: References: <83pqog2lko.fsf@gnu.org> <83bozz3jev.fsf@gnu.org> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: dough.gmane.org 1303395938 10219 80.91.229.12 (21 Apr 2011 14:25:38 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Thu, 21 Apr 2011 14:25:38 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Apr 21 16:25:34 2011 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1QCup2-0001Op-I0 for ged-emacs-devel@m.gmane.org; Thu, 21 Apr 2011 16:25:32 +0200 Original-Received: from localhost ([::1]:42902 helo=lists2.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QCup2-0008WA-1O for ged-emacs-devel@m.gmane.org; Thu, 21 Apr 2011 10:25:32 -0400 Original-Received: from eggs.gnu.org ([140.186.70.92]:36207) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QCuoy-0008Tc-20 for emacs-devel@gnu.org; Thu, 21 Apr 2011 10:25:29 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QCuow-0004Dr-1S for emacs-devel@gnu.org; Thu, 21 Apr 2011 10:25:28 -0400 Original-Received: from lo.gmane.org ([80.91.229.12]:39140) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QCuov-0004Dj-IZ for emacs-devel@gnu.org; Thu, 21 Apr 2011 10:25:25 -0400 Original-Received: from list by lo.gmane.org with local (Exim 4.69) (envelope-from ) id 1QCuou-0001Ie-1b for emacs-devel@gnu.org; Thu, 21 Apr 2011 16:25:24 +0200 Original-Received: from cm-84.215.51.58.getinternet.no ([84.215.51.58]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Thu, 21 Apr 2011 16:25:24 +0200 Original-Received: from larsi by cm-84.215.51.58.getinternet.no with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Thu, 21 Apr 2011 16:25:24 +0200 X-Injected-Via-Gmane: http://gmane.org/ Mail-Followup-To: emacs-devel@gnu.org Original-Lines: 229 Original-X-Complaints-To: usenet@dough.gmane.org X-Gmane-NNTP-Posting-Host: cm-84.215.51.58.getinternet.no Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAFVBMVEWsqqU/OzkJBgcHBAUF AgMLCQkVEhJieXxKAAACe0lEQVQ4jUWTQZrbIAyFxaJdm0XYjwg+ADg5QEz3La5YF88H9z9Cn3Cm dRax+ZHekxCUf/zOD/n9yvlVrTXWudDlnjPlnPcQRPbtORxAu4XxBV5ZWISfvdthhxu1Y/MEJedy PMdqrYzDPjsCXgB7Rug61tqGLSPXfB7vCNUf0ttoSBVjLp9ZNfaU0raniOTWOvuZ4uuuYI8F63uE FwCyJydNkilFRkh+xe6rXcjIBRIlzzHxtsUS67IQdT8DdoocY/KbV4AIGkfeADaNWAuyxeOxKmiH LqdICUV7gMextqbgM0MzBYqBuXAoIrU17ZXj6BMXRHjugcMYgnXT2u14MbOouNeX0QEIqW58D3IB pOJ13C5gb8yPoCAlBABohCWz3PAtRYivZ619tsQsJ+vhKAgTiPaXyJiuijIB/rDl3UTb5QLQqeOU EmodqFzBfAAgfMItjhrNtW68waxBqoxWoYGjap0LslOZEl1+uTFUAn8wqwCrRYaeN0zZ99OhMTNW 24xTgCLbVCEBCTCm+QEW6y5bpAmD9hy71e0/UMolX8k4FA4ytVWD3z0wDhFusT1cdfiYPrR67F7M dKTNRdsL+w/Wt/+g8FV5KdpJ0nFTcfRdP5n9PNqg02bUrrxB8NdR/aEJzK1MM4iIaW75OYE1J/Q0 AkOUMFsivxR8txbKZabC2EVNVRU46/BWviLmnAgAOZ2ecSrw8zqF8gXUOkZUKO34TflFx20wVjHT ADnlDWPPon7diQHUGRS673qxIB/Ub8E18s9TI3B9VARVAhhWK+sE8a4XWm8JCvnG6t6jSUJ649Ku qVYieI3sn1019IbuSdMlolMzPXDzY/gLA4vpqi9FsMMAAAAASUVORK5CYII= Mail-Copies-To: never X-Now-Playing: Susanna and the Magical Orchestra's _List of Lights and Buoys_: "Time" User-Agent: Gnus/5.110016 (No Gnus v0.16) Emacs/24.0.50 (gnu/linux) Cancel-Lock: sha1:UsQyljnwdTwXsOOes4JFFHQRKm4= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 80.91.229.12 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:138611 Archived-At: --=-=-= Content-Type: text/plain Here's a quick stab at it. There's some cargo-cult programming in there, and I have to go over the error cases again to make sure there's no FD leaks, but it'll probably look something like the patch included. Usage is: (call-process "echo" nil '(:file "/tmp/hello") nil "thing") or (call-process "echo" nil '((:file "/tmp/hello") "/tmp/error") nil "thing") So with this, `call-process' can do all the combinations of STDERR/STDOUT to file/buffers, except that you can't put STDERR in one buffer and STDOUT in a different buffer. But you can get STDERR in a buffer by itself, and STDOUT in a file, so it's progress of a kind... --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=callproc.patch === modified file 'src/callproc.c' *** src/callproc.c 2011-04-14 19:34:42 +0000 --- src/callproc.c 2011-04-21 14:17:44 +0000 *************** *** 96,101 **** --- 96,103 ---- /* Nonzero if this is termination due to exit. */ static int call_process_exited; + static Lisp_Object Qcallproc_file_symbol; + static Lisp_Object Fgetenv_internal (Lisp_Object, Lisp_Object); static Lisp_Object *************** *** 196,205 **** --- 198,209 ---- /* File to use for stderr in the child. t means use same as standard output. */ Lisp_Object error_file; + Lisp_Object output_file = Qnil; #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */ char *outf, *tempfile; int outfilefd; #endif + int fd_output = 0; struct coding_system process_coding; /* coding-system of process output */ struct coding_system argument_coding; /* coding-system of arguments */ /* Set to the return value of Ffind_operation_coding_system. */ *************** *** 275,281 **** /* If BUFFER is a list, its meaning is (BUFFER-FOR-STDOUT FILE-FOR-STDERR). */ ! if (CONSP (buffer)) { if (CONSP (XCDR (buffer))) { --- 279,286 ---- /* If BUFFER is a list, its meaning is (BUFFER-FOR-STDOUT FILE-FOR-STDERR). */ ! if (CONSP (buffer) && ! ! EQ (Qcallproc_file_symbol, XCAR (buffer))) { if (CONSP (XCDR (buffer))) { *************** *** 291,296 **** --- 296,312 ---- buffer = XCAR (buffer); } + /* If the buffer is (still) a list, it might be a (:file "file") spec. */ + if (CONSP (buffer) && + CONSP (XCDR (buffer)) && + EQ (Qcallproc_file_symbol, XCAR (buffer))) + { + output_file = Fexpand_file_name (XCAR (XCDR (buffer)), + BVAR (current_buffer, directory)); + CHECK_STRING (output_file); + buffer = Qnil; + } + if (!(EQ (buffer, Qnil) || EQ (buffer, Qt) || INTEGERP (buffer))) *************** *** 318,328 **** protected by the caller, so all we really have to worry about is buffer. */ { ! struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; current_dir = BVAR (current_buffer, directory); ! GCPRO4 (infile, buffer, current_dir, error_file); current_dir = Funhandled_file_name_directory (current_dir); if (NILP (current_dir)) --- 334,344 ---- protected by the caller, so all we really have to worry about is buffer. */ { ! struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; current_dir = BVAR (current_buffer, directory); ! GCPRO5 (infile, buffer, current_dir, error_file, output_file); current_dir = Funhandled_file_name_directory (current_dir); if (NILP (current_dir)) *************** *** 342,347 **** --- 358,365 ---- current_dir = ENCODE_FILE (current_dir); if (STRINGP (error_file) && STRING_MULTIBYTE (error_file)) error_file = ENCODE_FILE (error_file); + if (STRINGP (output_file) && STRING_MULTIBYTE (output_file)) + output_file = ENCODE_FILE (output_file); UNGCPRO; } *************** *** 353,358 **** --- 371,394 ---- infile = DECODE_FILE (infile); report_file_error ("Opening process input file", Fcons (infile, Qnil)); } + + if (STRINGP (output_file)) + { + #ifdef DOS_NT + fd_output = emacs_open (SSDATA (output_file), + O_WRONLY | O_TRUNC | O_CREAT | O_TEXT, + S_IREAD | S_IWRITE); + #else /* not DOS_NT */ + fd_output = creat (SSDATA (output_file), 0666); + #endif /* not DOS_NT */ + if (fd_output < 0) + { + output_file = DECODE_FILE (output_file); + report_file_error ("Opening process output file", + Fcons (output_file, Qnil)); + } + } + /* Search for program; barf if not found. */ { struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; *************** *** 413,425 **** strcat (tempfile, "detmp.XXX"); mktemp (tempfile); ! outfilefd = creat (tempfile, S_IREAD | S_IWRITE); ! if (outfilefd < 0) { emacs_close (filefd); report_file_error ("Opening process output file", ! Fcons (build_string (tempfile), Qnil)); } fd[0] = filefd; fd[1] = outfilefd; #endif /* MSDOS */ --- 449,467 ---- strcat (tempfile, "detmp.XXX"); mktemp (tempfile); ! /* If we're redirecting STDOUT to a file, this is already opened. */ ! if (fd_output == 0) { + outfilefd = creat (tempfile, S_IREAD | S_IWRITE); + if (outfilefd < 0) + { emacs_close (filefd); report_file_error ("Opening process output file", ! Fcons (build_string (tempfile), Qnil)); ! } } + else + outfilefd = fd_output; fd[0] = filefd; fd[1] = outfilefd; #endif /* MSDOS */ *************** *** 450,455 **** --- 492,499 ---- struct sigaction sigpipe_action; #endif + if (fd_output > 0) + fd1 = fd_output; #if 0 /* Some systems don't have sigblock. */ mask = sigblock (sigmask (SIGCHLD)); #endif *************** *** 1554,1559 **** --- 1598,1606 ---- #endif staticpro (&Vtemp_file_name_pattern); + Qcallproc_file_symbol = intern_c_string (":file"); + staticpro (&Qcallproc_file_symbol); + DEFVAR_LISP ("shell-file-name", Vshell_file_name, doc: /* *File name to load inferior shells from. Initialized from the SHELL environment variable, or to a system-dependent --=-=-= Content-Type: text/plain (Note! Not thoroughly tested. I'll go through all the possibilities now...) -- (domestic pets only, the antidote for overdose, milk.) bloggy blog http://lars.ingebrigtsen.no/ --=-=-=--