1 /* Server for the Midnight Commander Virtual File System.
3 Copyright (C) 1995, 1996, 1997 The Free Software Foundation
6 Miguel de Icaza, 1995, 1997,
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 opendir instead of keeping its table of file handles could return
25 the pointer and expect the client to send a proper value back each
28 We should use syslog to register login/logout.
32 /* {{{ Includes and global variables */
46 # include <sys/param.h>
48 # define NGROUPS_MAX NGROUPS
57 # ifdef HAVE_SHADOW_SHADOW_H
58 # include <shadow/shadow.h>
64 #include <sys/types.h>
69 # include <sys/timeb.h> /* alex: for struct timeb definition */
70 #endif /* SCO_FLAVOR */
74 /* Network include files */
75 #include <sys/socket.h>
76 #include <netinet/in.h>
78 #include <arpa/inet.h>
81 # include <rpc/pmap_prot.h>
82 # ifdef HAVE_RPC_PMAP_CLNT_H
83 # include <rpc/pmap_clnt.h>
87 /* Authentication include files */
90 # include <security/pam_misc.h>
91 # ifndef PAM_ESTABLISH_CRED
92 # define PAM_ESTABLISH_CRED PAM_CRED_ESTABLISH
102 /* The socket from which we accept commands */
105 /* Requested version number from client */
106 static int clnt_version
;
108 /* If non zero, we accept further commands */
112 char *home_dir
= NULL
;
116 /* Were we started from inetd? */
117 int inetd_started
= 0;
119 /* Are we running as a daemon? */
128 /* port number in which we listen to connections,
129 * if zero, we try to contact the portmapper to get a port, and
130 * if it's not possible, then we use a hardcoded value
134 /* if the server will use rcmd based authentication (hosts.equiv .rhosts) */
137 #define OPENDIR_HANDLES 8
139 #define DO_QUIT_VOID() \
146 /* Only used by get_port_number */
147 #define DO_QUIT_NONVOID(a) \
156 static int quit_server
;
157 static int return_code
;
161 /* {{{ Misc routines */
163 void send_status (int status
, int errno_number
)
165 rpc_send (msock
, RPC_INT
, status
, RPC_INT
, errno_number
, RPC_END
);
171 /* {{{ File with handle operations */
175 int handle
, flags
, mode
;
178 rpc_get (msock
, RPC_STRING
, &arg
, RPC_INT
, &flags
, RPC_INT
, &mode
,RPC_END
);
180 handle
= open (arg
, flags
, mode
);
181 send_status (handle
, errno
);
187 int handle
, count
, n
;
190 rpc_get (msock
, RPC_INT
, &handle
, RPC_INT
, &count
, RPC_END
);
191 data
= g_malloc (count
);
193 send_status (-1, ENOMEM
);
196 if (verbose
) printf ("count=%d\n", count
);
197 n
= read (handle
, data
, count
);
198 if (verbose
) printf ("result=%d\n", n
);
200 send_status (-1, errno
);
204 rpc_send (msock
, RPC_BLOCK
, n
, data
, RPC_END
);
211 int handle
, count
, status
;
214 rpc_get (msock
, RPC_INT
, &handle
, RPC_INT
, &count
, RPC_END
);
217 int nbytes
= count
> 8192 ? 8192 : count
;
219 rpc_get (msock
, RPC_BLOCK
, nbytes
, buffer
, RPC_END
);
220 status
= write (handle
, buffer
, nbytes
);
223 send_status (status
, errno
);
228 int handle
, offset
, whence
, status
;
233 RPC_INT
, &whence
, RPC_END
);
234 status
= lseek (handle
, offset
, whence
);
235 send_status (status
, errno
);
242 rpc_get (msock
, RPC_INT
, &handle
, RPC_END
);
243 status
= close (handle
);
244 send_status (status
, errno
);
249 /* {{{ Stat family routines */
251 void send_time (int sock
, time_t time
)
253 if (clnt_version
== 1) {
258 ct
[3] = ct
[10] = ct
[13] = ct
[16] = ct
[19] = 0;
260 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
265 month
= (ct
[6] == 'n') ? 5 : 6;
266 } else if (ct
[4] == 'F'){
268 } else if (ct
[4] == 'M'){
269 month
= (ct
[6] == 'r') ? 2 : 5;
270 } else if (ct
[4] == 'A'){
271 month
= (ct
[5] == 'p') ? 3 : 7;
272 } else if (ct
[4] == 'S'){
274 } else if (ct
[4] == 'O'){
276 } else if (ct
[4] == 'N'){
281 RPC_INT
, atoi (&ct
[17]), /* sec */
282 RPC_INT
, atoi (&ct
[14]), /* min */
283 RPC_INT
, atoi (&ct
[11]), /* hour */
284 RPC_INT
, atoi (&ct
[8]), /* mday */
285 RPC_INT
, atoi (&ct
[20]), /* year */
286 RPC_INT
, month
, /* month */
289 long ltime
= (long) time
;
292 g_snprintf (buf
, sizeof(buf
), "%lx", ltime
);
299 void send_stat_info (struct stat
*st
)
303 #ifdef HAVE_ST_BLOCKS
310 rpc_send (msock
, RPC_INT
, (long) st
->st_dev
,
311 RPC_INT
, (long) st
->st_ino
,
312 RPC_INT
, (long) st
->st_mode
,
313 RPC_INT
, (long) st
->st_nlink
,
314 RPC_INT
, (long) st
->st_uid
,
315 RPC_INT
, (long) st
->st_gid
,
316 RPC_INT
, (long) st
->st_size
,
317 RPC_INT
, (long) blocks
, RPC_END
);
318 send_time (msock
, st
->st_atime
);
319 send_time (msock
, st
->st_mtime
);
320 send_time (msock
, st
->st_ctime
);
329 rpc_get (msock
, RPC_STRING
, &file
, RPC_END
);
330 n
= lstat (file
, &st
);
331 send_status (n
, errno
);
333 send_stat_info (&st
);
343 rpc_get (msock
, RPC_INT
, &handle
, RPC_END
);
344 n
= fstat (handle
, &st
);
345 send_status (n
, errno
);
349 send_stat_info (&st
);
358 rpc_get (msock
, RPC_STRING
, &file
, RPC_END
);
360 n
= stat (file
, &st
);
361 send_status (n
, errno
);
363 send_stat_info (&st
);
369 /* {{{ Directory lookup operations */
373 DIR *dirs
[OPENDIR_HANDLES
];
374 char *names
[OPENDIR_HANDLES
];
377 void close_handle (int handle
)
379 if (mcfs_DIR
.used
> 0) mcfs_DIR
.used
--;
380 if (mcfs_DIR
.dirs
[handle
])
381 closedir (mcfs_DIR
.dirs
[handle
]);
382 if (mcfs_DIR
.names
[handle
])
383 g_free (mcfs_DIR
.names
[handle
]);
384 mcfs_DIR
.dirs
[handle
] = 0;
385 mcfs_DIR
.names
[handle
] = 0;
388 void do_opendir (void)
394 rpc_get (msock
, RPC_STRING
, &arg
, RPC_END
);
396 if (mcfs_DIR
.used
== OPENDIR_HANDLES
){
397 send_status (-1, ENFILE
); /* Error */
403 for (i
= 0; i
< OPENDIR_HANDLES
; i
++){
404 if (mcfs_DIR
.dirs
[i
] == 0){
411 send_status (-1, EMFILE
);
414 fprintf (stderr
, "OOPS! you have found a bug in mc - do_opendir()!\n");
418 if (verbose
) printf ("handle=%d\n", handle
);
421 mcfs_DIR
.dirs
[handle
] = p
;
422 mcfs_DIR
.names
[handle
] = arg
;
425 /* Because 0 is an error value */
426 rpc_send (msock
, RPC_INT
, handle
+1, RPC_INT
, 0, RPC_END
);
429 send_status (-1, errno
);
434 /* Sends the complete directory listing, as well as the stat information */
435 void do_readdir (void)
437 struct dirent
*dirent
;
442 rpc_get (msock
, RPC_INT
, &handle
, RPC_END
);
445 rpc_send (msock
, RPC_INT
, 0, RPC_END
);
449 /* We incremented it in opendir */
452 while ((dirent
= readdir (mcfs_DIR
.dirs
[handle
]))){
453 int length
= NLENGTH (dirent
);
455 rpc_send (msock
, RPC_INT
, length
, RPC_END
);
456 rpc_send (msock
, RPC_BLOCK
, length
, dirent
->d_name
, RPC_END
);
457 fname
= g_strconcat (mcfs_DIR
.names
[handle
],
458 PATH_SEP_STR
, dirent
->d_name
, NULL
);
459 n
= lstat (fname
, &st
);
460 send_status (n
, errno
);
463 send_stat_info (&st
);
465 rpc_send (msock
, RPC_INT
, 0, RPC_END
);
468 void do_closedir (void)
472 rpc_get (msock
, RPC_INT
, &handle
, RPC_END
);
473 close_handle (handle
-1);
478 /* {{{ Operations with one and two file name argument */
485 rpc_get (msock
, RPC_STRING
, &file
, RPC_END
);
487 status
= chdir (file
);
488 send_status (status
, errno
);
497 rpc_get (msock
, RPC_STRING
, &file
, RPC_END
);
499 status
= rmdir (file
);
500 send_status (status
, errno
);
509 rpc_get (msock
, RPC_STRING
, &file
, RPC_INT
, &mode
, RPC_END
);
511 status
= mkdir (file
, mode
);
512 send_status (status
, errno
);
519 int mode
, dev
, status
;
521 rpc_get (msock
, RPC_STRING
, &file
, RPC_INT
, &mode
, RPC_INT
, &dev
, RPC_END
);
523 status
= mknod (file
, mode
, dev
);
524 send_status (status
, errno
);
528 void do_readlink (void)
534 rpc_get (msock
, RPC_STRING
, &file
, RPC_END
);
535 n
= readlink (file
, buffer
, 2048);
536 send_status (n
, errno
);
539 rpc_send (msock
, RPC_STRING
, buffer
, RPC_END
);
544 void do_unlink (void)
549 rpc_get (msock
, RPC_STRING
, &file
, RPC_END
);
550 status
= unlink (file
);
551 send_status (status
, errno
);
555 void do_rename (void)
560 rpc_get (msock
, RPC_STRING
, &f1
, RPC_STRING
, &f2
, RPC_END
);
561 status
= rename (f1
, f2
);
562 send_status (status
, errno
);
563 g_free (f1
); g_free (f2
);
566 void do_symlink (void)
571 rpc_get (msock
, RPC_STRING
, &f1
, RPC_STRING
, &f2
, RPC_END
);
572 status
= symlink (f1
, f2
);
573 send_status (status
, errno
);
574 g_free (f1
); g_free (f2
);
582 rpc_get (msock
, RPC_STRING
, &f1
, RPC_STRING
, &f2
, RPC_END
);
583 status
= link (f1
, f2
);
584 send_status (status
, errno
);
585 g_free (f1
); g_free (f2
);
591 /* {{{ Misc commands */
593 void do_gethome (void)
595 rpc_send (msock
, RPC_STRING
, (home_dir
) ? home_dir
: "/", RPC_END
);
598 void do_getupdir (void)
600 rpc_send (msock
, RPC_STRING
, (up_dir
) ? up_dir
: "/", RPC_END
);
608 rpc_get (msock
, RPC_STRING
, &file
, RPC_INT
, &mode
, RPC_END
);
609 status
= chmod (file
, mode
);
610 send_status (status
, errno
);
617 int owner
, group
, status
;
619 rpc_get (msock
, RPC_STRING
, &file
,RPC_INT
, &owner
, RPC_INT
,&group
,RPC_END
);
620 status
= chown (file
, owner
, group
);
621 send_status (status
, errno
);
633 struct utimbuf times
;
635 rpc_get (msock
, RPC_STRING
, &file
,
639 sscanf (as
, "%lx", &atime
);
640 sscanf (ms
, "%lx", &mtime
);
641 if (verbose
) printf ("Got a = %s, m = %s, comp a = %ld, m = %ld\n",
642 as
, ms
, atime
, mtime
);
645 times
.actime
= (time_t) atime
;
646 times
.modtime
= (time_t) mtime
;
647 status
= utime (file
, ×
);
648 send_status (status
, errno
);
665 mc_pam_conversation (int messages
, const struct pam_message
**msg
,
666 struct pam_response
**resp
, void *appdata_ptr
)
668 struct pam_response
*r
;
669 struct user_pass
*up
= appdata_ptr
;
672 r
= g_new (struct pam_response
, messages
);
677 for (status
= PAM_SUCCESS
; messages
--; msg
++, r
++){
678 switch ((*msg
)->msg_style
){
680 case PAM_PROMPT_ECHO_ON
:
681 r
->resp
= g_strdup (up
->username
);
682 r
->resp_retcode
= PAM_SUCCESS
;
685 case PAM_PROMPT_ECHO_OFF
:
686 r
->resp
= g_strdup (up
->password
);
687 r
->resp_retcode
= PAM_SUCCESS
;
692 r
->resp_retcode
= PAM_SUCCESS
;
697 r
->resp_retcode
= PAM_SUCCESS
;
704 static struct pam_conv conv
= { &mc_pam_conversation
, NULL
};
707 /* Return 0 if authentication failed, 1 otherwise */
709 mc_pam_auth (char *username
, char *password
)
715 up
.username
= username
;
716 up
.password
= password
;
717 conv
.appdata_ptr
= &up
;
719 if ((status
= pam_start("mcserv", username
, &conv
, &pamh
)) != PAM_SUCCESS
)
721 if ((status
= pam_authenticate (pamh
, 0)) != PAM_SUCCESS
)
723 if ((status
= pam_acct_mgmt (pamh
, 0)) != PAM_SUCCESS
)
725 if ((status
= pam_setcred (pamh
, PAM_ESTABLISH_CRED
)) != PAM_SUCCESS
)
727 pam_end (pamh
, status
);
731 pam_end (pamh
, status
);
735 #else /* Code for non-PAM authentication */
737 /* Keep reading until we find a \n */
738 static int next_line (int socket
)
743 if (read (socket
, &c
, 1) <= 0)
750 static int ftp_answer (int sock
, char *text
)
755 socket_read_block (sock
, answer
, 3);
757 if (strcmp (answer
, text
) == 0)
762 int do_ftp_auth (char *username
, char *password
)
764 struct sockaddr_in local_address
;
765 unsigned long inaddr
;
769 bzero ((char *) &local_address
, sizeof (local_address
));
771 local_address
.sin_family
= AF_INET
;
772 /* FIXME: extract the ftp port with the proper function */
773 local_address
.sin_port
= htons (21);
775 /* Convert localhost to usable format */
776 if ((inaddr
= inet_addr ("127.0.0.1")) != -1)
777 bcopy ((char *) &inaddr
, (char *) &local_address
.sin_addr
,
780 if ((my_socket
= socket (AF_INET
, SOCK_STREAM
, 0)) < 0){
781 if (!isDaemon
) fprintf (stderr
, "do_auth: can't create socket\n");
784 if (connect (my_socket
, (struct sockaddr
*) &local_address
,
785 sizeof (local_address
)) < 0){
787 "do_auth: can't connect to ftp daemon for authentication\n");
791 send_string (my_socket
, "user ");
792 send_string (my_socket
, username
);
793 send_string (my_socket
, "\r\n");
794 if (!ftp_answer (my_socket
, "331")){
795 send_string (my_socket
, "quit\r\n");
799 next_line (my_socket
); /* Eat all the line */
800 send_string (my_socket
, "pass ");
801 send_string (my_socket
, password
);
802 send_string (my_socket
, "\r\n");
803 socket_read_block (my_socket
, answer
, 3);
805 send_string (my_socket
, "\r\n");
806 send_string (my_socket
, "quit\r\n");
808 if (strcmp (answer
, "230") == 0)
813 int do_classic_auth (char *username
, char *password
)
819 extern char *pw_encrypt (char *, char *);
821 #ifdef NEED_CRYPT_PROTOTYPE
822 extern char *crypt (const char *, const char *);
826 if ((this = getpwnam (username
)) == 0)
830 if ((spw
= getspnam (username
)) == NULL
)
831 this->pw_passwd
= "*";
833 this->pw_passwd
= spw
->sp_pwdp
;
834 if (strcmp (pw_encrypt (password
, this->pw_passwd
), this->pw_passwd
) == 0)
840 if (strcmp (crypt (password
, this->pw_passwd
), this->pw_passwd
) == 0){
851 #endif /* non-PAM authentication */
853 /* Try to authenticate the user based on:
854 - PAM if the system has it, else it checks:
855 - pwdauth if the system supports it.
856 - conventional auth (check salt on /etc/passwd, crypt, and compare
857 - try to contact the local ftp server and login (if -f flag used)
860 do_auth (char *username
, char *password
)
865 if (strcmp (username
, "anonymous") == 0)
869 if (mc_pam_auth (username
, password
) == 0)
871 #else /* if there is no pam */
873 if (pwdauth (username
, password
) == 0)
877 if (do_classic_auth (username
, password
))
880 auth
= do_ftp_auth (username
, password
);
886 this = getpwnam (username
);
890 if (chdir (this->pw_dir
) == -1)
893 if (this->pw_dir
[strlen (this->pw_dir
) - 1] == '/')
894 home_dir
= g_strdup (this->pw_dir
);
896 home_dir
= g_malloc (strlen (this->pw_dir
) + 2);
898 strcpy (home_dir
, this->pw_dir
);
899 strcat (home_dir
, "/");
905 if (setgid (this->pw_gid
) == -1)
908 #ifdef HAVE_INITGROUPS
910 if (NGROUPS_MAX
> 1 && initgroups (this->pw_name
, this->pw_gid
))
915 #if defined (HAVE_SETUID)
916 if (setuid (this->pw_uid
))
918 #elif defined (HAVE_SETREUID)
919 if (setreuid (this->pw_uid
, this->pw_uid
))
923 /* If the setuid call failed, then deny access */
924 /* This should fix the problem on those machines with strange setups */
925 if (getuid () != this->pw_uid
)
928 if (strcmp (username
, "ftp") == 0)
929 chroot (this->pw_dir
);
936 int do_rauth (int socket
)
938 struct sockaddr_in from
;
941 if (getpeername(0, (struct sockaddr
*)&from
, &fromlen
) < 0)
943 from
.sin_port
= ntohs ((unsigned short) from
.sin_port
);
945 /* Strange, this should not happend */
946 if (from
.sin_family
!= AF_INET
)
949 hp
= gethostbyaddr((char *)&fromp
.sin_addr
, sizeof (struct in_addr
),
955 int do_rauth (int msock
)
960 void login_reply (int logged_in
)
962 rpc_send (msock
, RPC_INT
,
963 logged_in
? MC_LOGINOK
: MC_INVALID_PASS
,
967 /* FIXME: Implement the anonymous login */
974 rpc_get (msock
, RPC_LIMITED_STRING
, &up_dir
, RPC_LIMITED_STRING
, &username
, RPC_END
);
975 if (verbose
) printf ("username: %s\n", username
);
978 logged_in
= do_rauth (msock
);
980 login_reply (logged_in
);
984 rpc_send (msock
, RPC_INT
, MC_NEED_PASSWORD
, RPC_END
);
985 rpc_get (msock
, RPC_INT
, &result
, RPC_END
);
986 if (result
== MC_QUIT
)
988 if (result
!= MC_PASS
){
989 if (verbose
) printf ("do_login: Unknown response: %d\n", result
);
992 rpc_get (msock
, RPC_LIMITED_STRING
, &password
, RPC_END
);
993 logged_in
= do_auth (username
, password
);
995 login_reply (logged_in
);
1000 /* {{{ Server and dispatching functions */
1002 /* This structure must be kept in synch with mcfs.h enums */
1006 void (*callback
)(void);
1008 { "open", do_open
},
1009 { "close", do_close
},
1010 { "read", do_read
},
1011 { "write", do_write
},
1012 { "opendir", do_opendir
},
1013 { "readdir", do_readdir
},
1014 { "closedir", do_closedir
},
1015 { "stat ", do_stat
},
1016 { "lstat ", do_lstat
},
1017 { "fstat", do_fstat
},
1018 { "chmod", do_chmod
},
1019 { "chown", do_chown
},
1020 { "readlink ", do_readlink
},
1021 { "unlink", do_unlink
},
1022 { "rename", do_rename
},
1023 { "chdir ", do_chdir
},
1024 { "lseek", do_lseek
},
1025 { "rmdir", do_rmdir
},
1026 { "symlink", do_symlink
},
1027 { "mknod", do_mknod
},
1028 { "mkdir", do_mkdir
},
1029 { "link", do_link
},
1030 { "gethome", do_gethome
},
1031 { "getupdir", do_getupdir
},
1032 { "login", do_login
},
1033 { "quit", do_quit
},
1034 { "utime", do_utime
},
1037 static int ncommands
= sizeof(commands
)/sizeof(struct _command
);
1039 void exec_command (int command
)
1042 command
>= ncommands
||
1043 commands
[command
].command
== 0){
1044 fprintf (stderr
, "Got unknown command: %d\n", command
);
1047 if (verbose
) printf ("Command: %s\n", commands
[command
].command
);
1048 (*commands
[command
].callback
)();
1051 void check_version ()
1055 rpc_get (msock
, RPC_INT
, &version
, RPC_END
);
1057 version
<= RPC_PROGVER
)
1058 rpc_send (msock
, RPC_INT
, MC_VERSION_OK
, RPC_END
);
1060 rpc_send (msock
, RPC_INT
, MC_VERSION_MISMATCH
, RPC_END
);
1062 clnt_version
= version
;
1065 /* This routine is called by rpc_get/rpc_send when the connection is closed */
1066 void tcp_invalidate_socket (int sock
)
1068 if (verbose
) printf ("Connection closed\n");
1072 void server (int sock
)
1081 if (rpc_get (sock
, RPC_INT
, &command
, RPC_END
) &&
1082 (logged_in
|| command
== MC_LOGIN
))
1083 exec_command (command
);
1084 } while (!quit_server
);
1089 /* {{{ Net support code */
1091 char *get_client (int portnum
)
1093 int sock
, clilen
, newsocket
;
1094 struct sockaddr_in client_address
, server_address
;
1096 char hostname
[255];
1099 if ((sock
= socket (AF_INET
, SOCK_STREAM
, 0)) < 0)
1100 return "Can't create socket";
1102 /* Use this to debug: */
1103 if (setsockopt (sock
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &yes
, sizeof (yes
)) < 0)
1104 return "setsockopt failed";
1106 gethostname (hostname
, 255);
1107 if (verbose
) printf ("hostname=%s\n", hostname
);
1108 hp
= gethostbyname (hostname
);
1112 bzero ((char *) &server_address
, sizeof (server_address
));
1113 server_address
.sin_family
= hp
->h_addrtype
;
1114 server_address
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
1115 server_address
.sin_port
= htons (portnum
);
1117 if (bind (sock
, (struct sockaddr
*) &server_address
,
1118 sizeof (server_address
)) < 0)
1119 return "Can't bind";
1126 clilen
= sizeof (client_address
);
1127 newsocket
= accept (sock
, (struct sockaddr
*) &client_address
,
1130 if (isDaemon
&& (child
= fork())) {
1134 waitpid (child
, &status
, 0);
1138 if (isDaemon
&& fork()) exit (0);
1146 #ifdef HAVE_PMAP_SET
1147 void signal_int_handler (int sig
)
1149 pmap_unset (RPC_PROGNUM
, RPC_PROGVER
);
1153 #ifndef IPPORT_RESERVED
1154 #define IPPORT_RESERVED 1024;
1157 int get_port_number ()
1161 #ifdef HAVE_RRESVPORT
1162 int start_port
= IPPORT_RESERVED
;
1164 port
= rresvport (&start_port
);
1166 if (geteuid () == 0){
1167 fprintf (stderr
, "Could not bind the server on a reserved port\n");
1168 DO_QUIT_NONVOID (-1);
1176 port
= mcserver_port
;
1181 void register_port (int portnum
, int abort_if_fail
)
1183 #ifdef HAVE_PMAP_SET
1184 /* Register our service with the portmapper */
1185 /* protocol: pmap_set (prognum, versnum, protocol, portp) */
1187 if (pmap_set (RPC_PROGNUM
, RPC_PROGVER
, IPPROTO_TCP
, portnum
))
1188 signal (SIGINT
, signal_int_handler
);
1190 fprintf (stderr
, "Could not register service with portmapper\n");
1197 "This system lacks port registration, try using the -p\n"
1198 "flag to force installation at a given port");
1205 int main (int argc
, char *argv
[])
1208 extern char *optarg
;
1211 while ((c
= getopt (argc
, argv
, "fdiqp:v")) != -1){
1231 portnum
= atoi (optarg
);
1243 fprintf (stderr
, "Usage is: mcserv [options] [-p portnum]\n\n"
1245 "-d become a daemon (sets -q)\n"
1247 /* "-r use rhost based authentication\n" */
1249 "-f force ftp authentication\n"
1252 "-p to specify a port number to listen\n");
1258 if (isDaemon
&& fork()) exit (0);
1261 portnum
= get_port_number ();
1263 if (portnum
!= -1) {
1264 register_port (portnum
, 0);
1266 printf ("Using port %d\n", portnum
);
1267 if ((result
= get_client (portnum
)))
1269 #ifdef HAVE_PMAP_SET
1271 pmap_unset (RPC_PROGNUM
, RPC_PROGVER
);
1277 /* This functions are not used */
1278 void message (int is_error
, char *text
, char *msg
)
1280 printf ("%s %s\n", text
, msg
);
1283 char *unix_error_string (int a
)
1288 void vfs_die( char *m
)
1290 fprintf (stderr
, m
);
1294 char * mad_strconcat (const char *first
, ...)
1298 char *data
, *result
;
1303 len
= strlen (first
) + 1;
1304 va_start (ap
, first
);
1306 while ((data
= va_arg (ap
, char *)) != 0)
1307 len
+= strlen (data
);
1309 result
= g_malloc (len
);
1313 va_start (ap
, first
);
1314 strcpy (result
, first
);
1316 while ((data
= va_arg (ap
, char *)) != 0)
1317 strcat (result
, data
);
1323 #endif /* HAVE_MAD */