1 /*
2  * utils.c -- small (generic) functions
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 #include "ftp.h"
15 #include "linklist.h"
16 #include "strq.h"
17 #include "gvars.h"
18 #include "prompt.h"
19 
listify_string(const char * str,list * lp)20 void listify_string(const char *str, list *lp)
21 {
22 	char *e;
23 	char *s, *orgs;
24 
25 	orgs = s = xstrdup(str);
26 	while((e = strqsep(&s, ':')) != 0) {
27 		if(list_search(lp, (listsearchfunc)strcmp, e) == 0)
28 			list_additem(lp, xstrdup(e));
29 	}
30 	free(orgs);
31 }
32 
stringify_list(list * lp)33 char *stringify_list(list *lp)
34 {
35 	listitem *li;
36 	char *str = NULL;
37 
38 	if(!lp)
39 		return 0;
40 
41 	li = lp->first;
42 	if(li)
43 		str = xstrdup((char *)li->data);
44 	else
45 		return 0;
46 
47 	for(li = li->next; li; li = li->next) {
48     char* tmp = str;
49 		if (asprintf(&str, "%s:%s",  tmp, (char *)li->data) == -1)
50     {
51       free(tmp);
52       return NULL;
53     }
54     free(tmp);
55 	}
56 	return str;
57 }
58 
make_unique_filename(const char * path)59 char* make_unique_filename(const char* path)
60 {
61 	const size_t maxistr = (sizeof(unsigned) * 8) / 3;
62 	/* one for dot, one for NULL, and three just in case :P */
63   const size_t pathlen = strlen(path);
64   const size_t len = pathlen + maxistr + 5;
65 
66 	char* f = xmalloc(len);
67 	strlcpy(f, path, len);
68 	char* ext = f + pathlen;
69 
70   unsigned int n = 0;
71 	while (1) {
72 		if (access(f, F_OK) != 0)
73 			break;
74 		snprintf(ext, len - pathlen, ".%u", ++n);
75 	}
76 	return f;
77 }
78 
human_size(long long int size)79 char *human_size(long long int size)
80 {
81 	static char buf[17];
82 
83 	if(size < 1024)
84 		snprintf(buf, sizeof(buf), "%llu", size);
85 	else if(size < 999.5*1024) /* kilobinary */
86 		snprintf(buf, sizeof(buf), "%.1fKi", (double)size/1024);
87 	else if(size < 999.5*1024*1024) /* megabinary */
88 		snprintf(buf, sizeof(buf), "%.2fMi", (double)size/(1024*1024));
89 	else /* gigabinary */
90 		snprintf(buf, sizeof(buf), "%.2fGi", (double)size/(1024*1024*1024));
91 	/* they aren't transferring terabinaries with ftp, eh? */
92 
93 	return buf;
94 }
95 
human_time(unsigned int secs)96 char *human_time(unsigned int secs)
97 {
98 	static char buf[17];
99 
100 	if(secs < 60*60)
101 		snprintf(buf, 17, "%u:%02u", secs/60, secs%60);
102 	else
103 		snprintf(buf, 17, "%u:%02u:%02u", secs/(60*60), (secs/60)%60, secs%60);
104 	return buf;
105 }
106 
print_xterm_title_string(const char * str)107 static void print_xterm_title_string(const char *str)
108 {
109 	if(gvXtermTitleTerms && strstr(gvXtermTitleTerms, gvTerm) != 0 && str)
110 		fprintf(stderr, "%s", str);
111 }
112 
print_xterm_title(void)113 void print_xterm_title(void)
114 {
115 	char *xterm_title = expand_prompt(ftp_connected()
116 									  ? (ftp_loggedin() ? gvXtermTitle3
117 										 : gvXtermTitle2)
118 									  : gvXtermTitle1);
119 	print_xterm_title_string(xterm_title);
120 	free(xterm_title);
121 }
122 
reset_xterm_title(void)123 void reset_xterm_title(void)
124 {
125 	char* e = NULL;
126 	if (asprintf(&e, "\x1B]0;%s\x07", gvTerm) != -1)
127   {
128     print_xterm_title_string(e);
129 	  free(e);
130   }
131 }
132 
get_mode_string(mode_t m)133 char* get_mode_string(mode_t m)
134 {
135 	static char tmp[4];
136 
137 	strncpy(tmp, "000", 4);
138 
139 	if(test(m, S_IRUSR))
140 		tmp[0] += 4;
141 	if(test(m, S_IWUSR))
142 		tmp[0] += 2;
143 	if(test(m, S_IXUSR))
144 		tmp[0]++;
145 
146 	if(test(m, S_IRGRP))
147 		tmp[1] += 4;
148 	if(test(m, S_IWGRP))
149 		tmp[1] += 2;
150 	if(test(m, S_IXGRP))
151 		tmp[1]++;
152 
153 	if(test(m, S_IROTH))
154 		tmp[2] += 4;
155 	if(test(m, S_IWOTH))
156 		tmp[2] += 2;
157 	if(test(m, S_IXOTH))
158 		tmp[2]++;
159 
160 	return tmp;
161 }
162 
switch_search(const Ftp * f,const char * name)163 static int switch_search(const Ftp *f, const char *name)
164 {
165 	if(!f->url)
166 		return 1;
167 	if(f->url->alias) {
168 		if(strcmp(f->url->alias, name) == 0)
169 			return 0;
170 	}
171 	return strcmp(f->url->hostname, name);
172 }
173 
ftplist_search(const char * str)174 listitem *ftplist_search(const char *str)
175 {
176 	if(isdigit((int)str[0]) && strchr(str, '.') == 0) {
177 		listitem *li;
178 		int i = 1;
179 		int n = atoi(str);
180 		if(n <= 0 || n > list_numitem(gvFtpList)) {
181 			ftp_err(_("invalid connection number: '%d'\n"), n);
182 			return 0;
183 		}
184 		for(li=gvFtpList->first; li; li=li->next, i++) {
185 			if(i == n)
186 				return li;
187 		}
188 	} else {
189 		listitem *li = list_search(gvFtpList,
190 								   (listsearchfunc)switch_search, str);
191 		if(li)
192 			return li;
193 		else
194 			ftp_err(_("no such connection open: '%s'\n"), str);
195 	}
196 	return 0;
197 }
198 
invoke_shell(const char * fmt,...)199 void invoke_shell(const char* fmt, ...)
200 {
201 	char *shell;
202 	pid_t pid;
203 
204 	ftp_set_signal(SIGINT, SIG_IGN);
205 	shell = getenv("SHELL");
206 	if(!shell)
207 		shell = STD_SHELL;
208 	pid = fork();
209 	if(pid == 0) { /* child thread */
210 		if(fmt)
211     {
212       char* tmp = NULL;
213       va_list ap;
214       va_start(ap, fmt);
215       int r = vasprintf(&tmp, fmt, ap);
216       va_end(ap);
217       if (r == -1)
218       {
219         fprintf(stderr, _("Failed to allocate memory.\n"));
220         exit(1);
221       }
222 
223 			execl(shell, shell, "-c", tmp, (char *)NULL);
224     }
225 		else {
226 			printf(_("Executing '%s', use 'exit' to exit from shell...\n"),
227 				   shell);
228 			execl(shell, shell, (char *)NULL);
229 		}
230 		perror(shell);
231 		exit(1);
232 	}
233 	if(pid == -1) {
234 		perror("fork()");
235 		return;
236 	}
237 	waitpid(pid, 0, 0);  /* wait for child to finish execution */
238 }
239