887 lines
21 KiB
C
887 lines
21 KiB
C
/*
|
|
* ncpmount.c
|
|
*
|
|
* Copyright (C) 1995 by Volker Lendecke
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include <pwd.h>
|
|
#include <grp.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/param.h>
|
|
#include <netinet/in.h>
|
|
#include <netdb.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
/* #include <sys/wait.h> */ /* generates a warning here */
|
|
extern pid_t waitpid(pid_t, int *, int);
|
|
#include <sys/errno.h>
|
|
#include <sys/time.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <sys/mount.h>
|
|
#include <mntent.h>
|
|
#include <linux/ipx.h>
|
|
#include <linux/route.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <linux/fs.h>
|
|
#include <linux/ncp.h>
|
|
#include <linux/ncp_fs.h>
|
|
#include <linux/ncp_mount.h>
|
|
#include "ipxutil.h"
|
|
#include "ncplib_user.h"
|
|
|
|
static char *progname;
|
|
|
|
|
|
static void
|
|
str_upper(char *name)
|
|
{
|
|
while (*name) {
|
|
*name = toupper(*name);
|
|
name = name + 1;
|
|
}
|
|
}
|
|
|
|
static void
|
|
usage(void)
|
|
{
|
|
printf("usage: %s server mount-point [options]\n", progname);
|
|
printf("Try `%s -h' for more information\n", progname);
|
|
}
|
|
|
|
static void
|
|
help(void)
|
|
{
|
|
printf("\n");
|
|
printf("usage: %s server mount-point [options]\n", progname);
|
|
printf("\n"
|
|
"-U username Username sent to server\n"
|
|
"-u uid uid the mounted files get\n"
|
|
"-g gid gid the mounted files get\n"
|
|
"-f mode permission the files get (octal notation)\n"
|
|
"-d mode permission the dirs get (octal notation)\n"
|
|
"-C Don't convert password to uppercase\n"
|
|
"-P password Use this password\n"
|
|
"-n Do not use any password\n"
|
|
" If neither -P nor -n are given, you are\n"
|
|
" asked for a password.\n"
|
|
"-h print this help text\n"
|
|
"\n");
|
|
}
|
|
|
|
struct sap_query {
|
|
unsigned short query_type; /* net order */
|
|
unsigned short server_type; /* net order */
|
|
};
|
|
|
|
struct sap_server_ident {
|
|
unsigned short server_type __attribute__ ((packed));
|
|
char server_name[48] __attribute__ ((packed));
|
|
IPXNet server_network __attribute__ ((packed));
|
|
IPXNode server_node __attribute__ ((packed));
|
|
IPXPort server_port __attribute__ ((packed));
|
|
unsigned short intermediate_network __attribute__ ((packed));
|
|
};
|
|
|
|
void
|
|
ipx_fprint_node(FILE* file,IPXNode node)
|
|
{
|
|
fprintf(file,"%02X%02X%02X%02X%02X%02X",
|
|
(unsigned char)node[0],
|
|
(unsigned char)node[1],
|
|
(unsigned char)node[2],
|
|
(unsigned char)node[3],
|
|
(unsigned char)node[4],
|
|
(unsigned char)node[5]
|
|
);
|
|
}
|
|
|
|
void
|
|
ipx_fprint_network(FILE* file,IPXNet net)
|
|
{
|
|
fprintf(file,"%08lX",ntohl(net));
|
|
}
|
|
|
|
void
|
|
ipx_fprint_port(FILE* file,IPXPort port)
|
|
{
|
|
fprintf(file,"%04X",ntohs(port));
|
|
}
|
|
|
|
void
|
|
ipx_fprint_saddr(FILE* file,struct sockaddr_ipx* sipx)
|
|
{
|
|
ipx_fprint_network(file,sipx->sipx_network);
|
|
fprintf(file,":");
|
|
ipx_fprint_node(file,sipx->sipx_node);
|
|
fprintf(file,":");
|
|
ipx_fprint_port(file,sipx->sipx_port);
|
|
}
|
|
|
|
void
|
|
ipx_print_node(IPXNode node)
|
|
{
|
|
ipx_fprint_node(stdout,node);
|
|
}
|
|
|
|
void
|
|
ipx_print_network(IPXNet net)
|
|
{
|
|
ipx_fprint_network(stdout,net);
|
|
}
|
|
|
|
void
|
|
ipx_print_port(IPXPort port)
|
|
{
|
|
ipx_fprint_port(stdout,port);
|
|
}
|
|
|
|
void
|
|
ipx_print_saddr(struct sockaddr_ipx* sipx)
|
|
{
|
|
ipx_fprint_saddr(stdout,sipx);
|
|
}
|
|
|
|
static int
|
|
ipx_make_reachable(__u32 network)
|
|
{
|
|
struct rtentry rt_def;
|
|
/* Router */
|
|
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rt_def.rt_gateway;
|
|
/* Target */
|
|
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rt_def.rt_dst;
|
|
|
|
fd_set rd, wr, ex;
|
|
struct timeval tv;
|
|
|
|
struct ipx_rip_packet rip;
|
|
struct sockaddr_ipx addr;
|
|
int addrlen;
|
|
int sock;
|
|
int opt;
|
|
int res=-1;
|
|
int i;
|
|
|
|
sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
|
|
|
if (sock == -1) {
|
|
return -1;
|
|
}
|
|
|
|
opt=1;
|
|
/* Permit broadcast output */
|
|
if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST, &opt,sizeof(opt))==-1)
|
|
{
|
|
perror("setsockopt");
|
|
goto finished;
|
|
}
|
|
|
|
memset(&addr, 0, sizeof(addr));
|
|
addr.sipx_family=AF_IPX;
|
|
addr.sipx_network=htonl(0x0);
|
|
addr.sipx_port=htons(0x0);
|
|
addr.sipx_type=IPX_RIP_PTYPE;
|
|
|
|
if(bind(sock,(struct sockaddr*)&addr,sizeof(addr))==-1)
|
|
{
|
|
perror("bind");
|
|
goto finished;
|
|
}
|
|
|
|
addr.sipx_family = AF_IPX;
|
|
addr.sipx_network = htonl(0x0);
|
|
addr.sipx_port = htons(IPX_RIP_PORT);
|
|
addr.sipx_type = IPX_RIP_PTYPE;
|
|
ipx_assign_node(addr.sipx_node, IPX_BROADCAST_NODE);
|
|
|
|
rip.operation = htons(IPX_RIP_REQUEST);
|
|
rip.rt[0].network = htonl(network);
|
|
|
|
if (sendto(sock, &rip, sizeof(rip), 0,
|
|
(struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
perror("sendto");
|
|
goto finished;
|
|
}
|
|
|
|
do
|
|
{
|
|
|
|
FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex);
|
|
FD_SET(sock, &rd);
|
|
|
|
tv.tv_sec = 3;
|
|
tv.tv_usec = 0;
|
|
|
|
if (select(sock+1, &rd, &wr, &ex, &tv) == -1)
|
|
{
|
|
goto finished;
|
|
}
|
|
|
|
if (FD_ISSET(sock, &rd))
|
|
{
|
|
int len;
|
|
|
|
addrlen = sizeof(struct sockaddr_ipx);
|
|
|
|
len = recvfrom(sock, &rip, sizeof(rip), 0,
|
|
(struct sockaddr *)sr, &addrlen);
|
|
|
|
if (len < sizeof(rip))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
goto finished;
|
|
}
|
|
} while (ntohs(rip.operation) != IPX_RIP_RESPONSE);
|
|
|
|
if (rip.rt[0].network != htonl(network)) {
|
|
goto finished;
|
|
}
|
|
|
|
rt_def.rt_flags = RTF_GATEWAY;
|
|
st->sipx_network = htonl(network);
|
|
sr->sipx_family = st->sipx_family = AF_IPX;
|
|
i = 0;
|
|
do {
|
|
res = ioctl(sock, SIOCADDRT, &rt_def);
|
|
i++;
|
|
} while ((i < 5) && (res < 0) && (errno == EAGAIN));
|
|
|
|
if (res != 0) {
|
|
|
|
switch (errno) {
|
|
case ENETUNREACH:
|
|
fprintf(stderr,
|
|
"%s: Router network (%08lX) not reachable.\n",
|
|
progname, htonl(sr->sipx_network));
|
|
break;
|
|
default:
|
|
perror("ioctl");
|
|
break;
|
|
}
|
|
goto finished;
|
|
}
|
|
|
|
finished:
|
|
close(sock);
|
|
return res;
|
|
}
|
|
|
|
int
|
|
ipx_sap_find_server(char *name, int server_type, int timeout,
|
|
struct sockaddr_ipx *result)
|
|
{
|
|
struct sockaddr_ipx ipxs;
|
|
char data[1024];
|
|
int sock;
|
|
int opt;
|
|
int res = -1;
|
|
int name_len = strlen(name);
|
|
fd_set rd, wr, ex;
|
|
struct timeval tv;
|
|
struct sap_server_ident *ident;
|
|
|
|
struct ncp_server server;
|
|
struct nw_property prop;
|
|
struct net_address
|
|
{
|
|
__u32 network __attribute__ ((packed));
|
|
__u8 node[6] __attribute__ ((packed));
|
|
__u16 port __attribute__ ((packed));
|
|
} *n_addr = (struct net_address *)∝
|
|
|
|
|
|
if (name_len > 48) {
|
|
return -1;
|
|
}
|
|
|
|
sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX);
|
|
if (sock==-1) {
|
|
return -1;
|
|
}
|
|
|
|
opt=1;
|
|
/* Permit broadcast output */
|
|
if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST, &opt,sizeof(opt))==-1)
|
|
{
|
|
perror("setsockopt");
|
|
goto finished;
|
|
}
|
|
|
|
memset(&ipxs, 0, sizeof(ipxs));
|
|
ipxs.sipx_family=AF_IPX;
|
|
ipxs.sipx_network=htonl(0x0);
|
|
ipxs.sipx_port=htons(0x0);
|
|
ipxs.sipx_type=IPX_SAP_PTYPE;
|
|
|
|
if(bind(sock,(struct sockaddr*)&ipxs,sizeof(ipxs))==-1)
|
|
{
|
|
perror("bind");
|
|
goto finished;
|
|
}
|
|
|
|
*(unsigned short *)data = htons(IPX_SAP_NEAREST_QUERY);
|
|
*(unsigned short *)&(data[2]) = htons(server_type);
|
|
|
|
memset(&ipxs, 0, sizeof(ipxs));
|
|
ipxs.sipx_family=AF_IPX;
|
|
ipxs.sipx_network=htonl(0x0);
|
|
ipx_assign_node(ipxs.sipx_node, IPX_BROADCAST_NODE);
|
|
ipxs.sipx_port=htons(IPX_SAP_PORT);
|
|
ipxs.sipx_type=IPX_SAP_PTYPE;
|
|
|
|
if (sendto(sock, data, 4, 0,
|
|
(struct sockaddr *)&ipxs, sizeof(ipxs)) < 0)
|
|
{
|
|
perror("sendto");
|
|
goto finished;
|
|
}
|
|
|
|
do
|
|
{
|
|
|
|
FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex);
|
|
FD_SET(sock, &rd);
|
|
|
|
tv.tv_sec = timeout;
|
|
tv.tv_usec = 0;
|
|
|
|
if (select(sock+1, &rd, &wr, &ex, &tv) == -1)
|
|
{
|
|
goto finished;
|
|
}
|
|
|
|
if (FD_ISSET(sock, &rd))
|
|
{
|
|
int len = recv(sock, data, 1024, 0);
|
|
|
|
if (len < 96)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
goto finished;
|
|
}
|
|
} while (ntohs(*((__u16 *)data)) != IPX_SAP_NEAREST_RESPONSE);
|
|
|
|
ident = (struct sap_server_ident *)(data+2);
|
|
|
|
/* If the server we got back is the correct one, we normally
|
|
would not need to ask for the NET_ADDRESS property. But we
|
|
try to connect anyway to check whether there's a valid
|
|
route to the server's internal network. Because this one
|
|
request is not very expensive, we always do it. */
|
|
|
|
server.addr.sipx_family = AF_IPX;
|
|
server.addr.sipx_network = ident->server_network;
|
|
server.addr.sipx_port = ident->server_port;
|
|
ipx_assign_node(server.addr.sipx_node, ident->server_node);
|
|
|
|
if (ncp_connect(&server) != 0)
|
|
{
|
|
if ( (errno != ENETUNREACH)
|
|
|| (ipx_make_reachable(ntohl(server.addr.sipx_network))!=0)
|
|
|| (ncp_connect(&server) != 0)) {
|
|
goto finished;
|
|
}
|
|
}
|
|
|
|
if (ncp_read_property_value(&server, NCP_BINDERY_FSERVER,
|
|
name, 1, "NET_ADDRESS",
|
|
&prop) != 0)
|
|
{
|
|
ncp_disconnect(&server);
|
|
goto finished;
|
|
}
|
|
|
|
if (ncp_disconnect(&server) != 0)
|
|
{
|
|
goto finished;
|
|
}
|
|
|
|
result->sipx_family = AF_IPX;
|
|
result->sipx_network = n_addr->network;
|
|
result->sipx_port = n_addr->port;
|
|
ipx_assign_node(result->sipx_node, n_addr->node);
|
|
|
|
/* Now we connect to the ultimate target, again with a test
|
|
for reachability. This time nothing is done except connecting. */
|
|
|
|
server.addr = *result;
|
|
|
|
if (ncp_connect(&server) != 0)
|
|
{
|
|
if ( (errno != ENETUNREACH)
|
|
|| (ipx_make_reachable(ntohl(server.addr.sipx_network))!=0)
|
|
|| (ncp_connect(&server) != 0)) {
|
|
goto finished;
|
|
}
|
|
}
|
|
|
|
if (ncp_disconnect(&server) != 0)
|
|
{
|
|
goto finished;
|
|
}
|
|
|
|
res = 0;
|
|
|
|
|
|
finished:
|
|
close(sock);
|
|
return res;
|
|
}
|
|
|
|
int
|
|
ipx_sscanf_node(char *buf, unsigned char node[6])
|
|
{
|
|
int i;
|
|
int n[6];
|
|
|
|
if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x",
|
|
&(n[0]), &(n[1]), &(n[2]),
|
|
&(n[3]), &(n[4]), &(n[5]))) != 6) {
|
|
return i;
|
|
}
|
|
|
|
for (i=0; i<6; i++) {
|
|
node[i] = n[i];
|
|
}
|
|
return 6;
|
|
}
|
|
|
|
static int
|
|
parse_args(int argc, char *argv[], struct ncp_mount_data *data,
|
|
int *got_password, int *upcase_password)
|
|
{
|
|
int opt;
|
|
struct passwd *pwd;
|
|
struct group *grp;
|
|
|
|
*got_password = 0;
|
|
*upcase_password = 1;
|
|
|
|
while ((opt = getopt (argc, argv, "Cp:s:c:U:u:g:f:d:m:P:n")) != EOF) {
|
|
switch (opt) {
|
|
case 'C':
|
|
*upcase_password = 0;
|
|
break;
|
|
case 'U':
|
|
if (strlen(optarg) > 63) {
|
|
fprintf(stderr, "Username too long: %s\n",
|
|
optarg);
|
|
return 1;
|
|
}
|
|
strcpy(data->username, optarg);
|
|
break;
|
|
case 'u':
|
|
if (isdigit(optarg[0])) {
|
|
data->uid = atoi(optarg);
|
|
} else {
|
|
pwd = getpwnam(optarg);
|
|
if (pwd == NULL) {
|
|
fprintf(stderr, "Unknown user: %s\n",
|
|
optarg);
|
|
return 1;
|
|
}
|
|
data->uid = pwd->pw_uid;
|
|
}
|
|
break;
|
|
case 'g':
|
|
if (isdigit(optarg[0])) {
|
|
data->gid = atoi(optarg);
|
|
} else {
|
|
grp = getgrnam(optarg);
|
|
if (grp == NULL) {
|
|
fprintf(stderr, "Unknown group: %s\n",
|
|
optarg);
|
|
return 1;
|
|
}
|
|
data->gid = grp->gr_gid;
|
|
}
|
|
break;
|
|
case 'f':
|
|
data->file_mode = strtol(optarg, NULL, 8);
|
|
break;
|
|
case 'd':
|
|
data->dir_mode = strtol(optarg, NULL, 8);
|
|
break;
|
|
case 'P':
|
|
strcpy(data->password, optarg);
|
|
*got_password = 1;
|
|
break;
|
|
case 'n':
|
|
data->password[0] = '\0';
|
|
*got_password = 1;
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* Returns 0 if the filesystem is in the kernel after this routine
|
|
completes */
|
|
static int
|
|
load_ncpfs()
|
|
{
|
|
FILE *fver, *ffs;
|
|
char s[1024];
|
|
char modname[1024];
|
|
char *p, *p1;
|
|
pid_t pid;
|
|
int status;
|
|
|
|
/* Check if ncpfs is in the kernel */
|
|
ffs = fopen("/proc/filesystems", "r");
|
|
if (ffs == NULL) {
|
|
perror("Error: \"/proc/filesystems\" could not be read:");
|
|
return -1;
|
|
}
|
|
p = NULL;
|
|
while (! feof(ffs)) {
|
|
p1 = fgets(s, sizeof(s), ffs);
|
|
if (p1) {
|
|
p = strstr(s, "ncpfs");
|
|
if (p) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
fclose(ffs);
|
|
if (p) {
|
|
return 0;
|
|
}
|
|
fver = fopen("/proc/version", "r");
|
|
if (fver == NULL) {
|
|
perror("Error: \"/proc/version\" could not be read:");
|
|
return -1;
|
|
}
|
|
fgets(s, 1024, fver);
|
|
fclose(fver);
|
|
p = strstr(s, "version ");
|
|
if (p == NULL) {
|
|
version_error:
|
|
fprintf(stderr, "Error: Unable to determine the Linux version"
|
|
"from \"/proc/version\n");
|
|
return -1;
|
|
}
|
|
p = strchr(p, ' ') + 1;
|
|
p1 = strchr(p, ' ');
|
|
if (p1 == NULL) {
|
|
goto version_error;
|
|
}
|
|
strcpy(modname, "/lib/modules/");
|
|
strncat(modname, p, p1 - p);
|
|
strcat(modname, "/ncpfs.o");
|
|
|
|
/* system() function without signal handling, from Stevens */
|
|
|
|
if ((pid = fork()) < 0) {
|
|
return 1;
|
|
} else if (pid == 0) {
|
|
/* child */
|
|
execl("/sbin/insmod", "insmod", modname, NULL);
|
|
_exit(127); /* execl error */
|
|
} else {
|
|
/* parent */
|
|
while (waitpid(pid, &status, 0) < 0) {
|
|
if (errno != EINTR) {
|
|
status = -1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/* Check whether user is allowed to mount on the specified mount point */
|
|
static int
|
|
mount_ok(struct stat *st)
|
|
{
|
|
if (!S_ISDIR(st->st_mode))
|
|
{
|
|
errno = ENOTDIR;
|
|
return -1;
|
|
}
|
|
|
|
if ( (getuid() != 0)
|
|
&& ( (getuid() != st->st_uid)
|
|
|| ((st->st_mode & S_IRWXU) != S_IRWXU)))
|
|
{
|
|
errno = EPERM;
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
struct ncp_mount_data data;
|
|
struct sockaddr_ipx addr;
|
|
struct stat st;
|
|
struct ncp_server serv;
|
|
struct ncp_server *server = &serv;
|
|
char mount_name[256];
|
|
|
|
int fd;
|
|
int Got_Password;
|
|
int Upcase_Password;
|
|
int um;
|
|
unsigned int flags;
|
|
char hostname[MAXHOSTNAMELEN + 1];
|
|
|
|
char *server_name;
|
|
char mount_point[MAXPATHLEN];
|
|
|
|
struct mntent ment;
|
|
FILE *mtab;
|
|
|
|
int ncp_sock, wdog_sock;
|
|
|
|
progname = argv[0];
|
|
|
|
if (geteuid() != 0) {
|
|
fprintf(stderr, "%s must be installed suid root\n", progname);
|
|
exit(1);
|
|
}
|
|
|
|
memset(&data, 0, sizeof(struct ncp_mount_data));
|
|
|
|
memset(hostname, '\0', MAXHOSTNAMELEN+1);
|
|
gethostname(hostname, MAXHOSTNAMELEN);
|
|
|
|
if (argc < 3) {
|
|
if ( (argc == 2)
|
|
&& (argv[1][0] == '-')
|
|
&& (argv[1][1] == 'h')
|
|
&& (argv[1][2] == '\0')) {
|
|
|
|
help();
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
usage();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
server_name = argv[1];
|
|
str_upper(server_name);
|
|
|
|
realpath(argv[2], mount_point);
|
|
|
|
argv += 2;
|
|
argc -= 2;
|
|
|
|
if (stat(mount_point, &st) == -1) {
|
|
fprintf(stderr, "could not find mount point %s: %s\n",
|
|
mount_point, strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
if (mount_ok(&st) != 0) {
|
|
fprintf(stderr, "cannot to mount on %s: %s\n",
|
|
mount_point, strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
ncp_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
|
if (ncp_sock == -1) {
|
|
fprintf(stderr, "could not open ncp socket: %s\n",
|
|
strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
wdog_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
|
if (wdog_sock == -1) {
|
|
fprintf(stderr, "could not open wdog socket: %s\n",
|
|
strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
addr.sipx_type = NCP_PTYPE;
|
|
|
|
if (bind(ncp_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
|
fprintf(stderr, "\nbind: %s\n",
|
|
strerror(errno));
|
|
fprintf(stderr,
|
|
"\nMaybe you want to use \n"
|
|
"ipx_configure --auto_interface=on --auto_primary=on\n"
|
|
"and try again after waiting a minute.\n\n");
|
|
exit(1);
|
|
}
|
|
|
|
if (bind(wdog_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
|
fprintf(stderr, "bind(wdog_sock, ): %s\n",
|
|
strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
if (ipx_sap_find_server(server_name, IPX_SAP_FILE_SERVER,
|
|
3, &addr) != 0) {
|
|
fprintf(stderr, "could not find server %s\n", server_name);
|
|
exit(1);
|
|
}
|
|
|
|
/* Check if the ncpfs filesystem is in the kernel. If not, attempt
|
|
* to load the ncpfs module */
|
|
if (load_ncpfs() != 0) {
|
|
fprintf(stderr, "Error: Unable to start ncpfs, exiting...\n");
|
|
exit(1);
|
|
}
|
|
|
|
data.version = NCP_MOUNT_VERSION;
|
|
data.ncp_fd = ncp_sock;
|
|
data.wdog_fd = wdog_sock;
|
|
data.mounted_uid = getuid();
|
|
data.serv_addr = addr;
|
|
strcpy(data.server_name, server_name);
|
|
data.time_out = 20; /* 2 seconds */
|
|
data.retry_count = 2;
|
|
|
|
/* getuid() gives us the real uid, who may umount the fs */
|
|
data.mounted_uid = getuid();
|
|
|
|
if (getenv("USER")) {
|
|
strcpy(data.username, getenv("USER"));
|
|
str_upper(data.username);
|
|
}
|
|
|
|
if (data.username[0] == 0 && getenv("LOGNAME"))
|
|
{
|
|
strcpy(data.username,getenv("LOGNAME"));
|
|
str_upper(data.username);
|
|
}
|
|
|
|
data.uid = getuid();
|
|
data.gid = getgid();
|
|
um = umask(0);
|
|
umask(um);
|
|
data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & ~um;
|
|
data.dir_mode = 0;
|
|
|
|
if (parse_args(argc, argv, &data, &Got_Password,
|
|
&Upcase_Password) != 0) {
|
|
usage();
|
|
return -1;
|
|
}
|
|
|
|
if (data.dir_mode == 0) {
|
|
data.dir_mode = data.file_mode;
|
|
if ((data.dir_mode & S_IRUSR) != 0)
|
|
data.dir_mode |= S_IXUSR;
|
|
if ((data.dir_mode & S_IRGRP) != 0)
|
|
data.dir_mode |= S_IXGRP;
|
|
if ((data.dir_mode & S_IROTH) != 0)
|
|
data.dir_mode |= S_IXOTH;
|
|
}
|
|
|
|
if (Got_Password == 0) {
|
|
strcpy(data.password, getpass("Password: "));
|
|
}
|
|
|
|
if (Upcase_Password == 1) {
|
|
str_upper(data.password);
|
|
}
|
|
|
|
if (data.server_name[0] == '\0') {
|
|
strcpy(data.server_name, server_name);
|
|
str_upper(data.server_name);
|
|
}
|
|
|
|
flags = MS_MGC_VAL;
|
|
|
|
if (mount(NULL, mount_point, "ncpfs",
|
|
flags, (char *)&data) < 0) {
|
|
printf("mount failed\n");
|
|
close(wdog_sock);
|
|
close(ncp_sock);
|
|
return -1;
|
|
}
|
|
|
|
close(ncp_sock);
|
|
close(wdog_sock);
|
|
|
|
if (ncp_connect_mount(server, mount_point) != 0) {
|
|
fprintf(stderr, "Could not open %s: %s\n",
|
|
mount_point, strerror(errno));
|
|
umount(mount_point);
|
|
return -1;
|
|
}
|
|
server->silent = 1;
|
|
|
|
if (ncp_login_user(server, data.username, data.password) != 0) {
|
|
fprintf(stderr, "login failed\n");
|
|
fprintf(stderr,
|
|
"should try to type the username and\n"
|
|
"password in UPPERCASE.\n");
|
|
close(server->mount_fid);
|
|
umount(mount_point);
|
|
return -1;
|
|
}
|
|
|
|
strcpy(mount_name, server_name);
|
|
strcat(mount_name, "/");
|
|
strcat(mount_name, data.username);
|
|
|
|
ment.mnt_fsname = mount_name;
|
|
ment.mnt_dir = mount_point;
|
|
ment.mnt_type = "ncpfs";
|
|
ment.mnt_opts = "rw";
|
|
ment.mnt_freq = 0;
|
|
ment.mnt_passno= 0;
|
|
|
|
if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
|
|
{
|
|
fprintf(stderr, "Can't get "MOUNTED"~ lock file");
|
|
return 1;
|
|
}
|
|
close(fd);
|
|
|
|
if ((mtab = setmntent(MOUNTED, "a+")) == NULL)
|
|
{
|
|
fprintf(stderr, "Can't open " MOUNTED);
|
|
return 1;
|
|
}
|
|
|
|
if (addmntent(mtab, &ment) == 1)
|
|
{
|
|
fprintf(stderr, "Can't write mount entry");
|
|
return 1;
|
|
}
|
|
if (fchmod(fileno(mtab), 0644) == -1)
|
|
{
|
|
fprintf(stderr, "Can't set perms on "MOUNTED);
|
|
return 1;
|
|
}
|
|
endmntent(mtab);
|
|
|
|
if (unlink(MOUNTED"~") == -1)
|
|
{
|
|
fprintf(stderr, "Can't remove "MOUNTED"~");
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|