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