* srv.c (getsrv): Raise maximum packet size to 2048, as PACKETSZ is
[gnupg.git] / g10 / exec.c
blob9ecd2ab642119996dd721d74e8ba47a4ed0f6fa4
1 /* exec.c - generic call-a-program code
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #ifndef EXEC_TEMPFILE_ONLY
27 #include <sys/wait.h>
28 #endif
29 #ifdef HAVE_DOSISH_SYSTEM
30 #include <windows.h>
31 #endif
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <errno.h>
37 #include "gpg.h"
38 #include "options.h"
39 #include "i18n.h"
40 #include "iobuf.h"
41 #include "util.h"
42 #include "mkdtemp.h" /* From gnulib. */
43 #include "exec.h"
45 #ifdef NO_EXEC
46 int exec_write(struct exec_info **info,const char *program,
47 const char *args_in,const char *name,int writeonly,int binary)
49 log_error(_("no remote program execution supported\n"));
50 return G10ERR_GENERAL;
53 int exec_read(struct exec_info *info) { return G10ERR_GENERAL; }
54 int exec_finish(struct exec_info *info) { return G10ERR_GENERAL; }
55 int set_exec_path(const char *path) { return G10ERR_GENERAL; }
57 #else /* ! NO_EXEC */
59 #if defined (_WIN32)
60 /* This is a nicer system() for windows that waits for programs to
61 return before returning control to the caller. I hate helpful
62 computers. */
63 static int w32_system(const char *command)
65 PROCESS_INFORMATION pi;
66 STARTUPINFO si;
67 char *string;
69 /* We must use a copy of the command as CreateProcess modifies this
70 argument. */
71 string=xstrdup(command);
73 memset(&pi,0,sizeof(pi));
74 memset(&si,0,sizeof(si));
75 si.cb=sizeof(si);
77 if(!CreateProcess(NULL,string,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
78 return -1;
80 /* Wait for the child to exit */
81 WaitForSingleObject(pi.hProcess,INFINITE);
83 CloseHandle(pi.hProcess);
84 CloseHandle(pi.hThread);
85 xfree(string);
87 return 0;
89 #endif
91 /* Replaces current $PATH */
92 int set_exec_path(const char *path)
94 char *p;
96 p=xmalloc(5+strlen(path)+1);
97 strcpy(p,"PATH=");
98 strcat(p,path);
100 if(DBG_EXTPROG)
101 log_debug("set_exec_path: %s\n",p);
103 /* Notice that path is never freed. That is intentional due to the
104 way putenv() works. This leaks a few bytes if we call
105 set_exec_path multiple times. */
107 if(putenv(p)!=0)
108 return G10ERR_GENERAL;
109 else
110 return 0;
113 /* Makes a temp directory and filenames */
114 static int make_tempdir(struct exec_info *info)
116 char *tmp=opt.temp_dir,*namein=info->name,*nameout;
118 if(!namein)
119 namein=info->flags.binary?"tempin" EXTSEP_S "bin":"tempin" EXTSEP_S "txt";
121 nameout=info->flags.binary?"tempout" EXTSEP_S "bin":"tempout" EXTSEP_S "txt";
123 /* Make up the temp dir and files in case we need them */
125 if(tmp==NULL)
127 #if defined (_WIN32)
128 int err;
130 tmp=xmalloc(MAX_PATH+2);
131 err=GetTempPath(MAX_PATH+1,tmp);
132 if(err==0 || err>MAX_PATH+1)
133 strcpy(tmp,"c:\\windows\\temp");
134 else
136 int len=strlen(tmp);
138 /* GetTempPath may return with \ on the end */
139 while(len>0 && tmp[len-1]=='\\')
141 tmp[len-1]='\0';
142 len--;
145 #else /* More unixish systems */
146 tmp=getenv("TMPDIR");
147 if(tmp==NULL)
149 tmp=getenv("TMP");
150 if(tmp==NULL)
152 #ifdef __riscos__
153 tmp="<Wimp$ScrapDir>.GnuPG";
154 mkdir(tmp,0700); /* Error checks occur later on */
155 #else
156 tmp="/tmp";
157 #endif
160 #endif
163 info->tempdir=xmalloc(strlen(tmp)+strlen(DIRSEP_S)+10+1);
165 sprintf(info->tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp);
167 #if defined (_WIN32)
168 xfree(tmp);
169 #endif
171 if(mkdtemp(info->tempdir)==NULL)
172 log_error(_("can't create directory `%s': %s\n"),
173 info->tempdir,strerror(errno));
174 else
176 info->flags.madedir=1;
178 info->tempfile_in=xmalloc(strlen(info->tempdir)+
179 strlen(DIRSEP_S)+strlen(namein)+1);
180 sprintf(info->tempfile_in,"%s" DIRSEP_S "%s",info->tempdir,namein);
182 if(!info->flags.writeonly)
184 info->tempfile_out=xmalloc(strlen(info->tempdir)+
185 strlen(DIRSEP_S)+strlen(nameout)+1);
186 sprintf(info->tempfile_out,"%s" DIRSEP_S "%s",info->tempdir,nameout);
190 return info->flags.madedir?0:G10ERR_GENERAL;
193 /* Expands %i and %o in the args to the full temp files within the
194 temp directory. */
195 static int expand_args(struct exec_info *info,const char *args_in)
197 const char *ch=args_in;
198 unsigned int size,len;
200 info->flags.use_temp_files=0;
201 info->flags.keep_temp_files=0;
203 if(DBG_EXTPROG)
204 log_debug("expanding string \"%s\"\n",args_in);
206 size=100;
207 info->command=xmalloc(size);
208 len=0;
209 info->command[0]='\0';
211 while(*ch!='\0')
213 if(*ch=='%')
215 char *append=NULL;
217 ch++;
219 switch(*ch)
221 case 'O':
222 info->flags.keep_temp_files=1;
223 /* fall through */
225 case 'o': /* out */
226 if(!info->flags.madedir)
228 if(make_tempdir(info))
229 goto fail;
231 append=info->tempfile_out;
232 info->flags.use_temp_files=1;
233 break;
235 case 'I':
236 info->flags.keep_temp_files=1;
237 /* fall through */
239 case 'i': /* in */
240 if(!info->flags.madedir)
242 if(make_tempdir(info))
243 goto fail;
245 append=info->tempfile_in;
246 info->flags.use_temp_files=1;
247 break;
249 case '%':
250 append="%";
251 break;
254 if(append)
256 size_t applen=strlen(append);
258 if(applen+len>size-1)
260 if(applen<100)
261 applen=100;
263 size+=applen;
264 info->command=xrealloc(info->command,size);
267 strcat(info->command,append);
268 len+=strlen(append);
271 else
273 if(len==size-1) /* leave room for the \0 */
275 size+=100;
276 info->command=xrealloc(info->command,size);
279 info->command[len++]=*ch;
280 info->command[len]='\0';
283 ch++;
286 if(DBG_EXTPROG)
287 log_debug("args expanded to \"%s\", use %u, keep %u\n",info->command,
288 info->flags.use_temp_files,info->flags.keep_temp_files);
290 return 0;
292 fail:
294 xfree(info->command);
295 info->command=NULL;
297 return G10ERR_GENERAL;
300 /* Either handles the tempfile creation, or the fork/exec. If it
301 returns ok, then info->tochild is a FILE * that can be written to.
302 The rules are: if there are no args, then it's a fork/exec/pipe.
303 If there are args, but no tempfiles, then it's a fork/exec/pipe via
304 shell -c. If there are tempfiles, then it's a system. */
306 int exec_write(struct exec_info **info,const char *program,
307 const char *args_in,const char *name,int writeonly,int binary)
309 int ret=G10ERR_GENERAL;
311 if(opt.exec_disable && !opt.no_perm_warn)
313 log_info(_("external program calls are disabled due to unsafe "
314 "options file permissions\n"));
316 return ret;
319 #if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
320 /* There should be no way to get to this spot while still carrying
321 setuid privs. Just in case, bomb out if we are. */
322 if ( getuid () != geteuid ())
323 BUG ();
324 #endif
326 if(program==NULL && args_in==NULL)
327 BUG();
329 *info=xmalloc_clear(sizeof(struct exec_info));
331 if(name)
332 (*info)->name=xstrdup(name);
333 (*info)->flags.binary=binary;
334 (*info)->flags.writeonly=writeonly;
336 /* Expand the args, if any */
337 if(args_in && expand_args(*info,args_in))
338 goto fail;
340 #ifdef EXEC_TEMPFILE_ONLY
341 if(!(*info)->flags.use_temp_files)
343 log_error(_("this platform requires temporary files when calling"
344 " external programs\n"));
345 goto fail;
348 #else /* !EXEC_TEMPFILE_ONLY */
350 /* If there are no args, or there are args, but no temp files, we
351 can use fork/exec/pipe */
352 if(args_in==NULL || (*info)->flags.use_temp_files==0)
354 int to[2],from[2];
356 if(pipe(to)==-1)
357 goto fail;
359 if(pipe(from)==-1)
361 close(to[0]);
362 close(to[1]);
363 goto fail;
366 if(((*info)->child=fork())==-1)
368 close(to[0]);
369 close(to[1]);
370 close(from[0]);
371 close(from[1]);
372 goto fail;
375 if((*info)->child==0)
377 char *shell=getenv("SHELL");
379 if(shell==NULL)
380 shell="/bin/sh";
382 /* I'm the child */
384 /* If the program isn't going to respond back, they get to
385 keep their stdout/stderr */
386 if(!(*info)->flags.writeonly)
388 /* implied close of STDERR */
389 if(dup2(STDOUT_FILENO,STDERR_FILENO)==-1)
390 _exit(1);
392 /* implied close of STDOUT */
393 close(from[0]);
394 if(dup2(from[1],STDOUT_FILENO)==-1)
395 _exit(1);
398 /* implied close of STDIN */
399 close(to[1]);
400 if(dup2(to[0],STDIN_FILENO)==-1)
401 _exit(1);
403 if(args_in==NULL)
405 if(DBG_EXTPROG)
406 log_debug("execlp: %s\n",program);
408 execlp(program,program,(void *)NULL);
410 else
412 if(DBG_EXTPROG)
413 log_debug("execlp: %s -c %s\n",shell,(*info)->command);
415 execlp(shell,shell,"-c",(*info)->command,(void *)NULL);
418 /* If we get this far the exec failed. Clean up and return. */
420 if(args_in==NULL)
421 log_error(_("unable to execute program `%s': %s\n"),
422 program,strerror(errno));
423 else
424 log_error(_("unable to execute shell `%s': %s\n"),
425 shell,strerror(errno));
427 /* This mimics the POSIX sh behavior - 127 means "not found"
428 from the shell. */
429 if(errno==ENOENT)
430 _exit(127);
432 _exit(1);
435 /* I'm the parent */
437 close(to[0]);
439 (*info)->tochild=fdopen(to[1],binary?"wb":"w");
440 if((*info)->tochild==NULL)
442 ret = gpg_error_from_syserror ();
443 close(to[1]);
444 goto fail;
447 close(from[1]);
449 (*info)->fromchild=iobuf_fdopen(from[0],"r");
450 if((*info)->fromchild==NULL)
452 ret = gpg_error_from_syserror ();
453 close(from[0]);
454 goto fail;
457 /* fd iobufs are cached?! */
458 iobuf_ioctl((*info)->fromchild,3,1,NULL);
460 return 0;
462 #endif /* !EXEC_TEMPFILE_ONLY */
464 if(DBG_EXTPROG)
465 log_debug("using temp file `%s'\n",(*info)->tempfile_in);
467 /* It's not fork/exec/pipe, so create a temp file */
468 if( is_secured_filename ((*info)->tempfile_in) )
470 (*info)->tochild = NULL;
471 errno = EPERM;
473 else
474 (*info)->tochild=fopen((*info)->tempfile_in,binary?"wb":"w");
475 if((*info)->tochild==NULL)
477 ret = gpg_error_from_syserror ();
478 log_error(_("can't create `%s': %s\n"),
479 (*info)->tempfile_in,strerror(errno));
480 goto fail;
483 ret=0;
485 fail:
486 return ret;
489 int exec_read(struct exec_info *info)
491 int ret=G10ERR_GENERAL;
493 fclose(info->tochild);
494 info->tochild=NULL;
496 if(info->flags.use_temp_files)
498 if(DBG_EXTPROG)
499 log_debug("system() command is %s\n",info->command);
501 #if defined (_WIN32)
502 info->progreturn=w32_system(info->command);
503 #else
504 info->progreturn=system(info->command);
505 #endif
507 if(info->progreturn==-1)
509 log_error(_("system error while calling external program: %s\n"),
510 strerror(errno));
511 info->progreturn=127;
512 goto fail;
515 #if defined(WIFEXITED) && defined(WEXITSTATUS)
516 if(WIFEXITED(info->progreturn))
517 info->progreturn=WEXITSTATUS(info->progreturn);
518 else
520 log_error(_("unnatural exit of external program\n"));
521 info->progreturn=127;
522 goto fail;
524 #else
525 /* If we don't have the macros, do the best we can. */
526 info->progreturn = (info->progreturn & 0xff00) >> 8;
527 #endif
529 /* 127 is the magic value returned from system() to indicate
530 that the shell could not be executed, or from /bin/sh to
531 indicate that the program could not be executed. */
533 if(info->progreturn==127)
535 log_error(_("unable to execute external program\n"));
536 goto fail;
539 if(!info->flags.writeonly)
541 info->fromchild=iobuf_open(info->tempfile_out);
542 if (info->fromchild
543 && is_secured_file (iobuf_get_fd (info->fromchild)))
545 iobuf_close (info->fromchild);
546 info->fromchild = NULL;
547 errno = EPERM;
549 if(info->fromchild==NULL)
551 ret = gpg_error_from_syserror ();
552 log_error(_("unable to read external program response: %s\n"),
553 strerror(errno));
554 goto fail;
557 /* Do not cache this iobuf on close */
558 iobuf_ioctl(info->fromchild,3,1,NULL);
562 ret=0;
564 fail:
565 return ret;
568 int exec_finish(struct exec_info *info)
570 int ret=info->progreturn;
572 if(info->fromchild)
573 iobuf_close(info->fromchild);
575 if(info->tochild)
576 fclose(info->tochild);
578 #ifndef EXEC_TEMPFILE_ONLY
579 if(info->child>0)
581 if(waitpid(info->child,&info->progreturn,0)!=0 &&
582 WIFEXITED(info->progreturn))
583 ret=WEXITSTATUS(info->progreturn);
584 else
586 log_error(_("unnatural exit of external program\n"));
587 ret=127;
590 #endif
592 if(info->flags.madedir && !info->flags.keep_temp_files)
594 if(info->tempfile_in)
596 if(unlink(info->tempfile_in)==-1)
597 log_info(_("WARNING: unable to remove tempfile (%s) `%s': %s\n"),
598 "in",info->tempfile_in,strerror(errno));
601 if(info->tempfile_out)
603 if(unlink(info->tempfile_out)==-1)
604 log_info(_("WARNING: unable to remove tempfile (%s) `%s': %s\n"),
605 "out",info->tempfile_out,strerror(errno));
608 if(rmdir(info->tempdir)==-1)
609 log_info(_("WARNING: unable to remove temp directory `%s': %s\n"),
610 info->tempdir,strerror(errno));
613 xfree(info->command);
614 xfree(info->name);
615 xfree(info->tempdir);
616 xfree(info->tempfile_in);
617 xfree(info->tempfile_out);
618 xfree(info);
620 return ret;
622 #endif /* ! NO_EXEC */