utilvfs.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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., 675 Mass Ave, Cambridge, MA 02139, USA. */
  15. /* Namespace: exports vfs_get_host_and_username */
  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. #include <malloc.h>
  32. #ifdef USE_TERMNET
  33. #include <termnet.h>
  34. #endif
  35. #include <errno.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, user.
  50. * returns a malloced strings with the pathname relative to the host.
  51. * */
  52. char *vfs_split_url (char *path, char **host, char **user, int *port, char **pass,
  53. 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 = strdup (path);
  59. char *pend = pcopy + strlen (pcopy);
  60. int default_is_anon = flags & URL_DEFAULTANON;
  61. *pass = NULL;
  62. *port = default_port;
  63. *user = NULL;
  64. retval = NULL;
  65. dir = pcopy;
  66. if (!(flags & URL_NOSLASH)) {
  67. /* locate path component */
  68. for (; *dir != '/' && *dir; dir++)
  69. ;
  70. if (*dir){
  71. retval = strdup (dir);
  72. *dir = 0;
  73. } else
  74. retval = strdup ("/");
  75. }
  76. /* search for any possible user */
  77. at = strchr (pcopy, '@');
  78. /* We have a username */
  79. if (at){
  80. *at = 0;
  81. inner_colon = strchr (pcopy, ':');
  82. if (inner_colon){
  83. *inner_colon = 0;
  84. inner_colon++;
  85. if (*inner_colon == '@')
  86. *pass = NULL;
  87. else
  88. *pass = strdup (inner_colon);
  89. }
  90. if (*pcopy != 0)
  91. *user = strdup (pcopy);
  92. else
  93. default_is_anon = 0;
  94. if (pend == at+1)
  95. rest = at;
  96. else
  97. rest = at + 1;
  98. } else
  99. rest = pcopy;
  100. if (!*user){
  101. if (default_is_anon)
  102. *user = strdup ("anonymous");
  103. else {
  104. if ((passwd_info = getpwuid (geteuid ())) == NULL)
  105. *user = strdup ("anonymous");
  106. else {
  107. *user = strdup (passwd_info->pw_name);
  108. }
  109. endpwent ();
  110. }
  111. }
  112. /* Check if the host comes with a port spec, if so, chop it */
  113. colon = strchr (rest, ':');
  114. if (colon){
  115. *colon = 0;
  116. if (sscanf(colon+1, "%d", port)==1) {
  117. if (*port <= 0 || *port >= 65536)
  118. *port = default_port;
  119. } else {
  120. while(1) {
  121. colon++;
  122. switch(*colon) {
  123. case 'C': *port = 1;
  124. break;
  125. case 'r': *port = 2;
  126. break;
  127. case 0: goto done;
  128. }
  129. }
  130. }
  131. }
  132. done:
  133. *host = strdup (rest);
  134. free (pcopy);
  135. return retval;
  136. }
  137. #ifdef test_get_host_and_username
  138. struct tt {
  139. char *url;
  140. char *r_host;
  141. char *r_user;
  142. char *r_pass;
  143. char *r_dir;
  144. int r_port;
  145. };
  146. struct tt tests [] = {
  147. { "host", "host", "anonymous", NULL, "/", 21 },
  148. { "host/dir", "host", "anonymous", NULL, "/dir", 21 },
  149. { "host:40/", "host", "anonymous", NULL, "/", 40 },
  150. { "host:40/dir", "host", "anonymous", NULL, "/dir", 40 },
  151. { "user@host", "host", "user", NULL, "/", 21 },
  152. { "user@host/dir", "host", "user", NULL, "/dir", 21 },
  153. { "user@host:40/", "host", "user", NULL, "/", 40 },
  154. { "user@host:40/dir", "host", "user", NULL, "/dir", 40 },
  155. { "user:pass@host", "host", "user", "pass", "/", 21 },
  156. { "user:pass@host/dir", "host", "user", "pass", "/dir", 21 },
  157. { "user:pass@host:40", "host", "user", "pass", "/", 40 },
  158. { "user:pass@host:40/dir", "host", "user", "pass", "/dir", 40 },
  159. { "host/a@b", "host", "anonymous", NULL, "/a@b", 21 },
  160. { "host:40/a@b", "host", "anonymous", NULL, "/a@b", 40 },
  161. { "user@host/a@b", "host", "user", NULL, "/a@b", 21 },
  162. { "user@host:40/a@b", "host", "user", NULL, "/a@b", 40 },
  163. { "user:pass@host/a@b", "host", "user", "pass", "/a@b", 21 },
  164. { "user:pass@host:40/a@b", "host", "user", "pass", "/a@b", 40 },
  165. { "host/a:b", "host", "anonymous", NULL, "/a:b", 21 },
  166. { "host:40/a:b", "host", "anonymous", NULL, "/a:b", 40 },
  167. { "user@host/a:b", "host", "user", NULL, "/a:b", 21 },
  168. { "user@host:40/a:b", "host", "user", NULL, "/a:b", 40 },
  169. { "user:pass@host/a:b", "host", "user", "pass", "/a:b", 21 },
  170. { "user:pass@host:40/a:b", "host", "user", "pass", "/a:b", 40 },
  171. { "host/a/b", "host", "anonymous", NULL, "/a/b", 21 },
  172. { "host:40/a/b", "host", "anonymous", NULL, "/a/b", 40 },
  173. { "user@host/a/b", "host", "user", NULL, "/a/b", 21 },
  174. { "user@host:40/a/b", "host", "user", NULL, "/a/b", 40 },
  175. { "user:pass@host/a/b", "host", "user", "pass", "/a/b", 21 },
  176. { "user:pass@host:40/a/b", "host", "user", "pass", "/a/b", 40 },
  177. { NULL }
  178. };
  179. /* tests with implicit login name */
  180. struct tt tests2 [] = {
  181. { "@host", "host", "user", NULL, "/", 21 },
  182. { "@host/dir", "host", "user", NULL, "/dir", 21 },
  183. { "@host:40/", "host", "user", NULL, "/", 40 },
  184. { "@host:40/dir", "host", "user", NULL, "/dir", 40 },
  185. { ":pass@host", "host", "user", "pass", "/", 21 },
  186. { ":pass@host/dir", "host", "user", "pass", "/dir", 21 },
  187. { ":pass@host:40", "host", "user", "pass", "/", 40 },
  188. { ":pass@host:40/dir", "host", "user", "pass", "/dir", 40 },
  189. { "@host/a@b", "host", "user", NULL, "/a@b", 21 },
  190. { "@host:40/a@b", "host", "user", NULL, "/a@b", 40 },
  191. { ":pass@host/a@b", "host", "user", "pass", "/a@b", 21 },
  192. { ":pass@host:40/a@b", "host", "user", "pass", "/a@b", 40 },
  193. { "@host/a:b", "host", "user", NULL, "/a:b", 21 },
  194. { "@host:40/a:b", "host", "user", NULL, "/a:b", 40 },
  195. { ":pass@host/a:b", "host", "user", "pass", "/a:b", 21 },
  196. { ":pass@host:40/a:b", "host", "user", "pass", "/a:b", 40 },
  197. { "@host/a/b", "host", "user", NULL, "/a/b", 21 },
  198. { "@host:40/a/b", "host", "user", NULL, "/a/b", 40 },
  199. { ":pass@host/a/b", "host", "user", "pass", "/a/b", 21 },
  200. { ":pass@host:40/a/b", "host", "user", "pass", "/a/b", 40 },
  201. { NULL }
  202. };
  203. main ()
  204. {
  205. int i, port, err;
  206. char *dir, *host, *user, *pass;
  207. struct passwd *passwd_info;
  208. char *current;
  209. if ((passwd_info = getpwuid (geteuid ())) == NULL)
  210. current = strdup ("anonymous");
  211. else {
  212. current= strdup (passwd_info->pw_name);
  213. }
  214. endpwent ();
  215. for (i = 0; tests [i].url; i++){
  216. err = 0;
  217. dir = get_host_and_username (tests [i].url, &host, &user, &port, 21, 1, &pass);
  218. if (strcmp (dir, tests [i].r_dir))
  219. err++, printf ("dir: test %d flunked\n", i);
  220. if (!err && strcmp (host, tests [i].r_host))
  221. err++, printf ("host: test %d flunked\n", i);
  222. if (!err && strcmp (user, tests [i].r_user))
  223. err++, printf ("user: test %d flunked\n", i);
  224. if (!err && tests [i].r_pass)
  225. if (strcmp (dir, tests [i].r_dir))
  226. err++, printf ("pass: test %d flunked\n", i);
  227. if (!err & tests [i].r_port != port)
  228. err++, printf ("port: test %d flunked\n", i);
  229. if (err){
  230. printf ("host=[%s] user=[%s] pass=[%s] port=[%d]\n",
  231. host, user, pass, port);
  232. }
  233. }
  234. printf ("%d tests ok\nExtra tests:", i);
  235. for (i = 0; i < 4; i++){
  236. dir = get_host_and_username (tests [i].url, &host, &user, &port, 21, 0, &pass);
  237. if (strcmp (user, current))
  238. printf ("ntest: flunked %d\n", i);
  239. }
  240. printf ("%d tests ok\nTests with implicit login name\n", i);
  241. for (i = 0; tests2 [i].url; i++){
  242. err = 0;
  243. dir = get_host_and_username (tests2 [i].url, &host, &user, &port, 21, 1, &pass);
  244. if (strcmp (dir, tests2 [i].r_dir))
  245. err++, printf ("dir: test %d flunked\n", i);
  246. if (!err && strcmp (host, tests2 [i].r_host))
  247. err++, printf ("host: test %d flunked\n", i);
  248. if (!err && strcmp (user, current))
  249. err++, printf ("user: test %d flunked\n", i);
  250. if (!err && tests2 [i].r_pass)
  251. if (strcmp (dir, tests2 [i].r_dir))
  252. err++, printf ("pass: test %d flunked\n", i);
  253. if (!err & tests2 [i].r_port != port)
  254. err++, printf ("port: test %d flunked\n", i);
  255. if (err){
  256. printf ("host=[%s] user=[%s] pass=[%s] port=[%d]\n",
  257. host, user, pass, port);
  258. }
  259. }
  260. printf ("%d tests ok\n", i);
  261. }
  262. #endif