utilvfs.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /* Utilities for VFS modules.
  2. Currently includes login and tcp open socket routines.
  3. Copyright (C) 1995, 1996 Miguel de Icaza
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License
  6. as published by the Free Software Foundation; either version 2 of
  7. the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  15. /* Namespace: exports vfs_split_url */
  16. #ifndef test_get_host_and_username
  17. #include <config.h>
  18. #endif
  19. #include <unistd.h>
  20. #include <stdlib.h>
  21. #include <stdarg.h>
  22. #include <stdio.h>
  23. #include <signal.h>
  24. #include <string.h>
  25. #include <pwd.h>
  26. #include <sys/types.h>
  27. #include <netdb.h>
  28. #include <sys/socket.h>
  29. #include <netinet/in.h>
  30. #include <arpa/inet.h>
  31. #ifdef USE_TERMNET
  32. #include <termnet.h>
  33. #endif
  34. #include <errno.h>
  35. #include "utilvfs.h"
  36. #include "vfs.h"
  37. /* Extract the hostname and username from the path */
  38. /* path is in the form: [user@]hostname:port/remote-dir, e.g.:
  39. *
  40. * ftp://sunsite.unc.edu/pub/linux
  41. * ftp://miguel@sphinx.nuclecu.unam.mx/c/nc
  42. * ftp://tsx-11.mit.edu:8192/
  43. * ftp://joe@foo.edu:11321/private
  44. * ftp://joe:password@foo.se
  45. *
  46. * If the user is empty, e.g. ftp://@roxanne/private, then your login name
  47. * is supplied.
  48. *
  49. * returns malloced host if host isn't null, user and pass if pass is not null.
  50. * returns a malloced strings with the pathname relative to the host.
  51. * */
  52. char *vfs_split_url (const char *path, char **host, char **user,
  53. int *port, char **pass, int default_port, int flags)
  54. {
  55. struct passwd *passwd_info;
  56. char *dir, *colon, *inner_colon, *at, *rest;
  57. char *retval;
  58. char *pcopy = g_strdup (path);
  59. char *pend = pcopy + strlen (pcopy);
  60. int default_is_anon = flags & URL_DEFAULTANON;
  61. /* get user from ~/.netrc if we're supposed to */
  62. int default_is_netrc = use_netrc;
  63. if (pass)
  64. *pass = NULL;
  65. *port = default_port;
  66. *user = NULL;
  67. retval = NULL;
  68. dir = pcopy;
  69. if (!(flags & URL_NOSLASH)) {
  70. /* locate path component */
  71. while (*dir != PATH_SEP && *dir)
  72. dir++;
  73. if (*dir){
  74. retval = g_strdup (dir);
  75. *dir = 0;
  76. } else
  77. retval = g_strdup (PATH_SEP_STR);
  78. }
  79. /* search for any possible user */
  80. at = strchr (pcopy, '@');
  81. /* We have a username */
  82. if (at){
  83. *at = 0;
  84. inner_colon = strchr (pcopy, ':');
  85. if (inner_colon){
  86. *inner_colon = 0;
  87. inner_colon++;
  88. if (pass)
  89. *pass = g_strdup (inner_colon);
  90. }
  91. if (*pcopy != 0)
  92. *user = g_strdup (pcopy);
  93. else {
  94. default_is_anon = 0;
  95. /* don't lookup ~/.netrc, use login name instead */
  96. default_is_netrc = 0;
  97. }
  98. if (pend == at+1)
  99. rest = at;
  100. else
  101. rest = at + 1;
  102. } else
  103. rest = pcopy;
  104. /* dummy user to be replaced in lookup_netrc() in ftpfs.c */
  105. if (!*user && (default_is_netrc == 1))
  106. *user = g_strdup ("*netrc*");
  107. if (!*user){
  108. if (default_is_anon)
  109. *user = g_strdup ("anonymous");
  110. else {
  111. if ((passwd_info = getpwuid (geteuid ())) == NULL)
  112. *user = g_strdup ("anonymous");
  113. else {
  114. *user = g_strdup (passwd_info->pw_name);
  115. }
  116. endpwent ();
  117. }
  118. }
  119. /* Check if the host comes with a port spec, if so, chop it */
  120. colon = strchr (rest, ':');
  121. if (colon){
  122. *colon = 0;
  123. if (sscanf(colon+1, "%d", port)==1) {
  124. if (*port <= 0 || *port >= 65536)
  125. *port = default_port;
  126. } else {
  127. while(*(++colon)){
  128. switch(*colon) {
  129. case 'C': *port = 1;
  130. break;
  131. case 'r': *port = 2;
  132. break;
  133. }
  134. }
  135. }
  136. }
  137. if (host)
  138. *host = g_strdup (rest);
  139. g_free (pcopy);
  140. return retval;
  141. }
  142. #ifdef test_get_host_and_username
  143. struct tt {
  144. char *url;
  145. char *r_host;
  146. char *r_user;
  147. char *r_pass;
  148. char *r_dir;
  149. int r_port;
  150. };
  151. struct tt tests [] = {
  152. { "host", "host", "anonymous", NULL, "/", 21 },
  153. { "host/dir", "host", "anonymous", NULL, "/dir", 21 },
  154. { "host:40/", "host", "anonymous", NULL, "/", 40 },
  155. { "host:40/dir", "host", "anonymous", NULL, "/dir", 40 },
  156. { "user@host", "host", "user", NULL, "/", 21 },
  157. { "user@host/dir", "host", "user", NULL, "/dir", 21 },
  158. { "user@host:40/", "host", "user", NULL, "/", 40 },
  159. { "user@host:40/dir", "host", "user", NULL, "/dir", 40 },
  160. { "user:pass@host", "host", "user", "pass", "/", 21 },
  161. { "user:pass@host/dir", "host", "user", "pass", "/dir", 21 },
  162. { "user:pass@host:40", "host", "user", "pass", "/", 40 },
  163. { "user:pass@host:40/dir", "host", "user", "pass", "/dir", 40 },
  164. { "host/a@b", "host", "anonymous", NULL, "/a@b", 21 },
  165. { "host:40/a@b", "host", "anonymous", NULL, "/a@b", 40 },
  166. { "user@host/a@b", "host", "user", NULL, "/a@b", 21 },
  167. { "user@host:40/a@b", "host", "user", NULL, "/a@b", 40 },
  168. { "user:pass@host/a@b", "host", "user", "pass", "/a@b", 21 },
  169. { "user:pass@host:40/a@b", "host", "user", "pass", "/a@b", 40 },
  170. { "host/a:b", "host", "anonymous", NULL, "/a:b", 21 },
  171. { "host:40/a:b", "host", "anonymous", NULL, "/a:b", 40 },
  172. { "user@host/a:b", "host", "user", NULL, "/a:b", 21 },
  173. { "user@host:40/a:b", "host", "user", NULL, "/a:b", 40 },
  174. { "user:pass@host/a:b", "host", "user", "pass", "/a:b", 21 },
  175. { "user:pass@host:40/a:b", "host", "user", "pass", "/a:b", 40 },
  176. { "host/a/b", "host", "anonymous", NULL, "/a/b", 21 },
  177. { "host:40/a/b", "host", "anonymous", NULL, "/a/b", 40 },
  178. { "user@host/a/b", "host", "user", NULL, "/a/b", 21 },
  179. { "user@host:40/a/b", "host", "user", NULL, "/a/b", 40 },
  180. { "user:pass@host/a/b", "host", "user", "pass", "/a/b", 21 },
  181. { "user:pass@host:40/a/b", "host", "user", "pass", "/a/b", 40 },
  182. { NULL }
  183. };
  184. /* tests with implicit login name */
  185. struct tt tests2 [] = {
  186. { "@host", "host", "user", NULL, "/", 21 },
  187. { "@host/dir", "host", "user", NULL, "/dir", 21 },
  188. { "@host:40/", "host", "user", NULL, "/", 40 },
  189. { "@host:40/dir", "host", "user", NULL, "/dir", 40 },
  190. { ":pass@host", "host", "user", "pass", "/", 21 },
  191. { ":pass@host/dir", "host", "user", "pass", "/dir", 21 },
  192. { ":pass@host:40", "host", "user", "pass", "/", 40 },
  193. { ":pass@host:40/dir", "host", "user", "pass", "/dir", 40 },
  194. { "@host/a@b", "host", "user", NULL, "/a@b", 21 },
  195. { "@host:40/a@b", "host", "user", NULL, "/a@b", 40 },
  196. { ":pass@host/a@b", "host", "user", "pass", "/a@b", 21 },
  197. { ":pass@host:40/a@b", "host", "user", "pass", "/a@b", 40 },
  198. { "@host/a:b", "host", "user", NULL, "/a:b", 21 },
  199. { "@host:40/a:b", "host", "user", NULL, "/a:b", 40 },
  200. { ":pass@host/a:b", "host", "user", "pass", "/a:b", 21 },
  201. { ":pass@host:40/a:b", "host", "user", "pass", "/a:b", 40 },
  202. { "@host/a/b", "host", "user", NULL, "/a/b", 21 },
  203. { "@host:40/a/b", "host", "user", NULL, "/a/b", 40 },
  204. { ":pass@host/a/b", "host", "user", "pass", "/a/b", 21 },
  205. { ":pass@host:40/a/b", "host", "user", "pass", "/a/b", 40 },
  206. { NULL }
  207. };
  208. main ()
  209. {
  210. int i, port, err;
  211. char *dir, *host, *user, *pass;
  212. struct passwd *passwd_info;
  213. char *current;
  214. if ((passwd_info = getpwuid (geteuid ())) == NULL)
  215. current = g_strdup ("anonymous");
  216. else {
  217. current= g_strdup (passwd_info->pw_name);
  218. }
  219. endpwent ();
  220. for (i = 0; tests [i].url; i++){
  221. err = 0;
  222. dir = get_host_and_username (tests [i].url, &host, &user, &port, 21, 1, &pass);
  223. if (strcmp (dir, tests [i].r_dir))
  224. err++, printf ("dir: test %d flunked\n", i);
  225. if (!err && strcmp (host, tests [i].r_host))
  226. err++, printf ("host: test %d flunked\n", i);
  227. if (!err && strcmp (user, tests [i].r_user))
  228. err++, printf ("user: test %d flunked\n", i);
  229. if (!err && tests [i].r_pass)
  230. if (strcmp (dir, tests [i].r_dir))
  231. err++, printf ("pass: test %d flunked\n", i);
  232. if (!err & tests [i].r_port != port)
  233. err++, printf ("port: test %d flunked\n", i);
  234. if (err){
  235. printf ("host=[%s] user=[%s] pass=[%s] port=[%d]\n",
  236. host, user, pass, port);
  237. }
  238. }
  239. printf ("%d tests ok\nExtra tests:", i);
  240. for (i = 0; i < 4; i++){
  241. dir = get_host_and_username (tests [i].url, &host, &user, &port, 21, 0, &pass);
  242. if (strcmp (user, current))
  243. printf ("ntest: flunked %d\n", i);
  244. }
  245. printf ("%d tests ok\nTests with implicit login name\n", i);
  246. for (i = 0; tests2 [i].url; i++){
  247. err = 0;
  248. dir = get_host_and_username (tests2 [i].url, &host, &user, &port, 21, 1, &pass);
  249. if (strcmp (dir, tests2 [i].r_dir))
  250. err++, printf ("dir: test %d flunked\n", i);
  251. if (!err && strcmp (host, tests2 [i].r_host))
  252. err++, printf ("host: test %d flunked\n", i);
  253. if (!err && strcmp (user, current))
  254. err++, printf ("user: test %d flunked\n", i);
  255. if (!err && tests2 [i].r_pass)
  256. if (strcmp (dir, tests2 [i].r_dir))
  257. err++, printf ("pass: test %d flunked\n", i);
  258. if (!err & tests2 [i].r_port != port)
  259. err++, printf ("port: test %d flunked\n", i);
  260. if (err){
  261. printf ("host=[%s] user=[%s] pass=[%s] port=[%d]\n",
  262. host, user, pass, port);
  263. }
  264. }
  265. printf ("%d tests ok\n", i);
  266. }
  267. #endif