Exemplo n.º 1
0
/*
 * filter_data_file - function to return filename of scratch file for
 *		      display and sending filters.  This file is created
 *		      the first time it's needed, and persists until pine
 *		      exits.
 */
char *
filter_data_file(int create_it)
{
    static char *fn = NULL;

    if(!fn && create_it)
      fn = temp_nam(NULL, "df");
    
    return(fn);
}
Exemplo n.º 2
0
/*
 * Return the name of a file in the same directory as filename.
 * Same as temp_nam except it figures out a name in the same directory.
 * It also returns the name of the directory in ret_dir if ret_dir is
 * not NULL. That has to be freed by caller. If return is not NULL the
 * empty file has been created.
 */
char *
tempfile_in_same_dir(char *filename, char *prefix, char **ret_dir)
{
#ifndef MAXPATH
#define MAXPATH 1000    /* Longest file path we can deal with */
#endif
    char  dir[MAXPATH+1];
    char *dirp = NULL;
    char *ret_file = NULL;

    if(filename){
	char *lc;

	if((lc = last_cmpnt(filename)) != NULL){
	    int to_copy;

	    to_copy = (lc - filename > 1) ? (lc - filename - 1) : 1;
	    strncpy(dir, filename, MIN(to_copy, sizeof(dir)-1));
	    dir[MIN(to_copy, sizeof(dir)-1)] = '\0';
	}
	else{
	    dir[0] = '.';
	    dir[1] = '\0';
	}

	dirp = dir;
    }


    /* temp_nam creates ret_file */
    ret_file = temp_nam(dirp, prefix);

    /*
     * If temp_nam can't write in dirp it puts the file in a temp directory
     * anyway. We don't want that to happen to us.
     */
    if(dirp && ret_file && !in_dir(dirp, ret_file)){
	our_unlink(ret_file);
	fs_give((void **)&ret_file);  /* sets it to NULL */
    }

    if(ret_file && ret_dir && dirp)
      *ret_dir = cpystr(dirp);
      

    return(ret_file);
}
Exemplo n.º 3
0
/*----------------------------------------------------------------------
     Spawn a child process and optionally connect read/write pipes to it

  Args: command -- string to hand the shell
	outfile -- address of pointer containing file to receive output
	errfile -- address of pointer containing file to receive error output
	mode -- mode for type of shell, signal protection etc...
  Returns: pointer to alloc'd PIPE_S on success, NULL otherwise

  The outfile is either NULL, a pointer to a NULL value, or a pointer
  to the requested name for the output file.  In the pointer-to-NULL case
  the caller doesn't care about the name, but wants to see the pipe's
  results so we make one up.  It's up to the caller to make sure the
  free storage containing the name is cleaned up.

  Mode bits serve several purposes.
    PIPE_WRITE tells us we need to open a pipe to write the child's
	stdin.
    PIPE_READ tells us we need to open a pipe to read from the child's
	stdout/stderr.  *NOTE*  Having neither of the above set means 
	we're not setting up any pipes, just forking the child and exec'ing
	the command.  Also, this takes precedence over any named outfile.
    PIPE_STDERR means we're to tie the childs stderr to the same place
	stdout is going.  *NOTE* This only makes sense then if PIPE_READ
	or an outfile is provided.  Also, this takes precedence over any
	named errfile.
    PIPE_RESET means we reset the terminal mode to what it was before
	we started pine and then exec the command. In PC-Pine, _RESET
	was a shortcut for just executing a command.  We'll try to pay
	attention to the above flags to make sure we do the right thing.
    PIPE_PROT means to protect the child from the usual nasty signals
	that might cause premature death.  Otherwise, the default signals are
	set so the child can deal with the nasty signals in its own way.
	NOT USED UNDER WINDOWS
    PIPE_NOSHELL means we're to exec the command without the aid of
	a system shell.  *NOTE* This negates the affect of PIPE_USER.
	NOT USED UNDER WINDOWS
    PIPE_USER means we're to try executing the command in the user's
	shell.  Right now we only look in the environment, but that may get
	more sophisticated later.
	NOT USED UNDER WINDOWS
    PIPE_RUNNOW was added for WINDOWS for the case pipe is called to run
        a shell program (like for url viewing).  This is the only option
	where we don't wait for child termination, and is only obeyed if
	PIPE_WRITE and PIPE_READ aren't set
 ----*/
PIPE_S *
open_system_pipe(char *command, char **outfile, char **errfile, int mode,
		 int timeout, void (*pipecb_f)(PIPE_S *, int, void *),
		 void (*piperr_f)(char *))
{
    PIPE_S *syspipe = NULL;
#ifdef	_WINDOWS
    int exit_code = 0;
    char cmdbuf[1024];
    unsigned flags = 0;
#else
    char    shellpath[MAXPATH+1], *shell;
    int     p[2], oparentd = -1, ochildd = -1, iparentd = -1, ichildd = -1;
#endif

#ifdef	_WINDOWS
    if(mode & PIPE_STDERR)
      flags |= MSWIN_EAW_CAPT_STDERR;
    /* 
     * It'll be a lot more difficult to support READing and WRITing.
     * This was never supported, and there don't look to be any cases
     * that set both of these flags anymore for win32.
     *
     * errfile could probably be supported pretty easily
     */

    if(errfile){
	if(piperr_f)
	  (*piperr_f)("Pipe arg not yet supported: Error File");

	return(NULL);
    }


    if((mode & PIPE_RUNNOW)
       && !(mode & (PIPE_WRITE | PIPE_READ | PIPE_STDERR))){
	if(mswin_shell_exec(command, NULL) == 0
	   && (syspipe = (PIPE_S *) malloc(sizeof(PIPE_S))) != NULL){
	    memset(syspipe, 0, sizeof(PIPE_S));
	    return(syspipe);
	}

	return(NULL);
    }

    strncpy(cmdbuf, command, sizeof(cmdbuf));
    cmdbuf[sizeof(cmdbuf)-1] = '\0';

    if((syspipe = (PIPE_S *) malloc(sizeof(PIPE_S))) == NULL)
      return(NULL);

    memset(syspipe, 0, sizeof(PIPE_S));
    syspipe->mode = mode;
    if(!outfile){
	syspipe->deloutfile = 1;
	if(mode & PIPE_READ){
	    syspipe->outfile = temp_nam(NULL, "po");
	    our_unlink(syspipe->outfile);
	}
    }
    else{
	if(!*outfile) /* asked for, but not named? */
	  *outfile = temp_nam(NULL, "po");

	our_unlink(*outfile);
	syspipe->outfile = (char *) malloc((strlen(*outfile)+1)*sizeof(char));
	snprintf(syspipe->outfile, strlen(*outfile)+1, "%s", *outfile);
    }

    if(mode & PIPE_WRITE){
	/*
	 * Create tmp file to write, spawn child in close_pipe
	 * after tmp file's written...
	 */
	syspipe->infile = temp_nam(NULL, "pw");
	syspipe->out.f = our_fopen(syspipe->infile, "wb");
	syspipe->command = (char *) malloc((strlen(cmdbuf)+1)*sizeof(char));
	snprintf(syspipe->command, strlen(cmdbuf)+1, "%s", cmdbuf);
	dprint((1, "pipe write: %s", cmdbuf));
    }
    else if(mode & PIPE_READ){
	/* 
	 * Create a tmp file for command result, exec the command
	 * here into temp file, and return file pointer to it...
	 */
	syspipe->command = (char *) malloc((strlen(cmdbuf)+1)*sizeof(char));
	snprintf(syspipe->command, strlen(cmdbuf)+1, "%s", cmdbuf);
	dprint((1, "pipe read: %s", cmdbuf));
	if(pipe_mswin_exec_wrapper("pipe command", syspipe,
				   flags, pipecb_f, piperr_f)){
	    if(syspipe->outfile){
		free((void *) syspipe->outfile);
		syspipe->outfile = NULL;
	    }

	    zot_pipe(&syspipe);
	}
	else{
	  syspipe->in.f = our_fopen(syspipe->outfile, "rb");
	  syspipe->exit_code = exit_code;
	}
    }
    else{
	/* we just run the command taking outfile into account */
	syspipe->command = (char *) malloc((strlen(cmdbuf)+1)*sizeof(char));
	snprintf(syspipe->command, strlen(cmdbuf)+1, "%s", cmdbuf);
	if(pipe_mswin_exec_wrapper("pipe command", syspipe,
				   flags, pipecb_f, piperr_f)){
	    if(syspipe->outfile){
		free((void *) syspipe->outfile);
		syspipe->outfile = NULL;
	    }

	    zot_pipe(&syspipe);
	}
	else
	  syspipe->exit_code = exit_code;
    }

#else /* !_WINDOWS */

    if((syspipe = (PIPE_S *) malloc(sizeof(PIPE_S))) == NULL)
      return(NULL);

    memset(syspipe, 0, sizeof(PIPE_S));

    syspipe->mode = mode;

    /*
     * If we're not using the shell's command parsing smarts, build
     * argv by hand...
     */
    if(mode & PIPE_NOSHELL){
	char   **ap, *p;
	size_t   n;

	/* parse the arguments into argv */
	for(p = command; *p && isspace((unsigned char)(*p)); p++)
	  ;					/* swallow leading ws */

	if(*p){
	    int l = strlen(p);

	    if((syspipe->args = (char *) malloc((l + 1) * sizeof(char))) != NULL){
		strncpy(syspipe->args, p, l);
		syspipe->args[l] = '\0';
	    }
	    else{
		if(piperr_f)
		  (*piperr_f)(pipe_error_msg("<null>", "execute",
					     "Can't allocate command string"));
		zot_pipe(&syspipe);
		return(NULL);
	    }
	}
	else{
	    if(piperr_f)
	      (*piperr_f)(pipe_error_msg("<null>", "execute",
					 "No command name found"));
	    zot_pipe(&syspipe);
	    return(NULL);
	}

	for(p = syspipe->args, n = 2; *p; p++)	/* count the args */
	  if(isspace((unsigned char)(*p))
	     && *(p+1) && !isspace((unsigned char)(*(p+1))))
	    n++;

	if ((syspipe->argv = ap = (char **)malloc(n * sizeof(char *))) == NULL){
	    zot_pipe(&syspipe);
	    return(NULL);
	}

	memset(syspipe->argv, 0, n * sizeof(char *));

	for(p = syspipe->args; *p; ){		/* collect args */
	    while(*p && isspace((unsigned char)(*p)))
	      *p++ = '\0';

	    *ap++ = (*p) ? p : NULL;
	    while(*p && !isspace((unsigned char)(*p)))
	      p++;
	}

	/* make sure argv[0] exists in $PATH */
	if(can_access_in_path(getenv("PATH"), syspipe->argv[0],
			      EXECUTE_ACCESS) < 0){
	    if(piperr_f)
	      (*piperr_f)(pipe_error_msg(syspipe->argv[0], "access",
					 error_description(errno)));
	    zot_pipe(&syspipe);
	    return(NULL);
	}
    }

    /* fill in any output filenames */
    if(!(mode & PIPE_READ)){
	if(outfile && !*outfile)
	  *outfile = temp_nam(NULL, "pine_p"); /* asked for, but not named? */

	if(errfile && !*errfile)
	  *errfile = temp_nam(NULL, "pine_p"); /* ditto */
    }

    /* create pipes */
    if(mode & (PIPE_WRITE | PIPE_READ)){
	if(mode & PIPE_WRITE){
	    pipe(p);				/* alloc pipe to write child */
	    oparentd = p[STDOUT_FILENO];
	    ichildd  = p[STDIN_FILENO];
	}

	if(mode & PIPE_READ){
	    pipe(p);				/* alloc pipe to read child */
	    iparentd = p[STDIN_FILENO];
	    ochildd  = p[STDOUT_FILENO];
	}
    }

    if(pipecb_f)				/* let caller prep display */
      (*pipecb_f)(syspipe, OSB_PRE_OPEN, NULL);


    if((syspipe->pid = vfork()) == 0){
 	/* reset child's handlers in requested fashion... */
	(void)signal(SIGINT,  (mode & PIPE_PROT) ? SIG_IGN : SIG_DFL);
	(void)signal(SIGQUIT, (mode & PIPE_PROT) ? SIG_IGN : SIG_DFL);
	(void)signal(SIGHUP,  (mode & PIPE_PROT) ? SIG_IGN : SIG_DFL);
#ifdef	SIGCHLD
	(void) signal(SIGCHLD,  SIG_DFL);
#endif

	/* if parent isn't reading, and we have a filename to write */
	if(!(mode & PIPE_READ) && outfile){	/* connect output to file */
	    int output = our_creat(*outfile, 0600);
	    dup2(output, STDOUT_FILENO);
	    if(mode & PIPE_STDERR)
	      dup2(output, STDERR_FILENO);
	    else if(errfile)
	      dup2(our_creat(*errfile, 0600), STDERR_FILENO);
	}

	if(mode & PIPE_WRITE){			/* connect process input */
	    close(oparentd);
	    dup2(ichildd, STDIN_FILENO);	/* tie stdin to pipe */
	    close(ichildd);
	}

	if(mode & PIPE_READ){			/* connect process output */
	    close(iparentd);
	    dup2(ochildd, STDOUT_FILENO);	/* tie std{out,err} to pipe */
	    if(mode & PIPE_STDERR)
	      dup2(ochildd, STDERR_FILENO);
	    else if(errfile)
	      dup2(our_creat(*errfile, 0600), STDERR_FILENO);

	    close(ochildd);
	}

	if(mode & PIPE_NOSHELL){
	    execvp(syspipe->argv[0], syspipe->argv);
	}
	else{
	    if(mode & PIPE_USER){
		char *env, *sh;
		if((env = getenv("SHELL")) && (sh = strrchr(env, '/'))){
		    shell = sh + 1;
		    strncpy(shellpath, env, sizeof(shellpath)-1);
		    shellpath[sizeof(shellpath)-1] = '\0';
		}
		else{
		    shell = "csh";
		    strncpy(shellpath, "/bin/csh", sizeof(shellpath)-1);
		    shellpath[sizeof(shellpath)-1] = '\0';
		}
	    }
	    else{
		shell = "sh";
		strncpy(shellpath, "/bin/sh", sizeof(shellpath)-1);
		shellpath[sizeof(shellpath)-1] = '\0';
	    }

	    execl(shellpath, shell, command ? "-c" : (char *)NULL, fname_to_locale(command), (char *)NULL);
	}

	fprintf(stderr, "Can't exec %s\nReason: %s",
		command, error_description(errno));
	_exit(-1);
    }

    if((child_pid = syspipe->pid) > 0){
	syspipe->isig = signal(SIGINT,  SIG_IGN); /* Reset handlers to make */
	syspipe->qsig = signal(SIGQUIT, SIG_IGN); /* sure we don't come to  */
	syspipe->hsig = signal(SIGHUP,  SIG_IGN); /* a premature end...     */
	if((syspipe->timeout = timeout) != 0){
	    syspipe->alrm      = signal(SIGALRM,  pipe_alarm);
	    syspipe->old_timeo = alarm(timeout);
	}

	if(mode & PIPE_WRITE){
	    close(ichildd);
	    if(mode & PIPE_DESC)
	      syspipe->out.d = oparentd;
	    else
	      syspipe->out.f = fdopen(oparentd, "w");
	}

	if(mode & PIPE_READ){
	    close(ochildd);
	    if(mode & PIPE_DESC)
	      syspipe->in.d = iparentd;
	    else
	      syspipe->in.f = fdopen(iparentd, "r");
	}
    }
    else{
	if(mode & (PIPE_WRITE | PIPE_READ)){
	    if(mode & PIPE_WRITE){
		close(oparentd);
		close(ichildd);
	    }

	    if(mode & PIPE_READ){
		close(iparentd);
		close(ochildd);
	    }
	}

	if(pipecb_f)				/* let caller fixup display */
	  (*pipecb_f)(syspipe, OSB_POST_OPEN, NULL);

	if(outfile && *outfile){
	    our_unlink(*outfile);
	    free((void *) *outfile);
	    *outfile = NULL;
	}

	if(errfile && *errfile){
	    our_unlink(*errfile);
	    free((void *) *errfile);
	    *errfile = NULL;
	}

	if(piperr_f)
	  (*piperr_f)(pipe_error_msg(command, "fork",
				     error_description(errno)));
	zot_pipe(&syspipe);
    }

#endif /* UNIX */

    return(syspipe);
}
Exemplo n.º 4
0
/* ----------------------------------------------------------------------
   Execute the given mailcap command

  Args: cmd           -- the command to execute
	image_file    -- the file the data is in
	needsterminal -- does this command want to take over the terminal?
  ----*/
void
exec_mailcap_cmd(MCAP_CMD_S *mc_cmd, char *image_file, int needsterminal)
{
#ifdef _WINDOWS
    STARTUPINFO		start_info;
    PROCESS_INFORMATION	proc_info;
    WINHAND		childProcess;
    int			success = 0;
    char               *cmd;
    LPTSTR              image_file_lpt = NULL;
    LPTSTR              cmd_lpt = NULL;

    /* no special handling yet, but could be used to replace '*' hack */
    if(mc_cmd)
      cmd = mc_cmd->command;
    else
      return;

    dprint((9, "run_viewer: command=%s\n", cmd ? cmd : "?")) ;

    if(image_file)
      image_file_lpt = utf8_to_lptstr(image_file);

    /* Set to READONLY so the viewer can't try to edit it and keep it around */
    if(image_file_lpt)
      SetFileAttributes(image_file_lpt, FILE_ATTRIBUTE_READONLY);

    if(*cmd == '*' || (*cmd == '\"' && *(cmd+1) == '*')){
	/*
	 * It has been asked that there be the ability to do an 
	 * "Open With..." on attachments like you can from the
	 * Windows file browser.  After looking into this, it
	 * seems that the only way to do this would be through
	 * an undocumented hack.  Here, we would pass "openas" as
	 * the verb to mswin_shell_exec (also some changes in
	 * mswin_shell_exec).  Since this is the delicate world
	 * of attachment handling, it seems right not to rely on
	 * a hack.  The interface wouldn't be too clean anyways,
	 * as we would have to download the attachment only to
	 * display the "Open With..." dialog.  Go figure, some
	 * things Microsoft just wants to keep to themselves.
	 */

    /*
     * 2/1/2007. No idea when the above comment was written, but it is
     *  documented now at least. The below two urls describe the "openas" verb:
     *
     * http://blogs.msdn.com/oldnewthing/archive/2004/11/26/270710.aspx
     * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/
     *      shellcc/platform/shell/programmersguide/shell_basics/
     *      shell_basics_extending/context.asp
     */
	success = mswin_shell_exec(cmd, &childProcess) == 0;
    }
    else{
	memset(&proc_info, 0, sizeof(proc_info));
	memset(&start_info, 0, sizeof(start_info));
	start_info.dwFlags	    = STARTF_FORCEONFEEDBACK;
	start_info.wShowWindow  = SW_SHOWNORMAL;

	if(cmd)
	  cmd_lpt = utf8_to_lptstr(cmd);

	if(CreateProcess(NULL, cmd_lpt, NULL, NULL, FALSE,
			 CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
			 NULL, NULL, &start_info, &proc_info) == TRUE){
	    q_status_message(SM_ORDER, 0, 4, "VIEWER command completed");
	    dprint ((3, "CreatProcess(%s)  Success.\n",
		    cmd ? cmd : "?"));
	    childProcess = proc_info.hProcess;
	    success = 1;
	}

	if(cmd_lpt)
	  fs_give((void **) &cmd_lpt);
    }

    if(!success){
	int rc = (int) GetLastError();
	if(image_file_lpt)
	  SetFileAttributes(image_file_lpt, FILE_ATTRIBUTE_NORMAL);

	our_unlink(image_file);
	q_status_message2(SM_ORDER, 3, 4, "\007Can't start viewer. %s%s.",
			  (rc == 2 || rc == 3) ? "Viewer not found:  " :
			  (rc == 8) ? "Not enough memory" : "Windows error ",
			  (rc == 2 || rc == 3) ? cmd :
			  (rc == 8) ? "" : int2string(rc));
    }

    if(image_file_lpt)
      fs_give((void **) &image_file_lpt);

#elif	OSX_TARGET

    char   *command = NULL,
	   *result_file = NULL,
	   *p;
    char  **r_file_h;
    PIPE_S *syspipe;
    int     mode;

    if(!mc_cmd)
      return;
    if(mc_cmd->special_handling){
	char *rhost;

	if(mime_os_specific_access())
	  osx_launch_special_handling(mc_cmd, image_file);
	else{
	  q_status_message(SM_ORDER, 0, 4, "VIEWER command cancelled");
	  our_unlink(image_file);
	}
    }
    else {
	char *cmd = mc_cmd->command;
	size_t l;

	l = 32 + strlen(cmd) + (2*strlen(image_file));
	p = command = (char *) fs_get((l+1) * sizeof(char));
	if(!needsterminal)  /* put in background if it doesn't need terminal */
	  *p++ = '(';

	snprintf(p, l+1-(p-command), "%s", cmd);
	p += strlen(p);
	if(!needsterminal){
	    if(p-command+2 < l+1){
		*p++ = ')';
		*p++ = ' ';
		*p++ = '&';
	    }
	}

	if(p-command < l+1)
	  *p++ = '\n';

	if(p-command < l+1)
	  *p   = '\0';

	dprint((9, "exec_mailcap_cmd: command=%s\n",
		   command ? command : "?"));

	mode = PIPE_RESET;
	if(needsterminal == 1)
	  r_file_h = NULL;
	else{
	    mode       |= PIPE_WRITE | PIPE_STDERR;
	    result_file = temp_nam(NULL, "pine_cmd");
	    r_file_h    = &result_file;
	}

	if(syspipe = open_system_pipe(command, r_file_h, NULL, mode, 0, pipe_callback, NULL)){
	    close_system_pipe(&syspipe, NULL, pipe_callback);
	    if(needsterminal == 1)
	      q_status_message(SM_ORDER, 0, 4, "VIEWER command completed");
	    else if(needsterminal == 2)
	      display_output_file(result_file, "VIEWER", " command result", 1);
	    else
	      display_output_file(result_file, "VIEWER", " command launched", 1);
	}
	else
	  q_status_message1(SM_ORDER, 3, 4, "Cannot spawn command : %s", cmd);

	fs_give((void **)&command);
	if(result_file)
	  fs_give((void **)&result_file);
    }
#else
    char   *command = NULL,
	   *result_file = NULL,
	   *p, *cmd, *q, *psef;
    char  **r_file_h;
    PIPE_S *syspipe;
    int     mode;
    size_t  l;

    /* no os-specific command handling */
    if(mc_cmd)
      cmd = mc_cmd->command;
    else
      return;

#ifdef PSEFCMD
    psef = fs_get((60 + strlen(PSEFCMD) + strlen(image_file))*sizeof(char));
    sprintf(psef, "PSEF=`%s | /bin/grep \"%s\" | /bin/grep -v grep`", PSEFCMD, image_file);

    q = fs_get((80 + 2*strlen(psef))*sizeof(char)); /* bigger than 62 */
    sprintf(q, "/bin/sh -c '(%s; while test -n \"$PSEF\" ; do %s ; sleep %d ; done)' ;", psef, psef, ps_global->sleep);
    fs_give((void **) &psef);
#else
    q = cpystr("");
#endif /* PSEFCMD */

    l = 32 + strlen(cmd) + 2*strlen(image_file) + strlen(q);
    p = command = (char *)fs_get((l+1) * sizeof(char));
    if(!needsterminal)  /* put in background if it doesn't need terminal */
      *p++ = '(';
    snprintf(p, l+1-(p-command), "%s ; %s rm -f %s", cmd, q, image_file);
    fs_give((void **)&q);
    command[l] = '\0';
    p += strlen(p);
    if(!needsterminal && (p-command)+5 < l){
	*p++ = ')';
	*p++ = ' ';
	*p++ = '&';
    }

    *p++ = '\n';
    *p   = '\0';

    dprint((9, "exec_mailcap_cmd: command=%s\n",
	   command ? command : "?"));

    mode = PIPE_RESET;
    if(needsterminal == 1)
      r_file_h = NULL;
    else{
	mode       |= PIPE_WRITE | PIPE_STDERR;
	result_file = temp_nam(NULL, "pine_cmd");
	r_file_h    = &result_file;
    }

    if((syspipe = open_system_pipe(command, r_file_h, NULL, mode, 0, pipe_callback, NULL)) != NULL){
	close_system_pipe(&syspipe, NULL, pipe_callback);
	if(needsterminal == 1)
	  q_status_message(SM_ORDER, 0, 4, "VIEWER command completed");
	else if(needsterminal == 2)
	  display_output_file(result_file, "VIEWER", " command result", 1);
	else
	  display_output_file(result_file, "VIEWER", " command launched", 1);
    }
    else
      q_status_message1(SM_ORDER, 3, 4, "Cannot spawn command : %s", cmd);

    fs_give((void **)&command);

    if(result_file)
      fs_give((void **)&result_file);
#endif
}
Exemplo n.º 5
0
Arquivo: print.c Projeto: nysan/alpine
/*----------------------------------------------------------------------
       Open the printer

  Args: desc -- Description of item to print. Should have one trailing blank.

  Return value: < 0 is a failure.
		0 a success.

This does most of the work of popen so we can save the standard output of the
command we execute and send it back to the user.
  ----*/
int
open_printer(char *desc)
{
#ifndef _WINDOWS
    char command[201], prompt[200];
    int  cmd, rc, just_one;
    char *p, *init, *nick;
    char aname[100], wname[100];
    char *printer;
    int	 done = 0, i, lastprinter, cur_printer = 0;
    HelpType help;
    char   **list;
    static ESCKEY_S ekey[] = {
	/* TRANSLATORS: these are command labels for printing screen */
	{'y', 'y', "Y", N_("Yes")},
	{'n', 'n', "N", N_("No")},
	/* TRANSLATORS: go to Previous Printer in list */
	{ctrl('P'), 10, "^P", N_("Prev Printer")},
	{ctrl('N'), 11, "^N", N_("Next Printer")},
	{-2,   0,   NULL, NULL},
	/* TRANSLATORS: use Custom Print command */
	{'c', 'c', "C", N_("CustomPrint")},
	{KEY_UP,    10, "", ""},
	{KEY_DOWN,  11, "", ""},
	{-1, 0, NULL, NULL}};
#define PREV_KEY   2
#define NEXT_KEY   3
#define CUSTOM_KEY 5
#define UP_KEY     6
#define DOWN_KEY   7

    trailer      = NULL;
    init         = NULL;
    nick         = NULL;
    command[sizeof(command)-1] = '\0';

    if(ps_global->VAR_PRINTER == NULL){
        q_status_message(SM_ORDER | SM_DING, 3, 5,
	"No printer has been chosen.  Use SETUP on main menu to make choice.");
	return(-1);
    }

    /* Is there just one print command available? */
    just_one = (ps_global->printer_category!=3&&ps_global->printer_category!=2)
	       || (ps_global->printer_category == 2
		   && !(ps_global->VAR_STANDARD_PRINTER
			&& ps_global->VAR_STANDARD_PRINTER[0]
			&& ps_global->VAR_STANDARD_PRINTER[1]))
	       || (ps_global->printer_category == 3
		   && !(ps_global->VAR_PERSONAL_PRINT_COMMAND
			&& ps_global->VAR_PERSONAL_PRINT_COMMAND[0]
			&& ps_global->VAR_PERSONAL_PRINT_COMMAND[1]));

    if(F_ON(F_CUSTOM_PRINT, ps_global))
      ekey[CUSTOM_KEY].ch = 'c'; /* turn this key on */
    else
      ekey[CUSTOM_KEY].ch = -2;  /* turn this key off */

    if(just_one){
	ekey[PREV_KEY].ch = -2;  /* turn these keys off */
	ekey[NEXT_KEY].ch = -2;
	ekey[UP_KEY].ch   = -2;
	ekey[DOWN_KEY].ch = -2;
    }
    else{
	ekey[PREV_KEY].ch = ctrl('P'); /* turn these keys on */
	ekey[NEXT_KEY].ch = ctrl('N');
	ekey[UP_KEY].ch   = KEY_UP;
	ekey[DOWN_KEY].ch = KEY_DOWN;
	/*
	 * count how many printers in list and find the default in the list
	 */
	if(ps_global->printer_category == 2)
	  list = ps_global->VAR_STANDARD_PRINTER;
	else
	  list = ps_global->VAR_PERSONAL_PRINT_COMMAND;

	for(i = 0; list[i]; i++)
	  if(strcmp(ps_global->VAR_PRINTER, list[i]) == 0)
	    cur_printer = i;
	
	lastprinter = i - 1;
    }

    help = NO_HELP;
    ps_global->mangled_footer = 1;

    while(!done){
	if(init)
	  fs_give((void **)&init);

	if(trailer)
	  fs_give((void **)&trailer);

	if(just_one)
	  printer = ps_global->VAR_PRINTER;
	else
	  printer = list[cur_printer];

	parse_printer(printer, &nick, &p, &init, &trailer, NULL, NULL);
	strncpy(command, p, sizeof(command)-1);
	command[sizeof(command)-1] = '\0';
	fs_give((void **)&p);
	/* TRANSLATORS: Print something1 using something2.
	   For example, Print configuration using printer three. */
	snprintf(prompt, sizeof(prompt), _("Print %s using \"%s\" ? "),
		desc ? desc : "",
		*nick ? nick : command);
	prompt[sizeof(prompt)-1] = '\0';

	fs_give((void **)&nick);
	
	cmd = radio_buttons(prompt, -FOOTER_ROWS(ps_global),
				 ekey, 'y', 'x', help, RB_NORM);
	
	switch(cmd){
	  case 'y':
	    q_status_message1(SM_ORDER, 0, 9,
		"Printing with command \"%s\"", command);
	    done++;
	    break;

	  case 10:
	    cur_printer = (cur_printer>0)
				? (cur_printer-1)
				: lastprinter;
	    break;

	  case 11:
	    cur_printer = (cur_printer<lastprinter)
				? (cur_printer+1)
				: 0;
	    break;

	  case 'n':
	  case 'x':
	    done++;
	    break;

	  case 'c':
	    done++;
	    break;

	  default:
	    break;
	}
    }

    if(cmd == 'c'){
	if(init)
	  fs_give((void **)&init);

	if(trailer)
	  fs_give((void **)&trailer);

	snprintf(prompt, sizeof(prompt), "Enter custom command : ");
	prompt[sizeof(prompt)-1] = '\0';
	command[0] = '\0';
	rc = 1;
	help = NO_HELP;
	while(rc){
	    int flags = OE_APPEND_CURRENT;

	    rc = optionally_enter(command, -FOOTER_ROWS(ps_global), 0,
		sizeof(command), prompt, NULL, help, &flags);
	    
	    if(rc == 1){
		cmd = 'x';
		rc = 0;
	    }
	    else if(rc == 3)
	      help = (help == NO_HELP) ? h_custom_print : NO_HELP;
	    else if(rc == 0){
		removing_trailing_white_space(command);
		removing_leading_white_space(command);
		q_status_message1(SM_ORDER, 0, 9,
		    "Printing with command \"%s\"", command);
	    }
	}
    }

    if(cmd == 'x' || cmd == 'n'){
	q_status_message(SM_ORDER, 0, 2, "Print cancelled");
	if(init)
	  fs_give((void **)&init);

	if(trailer)
	  fs_give((void **)&trailer);

	return(-1);
    }

    display_message('x');

    ps_global->print = (PRINT_S *)fs_get(sizeof(PRINT_S));
    memset(ps_global->print, 0, sizeof(PRINT_S));

    strncpy(aname, ANSI_PRINTER, sizeof(aname)-1);
    aname[sizeof(aname)-1] = '\0';
    strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
    strncpy(wname, WYSE_PRINTER, sizeof(wname)-1);
    wname[sizeof(wname)-1] = '\0';
    strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
    if(strucmp(command, ANSI_PRINTER) == 0
       || strucmp(command, aname) == 0
       || strucmp(command, WYSE_PRINTER) == 0
       || strucmp(command, wname) == 0){
        /*----------- Attached printer ---------*/
        q_status_message(SM_ORDER, 0, 9,
	    "Printing to attached desktop printer...");
        display_message('x');
	xonxoff_proc(1);			/* make sure XON/XOFF used */
	crlf_proc(1);				/* AND LF->CR xlation */
	if(strucmp(command, ANSI_PRINTER) == 0
	   || strucmp(command, aname) == 0){
	    fputs("\033[5i", stdout);
	    ansi_off = 1;
	}
	else{
	    ansi_off = 0;
	    printf("%c", 18); /* aux on for wyse60,
			         Chuck Everett <*****@*****.**> */
	}

        ps_global->print->fp = stdout;
        if(strucmp(command, ANSI_PRINTER) == 0
	   || strucmp(command, WYSE_PRINTER) == 0){
	    /* put formfeed at the end of the trailer string */
	    if(trailer){
		int len = strlen(trailer);

		fs_resize((void **)&trailer, len+2);
		trailer[len] = '\f';
		trailer[len+1] = '\0';
	    }
	    else
	      trailer = cpystr("\f");
	}
    }
    else{
        /*----------- Print by forking off a UNIX command ------------*/
        dprint((4, "Printing using command \"%s\"\n",
	       command ? command : "?"));
	ps_global->print->result = temp_nam(NULL, "pine_prt");
	if(ps_global->print->result &&
	   (ps_global->print->pipe = open_system_pipe(command,
						      &ps_global->print->result, NULL,
						      PIPE_WRITE | PIPE_STDERR, 0,
						      pipe_callback, NULL))){
	    ps_global->print->fp = ps_global->print->pipe->out.f;
	}
	else{
	    if(ps_global->print->result){
		our_unlink(ps_global->print->result);
		fs_give((void **)&ps_global->print->result);
	    }

            q_status_message1(SM_ORDER | SM_DING, 3, 4,
			      "Error opening printer: %s",
                              error_description(errno));
            dprint((2, "Error popening printer \"%s\"\n",
                      error_description(errno)));
	    if(init)
	      fs_give((void **)&init);

	    if(trailer)
	      fs_give((void **)&trailer);
	    
	    return(-1);
        }
    }

    ps_global->print->err = 0;
    if(init){
	if(*init)
	  fputs(init, ps_global->print->fp);

	fs_give((void **)&init);
    }

    cb.cbuf[0] = '\0';
    cb.cbufp   = cb.cbuf;
    cb.cbufend = cb.cbuf;
#else /* _WINDOWS */
    int status;
    LPTSTR desclpt = NULL;

    if(desc)
      desclpt = utf8_to_lptstr(desc);

    if (status = mswin_print_ready (0, desclpt)) {
        q_status_message1(SM_ORDER | SM_DING, 3, 4,
			  "Error starting print job: %s",
			  mswin_print_error(status));
	if(desclpt)
	  fs_give((void **) &desclpt);

        return(-1);
    }

    if(desclpt)
      fs_give((void **) &desclpt);

    q_status_message(SM_ORDER, 0, 9, "Printing to windows printer...");
    display_message('x');

    /* init print control structure */
    ps_global->print = (PRINT_S *)fs_get(sizeof(PRINT_S));
    memset(ps_global->print, 0, sizeof(PRINT_S));

    ps_global->print->err = 0;
#endif /* _WINDOWS */

    return(0);
}
Exemplo n.º 6
0
/*
 * expand_filter_tokens - return an alloc'd string with any special tokens
 *			  in the given filter expanded, NULL otherwise.
 */
char *
expand_filter_tokens(char *filter, ENVELOPE *env, char **tmpf, char **resultf,
		     char **mtypef, int *key, int *hdrs, int *silent)
{
    char   **array, **q;
    char    *bp, *cmd = NULL, *p = NULL,
	    *tfn = NULL, *rfn = NULL, *dfn = NULL, *mfn = NULL,
	    *freeme_tfn = NULL, *freeme_rfn = NULL, *freeme_mfn = NULL;
    int      n = 0;
    size_t   len;

    /*
     * break filter into words delimited by whitespace so that we can
     * look for tokens. First we count how many words.
     */
    if((bp = cpystr(filter)) != NULL)
      p = strtok(bp, " \t");
    
    if(p){
	n++;
	while(strtok(NULL, " \t") != NULL)
	  n++;
    }

    if(!n){
	dprint((1, "Unexpected failure creating sending_filter\n"));
	if(bp)
	  fs_give((void **)&bp);

	return(cmd);
    }

    q = array = (char **) fs_get((n+1) * sizeof(*array));
    memset(array, 0, (n+1) * sizeof(*array));
    /* restore bp and form the array */
    strncpy(bp, filter, strlen(filter)+1);
    if((p = strtok(bp, " \t")) != NULL){
	if(q-array < n+1)
	  *q++ = cpystr(p);

	while((p = strtok(NULL, " \t")) != NULL && (q-array < n+1))
	  *q++ = cpystr(p);
    }

    if(bp)
      fs_give((void **)&bp);

    for(q = array; *q != NULL; q++){
	if(!strcmp(*q, "_RECIPIENTS_")){
	    char *rl = NULL;

	    if(env){
		size_t l;

		char *to_l = addr_list_string(env->to,
					      simple_addr_string, 0),
		     *cc_l = addr_list_string(env->cc,
					      simple_addr_string, 0),
		     *bcc_l = addr_list_string(env->bcc,
					       simple_addr_string, 0);

		l = strlen(to_l) + strlen(cc_l) + strlen(bcc_l) + 2;
		rl = (char *) fs_get((l+1) * sizeof(char));
		snprintf(rl, l+1, "%s %s %s", to_l, cc_l, bcc_l);
		fs_give((void **)&to_l);
		fs_give((void **)&cc_l);
		fs_give((void **)&bcc_l);
		for(to_l = rl; *to_l; to_l++)	/* to_l overloaded! */
		  if(*to_l == ',')			/* space delim'd list */
		    *to_l = ' ';
	    }

	    fs_give((void **)q);
	    *q = rl ? rl : cpystr("");
	}
	else if(!strcmp(*q, "_TMPFILE_")){
	    if(!tfn){
		tfn = temp_nam(NULL, "sf"); 	/* send filter file */
		if(!tfn)
		  dprint((1, "FAILED creat of _TMPFILE_\n"));
	    }

	    if(tmpf)
	      *tmpf = tfn;
	    else
	      freeme_tfn = tfn;

	    fs_give((void **)q);
	    *q = cpystr(tfn ? tfn : "");
	}
	else if(!strcmp(*q, "_RESULTFILE_")){
	    if(!rfn){
		rfn = temp_nam(NULL, "rf");
		/*
		 * We don't create the result file, the user does.
		 * That means we have to remove it after temp_nam creates it.
		 */
		if(rfn)
		  our_unlink(rfn);
		else
		  dprint((1, "FAILED creat of _RESULTFILE_\n"));
	    }

	    if(resultf)
	      *resultf = rfn;
	    else
	      freeme_rfn = rfn;

	    fs_give((void **)q);
	    *q = cpystr(rfn ? rfn : "");
	}
	else if(!strcmp(*q, "_MIMETYPE_")){
	    if(!mfn){
		mfn = temp_nam(NULL, "mt");
		/*
		 * We don't create the mimetype file, the user does.
		 * That means we have to remove it after temp_nam creates it.
		 */
		if(mfn)
		  our_unlink(mfn);
		else
		  dprint((1, "FAILED creat of _MIMETYPE_\n"));
	    }

	    if(mtypef)
	      *mtypef = mfn;
	    else
	      freeme_mfn = mfn;

	    fs_give((void **)q);
	    *q = cpystr(mfn ? mfn : "");
	}
	else if(!strcmp(*q, "_DATAFILE_")){
	    if((dfn = filter_data_file(1)) == NULL)	/* filter data file */
	      dprint((1, "FAILED creat of _DATAFILE_\n"));

	    fs_give((void **)q);
	    *q = cpystr(dfn ? dfn : "");
	}
	else if(!strcmp(*q, "_PREPENDKEY_")){
	    (*q)[0] = '\0';
	    if(key)
	      *key = 1;
	}
	else if(!strcmp(*q, "_INCLUDEALLHDRS_")){
	    (*q)[0] = '\0';
	    if(hdrs)
	      *hdrs = 1;
	}
	else if(!strcmp(*q, "_SILENT_")){
	    (*q)[0] = '\0';
	    if(silent)
	      *silent = 1;
	}
    }

    /* count up required length */
    for(len = 0, q = array; *q != NULL; q++)
      len += (strlen(*q)+1);
    
    cmd = fs_get((len+1) * sizeof(char));
    cmd[len] = '\0';

    /* cat together all the args */
    p = cmd;
    for(q = array; *q != NULL; q++){
	sstrncpy(&p, *q, len+1-(p-cmd));
	sstrncpy(&p, " ", len+1-(p-cmd));
    }

    cmd[len] = '\0';

    if(freeme_rfn)
      fs_give((void **) &freeme_rfn);

    if(freeme_tfn){			/* this shouldn't happen */
	our_unlink(freeme_tfn);
	fs_give((void **) &freeme_tfn);
    }

    if(freeme_mfn)
      fs_give((void **) &freeme_mfn);
    
    free_list_array(&array);

    return(cmd);
}