~ubuntu-branches/ubuntu/trusty/bluefish/trusty

« back to all changes in this revision

Viewing changes to src/external_commands.c

  • Committer: Package Import Robot
  • Author(s): Daniel Leidert
  • Date: 2012-06-27 22:28:39 UTC
  • mfrom: (1.2.9)
  • Revision ID: package-import@ubuntu.com-20120627222839-5g0f5s6gpaezfhve
Tags: 2.2.3-1
* New upstream release.
* debian/control: Dropped DM-Upload-Allowed.
  (Maintainer): Set to my new address.
  (Suggests): Calculate browsers depending on distribution.
  (Depends): Added python depends for newly shipped Python scripts.
* debian/copyright: Minor update. Link to GPLv2 text.
* debian/rules: Enabled hardening. Added python2 module. Calculate brwoser
  dependencies via dpkg-vendor.
* debian/patches/LP810663_blacklist_from_appmenu.patch: Adjusted.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include "document.h"
29
29
#include "gtk_easy.h"
30
30
#include "outputbox.h"
 
31
#include "dialog_utils.h"
 
32
#include "external_commands.h"
31
33
 
32
34
#ifndef WIN32
33
35
#define USEBINSH
50
52
        gint end; /* -1 for end of the file */
51
53
        const gchar *formatstring; /* the command from the configuration, so including placeholders such as %i, %f, |,  etc. */
52
54
        gchar *commandstring; /* the command that will be started by g_spawn, the placeholders should have been replaced/removed */
 
55
        CustomCommandCallback customcommand_cb;
53
56
 
54
 
        gchar *securedir; /* if we need any local temporary files for input or output we'll use fifo's */
55
 
        gchar *fifo_in; /* the path for the iput and output fifo */
56
 
        gchar *fifo_out;
 
57
        gchar *securedir; /* if we need any local temporary files for input or output */
57
58
        gchar *tmp_in; /* the path for the input/output temporary filename */
58
59
        gchar *tmp_out;
59
60
        gchar *inplace; /* if we use in-place editing, so the input file will become the output file */
60
61
        gboolean pipe_in; /* if we use pipes for input and output */
61
62
        gboolean pipe_out;
62
63
 
63
 
#ifdef WIN32
64
 
        gpointer fifo_in_handle; /* the path for 'named pipes' on win32 */
65
 
        gpointer fifo_out_handle;
66
 
#endif
67
 
 
68
64
        gboolean include_stderr; /* if stderr should be included in the output */
69
65
        
70
66
        gint standard_input; /* the pipes that will be filled by g_spawn_async_with_pipes */
90
86
        if (ep->refcount <= 0) {
91
87
                DEBUG_MSG("externalp_unref, cleanup!\n");
92
88
                if (ep->commandstring) g_free(ep->commandstring);
93
 
                if (ep->fifo_in) {
94
 
                        #ifdef WIN32
95
 
                                CloseHandle(ep->fifo_in_handle);
96
 
                                g_free(ep->fifo_in_handle);
97
 
                        #else
98
 
                                unlink(ep->fifo_in);
99
 
                        #endif
100
 
                        g_free(ep->fifo_in);
101
 
                }
102
 
                if (ep->fifo_out) {
103
 
                        #ifdef WIN32
104
 
                                CloseHandle(ep->fifo_out_handle);
105
 
                                g_free(ep->fifo_out_handle);
106
 
                        #else
107
 
                                unlink(ep->fifo_out);
108
 
                        #endif
109
 
                        g_free(ep->fifo_out);
110
 
                }
111
89
                if (ep->tmp_in) {
112
90
                        unlink(ep->tmp_in);
113
91
                        g_free(ep->tmp_in);
183
161
        GError *gerror=NULL;
184
162
        DEBUG_MSG("child_watch_lcb, child exited with status=%d\n",status);
185
163
        
186
 
        if ((ep->pipe_in || ep->fifo_in) && !ep->buffer_out) {
 
164
        if (ep->pipe_in && !ep->buffer_out) {
187
165
                /* the child has exited before we actually started to write data to the child, just abort now */
188
166
                g_source_remove(ep->start_command_idle_id);
189
167
                externalp_unref(ep); /* unref twice, once for the start_command_idle, once for child_watch_lcb */
222
200
start_command_idle(gpointer data)
223
201
{
224
202
        Texternalp *ep = data;
225
 
        GError *gerror=NULL;
226
 
 
227
203
        if (ep->pipe_in) {
228
204
                DEBUG_MSG("start_command_idle, creating channel_in from pipe\n");
229
205
#ifdef WIN32
231
207
#else
232
208
                ep->channel_in = g_io_channel_unix_new(ep->standard_input);
233
209
#endif
234
 
        } else if (ep->fifo_in) {
235
 
                DEBUG_MSG("start_command_idle, connecting channel_in to fifo %s\n",ep->fifo_in);
236
 
                /* problem: this can hang if there is no process actually reading from this fifo... so if the 
237
 
                command died in some way (a nonexisting command), this call will hang bluefish */
238
 
                ep->channel_in = g_io_channel_new_file(ep->fifo_in,"w",&gerror);
239
 
                if (gerror) {
240
 
                        DEBUG_MSG("start_command_idle, error connecting to fifo %s: %s\n",ep->fifo_in,gerror->message);
241
 
                        g_warning("failed to create fifo %s %d: %s\n",ep->fifo_in, gerror->code, gerror->message);
242
 
                        g_error_free(gerror);
243
 
                        /* BUG TODO: free Texternalp */
244
 
                        return FALSE;
245
 
                }
246
210
        }
247
 
        if (ep->pipe_in || ep->fifo_in) {
 
211
        if (ep->pipe_in) {
248
212
                ep->refcount++;
249
213
                ep->buffer_out = ep->buffer_out_position = doc_get_chars(ep->bfwin->current_document,ep->begin,ep->end);
250
214
                g_io_channel_set_flags(ep->channel_in,G_IO_FLAG_NONBLOCK,NULL);
259
223
                ep->channel_out = g_io_channel_unix_new(ep->standard_output);
260
224
#endif
261
225
                DEBUG_MSG("start_command_idle, created channel_out from pipe\n");
262
 
        } else if (ep->fifo_out) {
263
 
                ep->channel_out = g_io_channel_new_file(ep->fifo_out,"r",&gerror);
264
 
                DEBUG_MSG("start_command_idle, created channel_out from fifo %s\n",ep->fifo_out);
265
 
                if (gerror) {
266
 
                        g_warning("failed to start reading from file %s %d: %s\n",ep->fifo_out, gerror->code, gerror->message);
267
 
                        g_error_free(gerror);
268
 
                        /* BUG TODO: free Texternalp */
269
 
                        return FALSE;
270
 
                }
271
226
        }
272
 
        if (ep->channel_out_lcb && (ep->pipe_out || ep->fifo_out)) {
 
227
        if (ep->channel_out_lcb && ep->pipe_out) {
273
228
                ep->refcount++;
274
229
                g_io_channel_set_flags(ep->channel_out,G_IO_FLAG_NONBLOCK,NULL);
275
230
                DEBUG_MSG("start_command_idle, add watch for channel_out\n");
277
232
        }
278
233
        externalp_unref(ep);
279
234
        
280
 
        
281
235
        return FALSE; /* don't call me again */
282
236
}
283
237
 
301
255
    g_shell_parse_argv(ep->commandstring, NULL, &argv, NULL);
302
256
#endif
303
257
        DEBUG_MSG("start_command_backend,commandstring=%s\n",ep->commandstring);
304
 
#ifdef WIN32
305
258
        ep->include_stderr = FALSE;
306
 
        if (ep->fifo_in) {
307
 
                ep->fifo_in = g_strdup("\\\\.\\pipe\\bluefish_in");
308
 
                if ((ep->fifo_in_handle = CreateNamedPipe(ep->fifo_in, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_NOWAIT, 
309
 
                         PIPE_UNLIMITED_INSTANCES, 2048, 2048, 100, NULL)) == INVALID_HANDLE_VALUE) {
310
 
                        g_print("some error happened creating fifo %s??\n", ep->fifo_in);
311
 
                        return;
312
 
                }
313
 
        }
314
 
        if (ep->fifo_out) {
315
 
                ep->fifo_out = g_strdup("\\\\.\\pipe\\bluefish_out");
316
 
                if ((ep->fifo_out_handle = CreateNamedPipe(ep->fifo_out, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE | PIPE_NOWAIT, 
317
 
                         PIPE_UNLIMITED_INSTANCES, 2048, 2048, 100, NULL)) == INVALID_HANDLE_VALUE) {
318
 
                        g_print("some error happened creating fifo %s??\n", ep->fifo_out);
319
 
                        return;
320
 
                }
321
 
        }
322
 
#else
323
 
        if (ep->fifo_in) {
324
 
                if (mkfifo(ep->fifo_in, 0600) != 0) {
325
 
                        DEBUG_MSG("some error happened creating fifo %s??\n",ep->fifo_in);
326
 
                        return;
327
 
                }
328
 
                DEBUG_MSG("start_command_backend, created fifo %s\n",ep->fifo_in);
329
 
        }
330
 
        if (ep->fifo_out) {
331
 
                if (mkfifo(ep->fifo_out, 0600) != 0) {
332
 
                        DEBUG_MSG("some error happened creating fifo %s??\n",ep->fifo_out);
333
 
                        return;
334
 
                }
335
 
        }
336
 
#endif
337
 
        DEBUG_MSG("start_command_backend, pipe_in=%d, pipe_out=%d, fifo_in=%s, fifo_out=%s,include_stderr=%d\n",ep->pipe_in,ep->pipe_out,ep->fifo_in,ep->fifo_out,ep->include_stderr);
 
259
        DEBUG_MSG("start_command_backend, pipe_in=%d, pipe_out=%d, include_stderr=%d\n",ep->pipe_in,ep->pipe_out,ep->include_stderr);
338
260
        DEBUG_MSG("start_command_backend, about to spawn process /bin/sh -c %s\n",argv[2]);
339
261
        g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, (ep->include_stderr)?spawn_setup_lcb:NULL, ep, &ep->child_pid, 
340
262
                                (ep->pipe_in) ? &ep->standard_input : NULL,
383
305
384
306
 
385
307
/* The format string should have new options:
386
 
    * %flocal full path (function should abort for remote files)
 
308
    * %f local full path (function should abort for remote files)
387
309
    * %c local directory of file (function should abort for remote files)
388
310
    * %n filename without path
389
311
    * %u URL
390
312
    * %p preview URL if basedir and preview dir are set in project settings, else identical to %u
391
 
    * %i temporary fifo for input, if the document is not modified and local equal to %f
392
 
    * %o temporary fifo for output of filters or outputbox
393
 
    * %I temporary filename for input (fifo is faster), if the document is not modified and local equal to %f
394
 
    * %O temporary filename for output of filters or outputbox (fifo is faster) (previously %f)
 
313
    * %i temporary filename for input (fifo is faster), if the document is not modified and local equal to %f
 
314
    * %o temporary filename for output of filters or outputbox (fifo is faster) (previously %f)
395
315
    * %t temporary filename for both input and output (for in-place-editing filters)
 
316
    * %a user supplied arguments
396
317
*/
397
318
static gchar *create_commandstring(Texternalp *ep, const gchar *formatstr, gboolean discard_output) {
398
319
        Tconvert_table *table;
399
320
        gchar *localname=NULL, *localfilename=NULL, *retstring, *curi=NULL;
400
 
        gchar *formatstring;
 
321
        gchar *formatstring, *user_argument=NULL;
401
322
        gint formatstringlen;
402
323
        gboolean is_local_non_modified;
403
324
        gboolean need_local = FALSE,
405
326
                need_pipeout = FALSE,
406
327
                need_tmpin = FALSE,
407
328
                need_tmpout = FALSE,
408
 
                need_fifoin = FALSE,
409
 
                need_fifoout = FALSE,
410
329
                need_inplace = FALSE,
411
330
                need_preview_uri = FALSE,
412
 
                need_filename=FALSE;
 
331
                need_filename=FALSE,
 
332
                need_arguments=FALSE;
413
333
        gint items = 2, cur=0;
414
334
        
415
335
        if (!ep->bfwin->current_document) {
428
348
                need_pipeout = TRUE;
429
349
                formatstring[formatstringlen-1]=' ';
430
350
        }
431
 
        
 
351
        need_arguments = (strstr(formatstring, "%a") != NULL);
432
352
        need_filename = need_local = (strstr(formatstring, "%c") != NULL || strstr(formatstring, "%f") != NULL);
433
353
        need_preview_uri = (strstr(formatstring, "%p") != NULL);
434
354
        if (!need_filename) { /* local already implies we need a filename */
446
366
        if (need_local && !localname) {
447
367
                g_free(formatstring);
448
368
                g_free(localname);
449
 
 
450
369
                return NULL;
451
370
        }
452
371
 
453
372
        need_tmpin = (strstr(formatstring, "%I") != NULL);
454
373
        /* %f is for backwards compatibility with bluefish 1.0 */
455
374
        need_tmpout = (strstr(formatstring, "%O") != NULL);
456
 
        need_fifoin = (strstr(formatstring, "%i") != NULL);
457
 
        need_fifoout = (strstr(formatstring, "%o") != NULL);
458
375
        need_inplace = (strstr(formatstring, "%t") != NULL);
459
376
        
460
 
        if ((need_tmpout || need_fifoout || need_inplace || need_pipeout) && discard_output) {
 
377
        if ((need_tmpout || need_inplace || need_pipeout) && discard_output) {
461
378
                DEBUG_MSG("create_commandstring, external_commands should not have %%o\n");
462
 
                /*  BUG: give a warning that external commands should not use %o */
463
379
                g_free(formatstring);
464
380
                g_free(localname);
465
 
 
466
381
                return NULL;
467
382
        }
468
 
        if ((need_tmpin && (need_fifoin || need_inplace || need_pipein)) 
469
 
                        || (need_fifoin && (need_inplace || need_pipein))
 
383
        if ((need_tmpin && (need_inplace || need_pipein)) 
470
384
                        || (need_inplace && need_pipein)) {
471
385
                DEBUG_MSG("create_commandstring, cannot have multiple inputs\n");
472
386
                /*  BUG: give a warning that you cannot have multiple inputs */
473
387
                g_free(formatstring);
474
388
                g_free(localname);
475
 
 
476
389
                return NULL;
477
390
        }
478
 
        if ((need_tmpout && (need_fifoout || need_inplace || need_pipeout)) 
479
 
                        || (need_fifoout && (need_inplace || need_pipeout))
 
391
        if ((need_tmpout && (need_inplace || need_pipeout)) 
480
392
                        || (need_inplace && need_pipeout)) {
481
 
                DEBUG_MSG("create_commandstring, cannot have multiple outputs\n");
 
393
                DEBUG_MSG("create_commandstring, cannot have multiple outputs, tmpout=%d, pipeout=%d, inplace=%d\n",need_tmpout,need_pipeout,need_inplace);
482
394
                /*  BUG: give a warning that you cannot have multiple outputs */
483
395
                g_free(formatstring);
484
396
                g_free(localname);
485
397
 
486
398
                return NULL;
487
399
        }
 
400
        
 
401
        if (need_arguments) {
 
402
                GtkWidget *dialog, *entry;
 
403
                gchar *tmp;
 
404
                gint result;
 
405
                dialog = gtk_dialog_new_with_buttons(_("Supply extra arguments"),
 
406
                                                                                          GTK_WINDOW(ep->bfwin->main_window),
 
407
                                                                                          GTK_DIALOG_DESTROY_WITH_PARENT,
 
408
                                                                                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
409
                                                                                          GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
 
410
                tmp = g_strdup_printf(_("Supply arguments to define %%a in '%s'"), formatstring);
 
411
                entry = dialog_entry_labeled(NULL, tmp, gtk_dialog_get_content_area(GTK_DIALOG(dialog)), 6);
 
412
                g_free(tmp);
 
413
                gtk_widget_show_all(dialog);
 
414
                result = gtk_dialog_run(GTK_DIALOG (dialog));
 
415
                switch (result) {
 
416
                case GTK_RESPONSE_ACCEPT:
 
417
                        user_argument = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
 
418
                        if (!user_argument || user_argument[0]=='\0') {
 
419
                                need_arguments = FALSE;
 
420
                        }
 
421
                break;
 
422
                default:
 
423
                        gtk_widget_destroy(dialog);
 
424
                        return NULL;
 
425
                break;
 
426
                }
 
427
                gtk_widget_destroy(dialog);
 
428
        }
 
429
        
 
430
        
488
431
        if (need_pipein)  ep->pipe_in = TRUE;
489
432
        if (need_pipeout) ep->pipe_out = TRUE;
490
 
/*      if (!need_tmpin && !need_fifoin && !need_inplace && !need_filename && !need_preview_uri) {
491
 
                ep->pipe_in = TRUE;
492
 
        }
493
 
        if (!discard_output && !need_tmpout && !need_fifoout && !need_inplace) {
494
 
                ep->pipe_out = TRUE;
495
 
        }*/
496
433
        DEBUG_MSG("create_commandstring, formatstring '%s' seems OK\n",formatstring);
497
434
 
498
435
        is_local_non_modified = (ep->bfwin->current_document->uri 
504
441
        if (need_filename || is_local_non_modified) {
505
442
                curi = g_file_get_uri(ep->bfwin->current_document->uri);
506
443
 
507
 
                if (need_local || (is_local_non_modified && (need_tmpin||need_fifoin))) {
 
444
                if (need_local || (is_local_non_modified && need_tmpin)) {
508
445
                        #ifdef WIN32
509
446
                                localfilename = strrchr(localname, '\\')+1;
510
447
                        #else
518
455
        }
519
456
        if (need_tmpin) items++;
520
457
        if (need_tmpout) items++;
521
 
        if (need_fifoin) items++;
522
 
        if (need_fifoout) items++;
523
458
        if (need_inplace) items++;
 
459
        if (need_arguments) items++;
524
460
 
525
461
        table = g_new(Tconvert_table, items+1);
526
462
        if (need_filename) {
552
488
                        table[cur].my_char = g_strdup(ep->tmp_in);
553
489
                }
554
490
                cur++;
555
 
        } else if (need_fifoin) {
556
 
                table[cur].my_int = 'i';
557
 
                if (is_local_non_modified) {
558
 
                        table[cur].my_char = g_strdup(localname);;
559
 
                } else {
560
 
                        ep->fifo_in = create_secure_dir_return_filename();
561
 
                        table[cur].my_char = g_strdup(ep->fifo_in);
562
 
                }
563
 
                
564
 
                DEBUG_MSG("create_commandstring, %%i will be at %s\n",table[cur].my_char);
565
 
                cur++;
566
491
        } else if (need_inplace) {
567
492
                table[cur].my_int = 't';
568
493
                ep->inplace = create_secure_dir_return_filename();
575
500
                ep->tmp_out = create_secure_dir_return_filename();
576
501
                table[cur].my_char = g_strdup(ep->tmp_out);
577
502
                cur++;
578
 
        } else if (need_fifoout) {
579
 
                table[cur].my_int = 'o';
580
 
                ep->fifo_out = create_secure_dir_return_filename();
581
 
                table[cur].my_char = g_strdup(ep->fifo_out);
582
 
                DEBUG_MSG("create_commandstring, %%o will be at %s\n",ep->fifo_out);
583
 
                cur++;
584
503
        }
585
504
        if (need_local) {
586
505
                table[cur].my_int = 'f';
590
509
                table[cur].my_char = g_strndup(localname, strlen(localname) - strlen(localfilename));
591
510
                cur++;
592
511
        }
 
512
        if (need_arguments) {
 
513
                table[cur].my_int = 'a';
 
514
                table[cur].my_char = g_strdup(user_argument);
 
515
                cur++;
 
516
        }
593
517
        table[cur].my_int = '\0';
594
518
        table[cur].my_char = NULL;
595
519
        if (cur == 0) {
599
523
        }
600
524
        free_convert_table(table);
601
525
        g_free(formatstring);
 
526
        g_free(user_argument);
602
527
        DEBUG_MSG("create_commandstring, returning %s\n",retstring);
603
528
        return retstring;
604
529
}
661
586
        return TRUE;
662
587
}
663
588
 
664
 
static gboolean filter_io_watch_lcb(GIOChannel *channel,GIOCondition condition,gpointer data) {
 
589
static gboolean filter_custom_io_watch_lcb(GIOChannel *channel,GIOCondition condition,gpointer data) {
665
590
        Texternalp *ep = data;
666
 
        DEBUG_MSG("filter_io_watch_lcb, started with condition=%d\n",condition);
 
591
        DEBUG_MSG("filter_custom_io_watch_lcb, started with condition=%d\n",condition);
667
592
        if (condition & G_IO_IN) {
668
593
                gchar *str_return;
669
594
                gsize length;
672
597
                
673
598
                status = g_io_channel_read_to_end(channel,&str_return,&length,&gerror);
674
599
                if (gerror) {
675
 
                        g_warning("error while trying to read data for outputbox, %d: %s\n",gerror->code,gerror->message);
 
600
                        g_warning("error while trying to read data for filter or custom command, %d: %s\n",gerror->code,gerror->message);
676
601
                        g_error_free(gerror);
677
602
                }
678
603
        
679
604
                if (status == G_IO_STATUS_NORMAL && str_return) {
680
605
                        gint end=ep->end;
681
606
                        GError *error=NULL;
682
 
                        DEBUG_MSG("filter_io_watch_lcb, received '%s'\n",str_return);
683
 
                        if (ep->bfwin->current_document) {
 
607
                        if (ep->customcommand_cb) {
 
608
                                ep->customcommand_cb(str_return, ep->bfwin);
 
609
                        } else {
 
610
                                GtkTextIter iter;
 
611
                                GtkTextBuffer *buffer = ep->bfwin->current_document->buffer;
 
612
                                DEBUG_MSG("filter_custom_io_watch_lcb, received '%s'\n",str_return);
 
613
                                gint line=-1,offset=-1;
684
614
                                if (ep->end == -1) {
685
 
                                        end = gtk_text_buffer_get_char_count(ep->bfwin->current_document->buffer);
 
615
                                        end = gtk_text_buffer_get_char_count(buffer);
 
616
                                }
 
617
                                if (!gtk_text_buffer_get_has_selection(buffer)) {
 
618
                                        gtk_text_buffer_get_iter_at_mark(buffer, &iter,gtk_text_buffer_get_insert(buffer));
 
619
                                        line = gtk_text_iter_get_line(&iter);
 
620
                                        offset = gtk_text_iter_get_line_offset(&iter);
686
621
                                }
687
622
                                doc_replace_text(ep->bfwin->current_document, str_return, ep->begin, end);
 
623
                                if (line != -1) {
 
624
                                        gtk_text_buffer_get_iter_at_line_offset(buffer, &iter, line, offset);
 
625
                                        gtk_text_buffer_place_cursor(buffer, &iter);
 
626
                                }
688
627
                        }
689
628
                        g_io_channel_shutdown(channel,TRUE,&error);
690
629
                        externalp_unref(ep);
691
630
                        g_free(str_return);
692
631
                        return FALSE;
693
632
                } else {
694
 
                        DEBUG_MSG("filter_io_watch_lcb, status=%d\n",status);
 
633
                        DEBUG_MSG("filter_custom_io_watch_lcb, status=%d\n",status);
695
634
                }
696
635
                if (str_return) g_free(str_return);
697
636
        }
720
659
typedef enum {
721
660
        mode_filter,
722
661
        mode_outputbox,
723
 
        mode_command
 
662
        mode_command,
 
663
        mode_custom
724
664
} Tcommandmode;
725
665
 
726
666
static void command_backend(Tbfwin *bfwin, gint begin, gint end, 
727
 
                                                                const gchar *formatstring, Tcommandmode commandmode) {
 
667
                                                                const gchar *formatstring, Tcommandmode commandmode, CustomCommandCallback customcommand_cb) {
728
668
        Texternalp *ep;
729
669
        
730
670
        DEBUG_MSG("command_backend, started\n");
743
683
        }
744
684
        if (commandmode == mode_filter) {
745
685
                ep->include_stderr = FALSE;
746
 
                ep->channel_out_lcb = filter_io_watch_lcb;
 
686
                ep->channel_out_lcb = filter_custom_io_watch_lcb;
747
687
                ep->channel_out_data = ep;
748
688
        } else if (commandmode == mode_outputbox)       {
749
689
                ep->include_stderr = TRUE;
753
693
                ep->include_stderr = FALSE;
754
694
                ep->channel_out_lcb = NULL;
755
695
                ep->channel_out_data = NULL;
 
696
        } else if (commandmode == mode_custom) {
 
697
                ep->include_stderr = FALSE;
 
698
                ep->customcommand_cb = customcommand_cb;
 
699
                ep->channel_out_lcb = filter_custom_io_watch_lcb;
 
700
                ep->channel_out_data = ep;
756
701
        }
757
702
 
758
703
        start_command(ep);
759
704
}
760
705
 
761
706
void outputbox_command(Tbfwin *bfwin, const gchar *formatstring) {
762
 
        command_backend(bfwin, 0, -1,formatstring, mode_outputbox);
 
707
        command_backend(bfwin, 0, -1,formatstring, mode_outputbox, NULL);
763
708
}
764
709
 
765
710
 
766
711
void filter_command(Tbfwin *bfwin, const gchar *formatstring, gint begin, gint end) {
767
 
        command_backend(bfwin, begin, end,formatstring, mode_filter);
 
712
        command_backend(bfwin, begin, end,formatstring, mode_filter, NULL);
768
713
}
769
714
 
770
715
void external_command(Tbfwin *bfwin, const gchar *formatstring) {
771
 
        command_backend(bfwin, 0, -1,formatstring, mode_command);
 
716
        command_backend(bfwin, 0, -1,formatstring, mode_command, NULL);
 
717
}
 
718
 
 
719
void
 
720
custom_command(Tbfwin *bfwin, const gchar *formatstring, CustomCommandCallback func)
 
721
{
 
722
        command_backend(bfwin, 0, -1,formatstring, mode_custom, func);
772
723
}