1 /*
2 * redir.h --
3 *
4 * Yet Another FTP Client
5 * Copyright (C) 1998-2001, Martin Hedenfalk <mhe@stacken.kth.se>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version. See COPYING for more details.
11 */
12
13 #include "syshdr.h"
14
15 static FILE *redir_fp = 0;
16 static bool ispipe = false;
17 static int oldout = -1;
18 static int olderr = -1;
19
reject_ampersand(char * cmd)20 bool reject_ampersand(char *cmd)
21 {
22 char *e, *f;
23
24 /* look for and reject '&' in command
25 * (asynchronous execution)
26 * allow '&&'
27 */
28 e = cmd;
29 while(e && *e && (f=strchr(e, '&')) != 0) {
30 if(f == 0)
31 break;;
32 if(f[1] != '&') {
33 fprintf(stderr, _("Asynchronous mode NOT supported"
34 " (found '&' in command)\n"));
35 return true;
36 } else {
37 e = f+1;
38 if(!*e)
39 break;
40 e++;
41 }
42 }
43 return false;
44 }
45
46 typedef enum {REDIR_PIPE, REDIR_WRITE, REDIR_APPEND} redir_type;
47
open_redirection(char * cmd)48 int open_redirection(char *cmd)
49 {
50 redir_type type;
51 bool errtoo = false;
52
53 redir_fp = 0;
54
55 if(cmd[0] == '|') {
56 type = REDIR_PIPE;
57 } else if(cmd[0] == '>') {
58 if(cmd[1] == '>') {
59 cmd++;
60 type = REDIR_APPEND;
61 } else
62 type = REDIR_WRITE;
63 } else
64 return -1;
65
66 if(!*cmd) {
67 fprintf(stderr, _("missing redirection argument\n"));
68 return -1;
69 }
70
71 cmd++;
72 if(*cmd == '&') {
73 errtoo = true;
74 cmd++;
75 }
76
77 while(*cmd == ' ')
78 cmd++;
79
80 if(!*cmd) {
81 fprintf(stderr, _("missing redirection argument\n"));
82 return -1;
83 }
84
85 if(reject_ampersand(cmd))
86 return -1;
87
88 if(type == REDIR_PIPE) {
89 redir_fp = popen(cmd, "w");
90 ispipe = true;
91 } else {
92 redir_fp = fopen(cmd, type == REDIR_WRITE ? "w" : "a");
93 ispipe = false;
94 }
95
96 if(redir_fp == 0) {
97 perror(cmd);
98 return -1;
99 }
100
101 oldout = dup(fileno(stdout));
102 if(oldout == -1) {
103 perror("dup");
104 fclose(redir_fp);
105 redir_fp = 0;
106 return -1;
107 }
108
109 if(dup2(fileno(redir_fp), fileno(stdout)) == -1) {
110 perror("dup2");
111 fclose(redir_fp);
112 redir_fp = 0;
113 return -1;
114 }
115
116 if(errtoo) {
117 olderr = dup(fileno(stderr));
118 if(olderr == -1) {
119 perror("dup");
120 fclose(redir_fp);
121 if(dup2(oldout, fileno(stdout)) == -1)
122 perror("dup2");
123 redir_fp = 0;
124 oldout = -1;
125 olderr = -1;
126 return -1;
127 }
128
129 if(dup2(fileno(redir_fp), fileno(stderr)) == -1) {
130 perror("dup2");
131 fclose(redir_fp);
132 redir_fp = 0;
133 if(dup2(oldout, fileno(stdout)) == -1)
134 perror("dup2");
135 oldout = -1;
136 olderr = -1;
137 return -1;
138 }
139 }
140 return 0;
141 }
142
close_redirection(void)143 int close_redirection(void)
144 {
145 if(redir_fp == 0)
146 return -1;
147
148 if(oldout == -1)
149 fprintf(stderr, _("Error, cannot restore stdout!\n"));
150 else {
151 if(dup2(oldout, fileno(stdout)) == -1)
152 perror("dup2");
153 oldout = -1;
154 }
155 if(olderr != -1) {
156 if(dup2(olderr, fileno(stderr)) == -1)
157 perror("dup2");
158 olderr = -1;
159 }
160
161 if(ispipe)
162 pclose(redir_fp);
163 else
164 fclose(redir_fp);
165 redir_fp = 0;
166 return 0;
167 }
168