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