640 lines
12 KiB
C
640 lines
12 KiB
C
/*
|
|
* ncptest.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/time.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/ioctl.h>
|
|
/* #include <sys/wait.h> */ /* generates a warning here */
|
|
extern pid_t waitpid(pid_t, int *, int);
|
|
#include <sys/errno.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/fs.h>
|
|
#include <linux/ncp.h>
|
|
#include <linux/ncp_fs.h>
|
|
#include <linux/ncp_mount.h>
|
|
#include "ncplib_user.h"
|
|
#include "ipxutil.h"
|
|
|
|
static char *progname;
|
|
|
|
static void
|
|
str_upper(char *name)
|
|
{
|
|
while (*name) {
|
|
*name = toupper(*name);
|
|
name = name + 1;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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;
|
|
char name[strlen(_name)+1];
|
|
int name_len = strlen(_name);
|
|
fd_set rd, wr, ex;
|
|
struct timeval tv;
|
|
int packets;
|
|
|
|
if (name_len > 48) {
|
|
return -1;
|
|
}
|
|
|
|
strcpy(name, _name);
|
|
str_upper(name);
|
|
|
|
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(0x0001);
|
|
*(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;
|
|
}
|
|
|
|
packets = 10;
|
|
while (packets > 0) {
|
|
|
|
packets -= 1;
|
|
|
|
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) {
|
|
perror("select");
|
|
goto finished;
|
|
}
|
|
|
|
if (FD_ISSET(sock, &rd)) {
|
|
int len = recv(sock, data, 1024, 0);
|
|
int i;
|
|
struct sap_server_ident *ident;
|
|
|
|
for (i = 2; i < len; i += 64) {
|
|
ident = (struct sap_server_ident *)(data+i);
|
|
if ( (strncmp(name,ident->server_name,
|
|
name_len)==0)
|
|
&& (name_len < 48)
|
|
&& (ident->server_name[name_len] == '\0'))
|
|
{
|
|
result->sipx_family = AF_IPX;
|
|
result->sipx_network =
|
|
ident->server_network;
|
|
result->sipx_port = ident->server_port;
|
|
ipx_assign_node(result->sipx_node,
|
|
ident->server_node);
|
|
res = 0;
|
|
goto finished;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("nobody answered, server %s not found\n",
|
|
name);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
void
|
|
test_filesearch(struct ncp_server *server)
|
|
{
|
|
struct ncp_filesearch_info fsinfo;
|
|
struct ncp_file_info finfo;
|
|
|
|
if (ncp_file_search_init(server, 0, "sys:\\public", &fsinfo) != 0) {
|
|
printf("could not fs init\n");
|
|
return;
|
|
}
|
|
|
|
while (ncp_file_search_continue(server, &fsinfo,
|
|
0,
|
|
"*", &finfo) == 0) {
|
|
printf("name: %s\n", finfo.file_name);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void
|
|
test_getfinfo(struct ncp_server *server)
|
|
{
|
|
struct ncp_file_info finfo;
|
|
|
|
ncp_get_finfo(server, 0, "sys:", "public", &finfo);
|
|
ncp_get_finfo(server, 0, "sys:login", "login.exe", &finfo);
|
|
}
|
|
|
|
void
|
|
testopen(struct ncp_server *server)
|
|
{
|
|
struct ncp_file_info finfo;
|
|
char buf[1025];
|
|
int bytes_read;
|
|
|
|
ncp_open_file(server, 0, "sys:\\etc\\samples\\protocol", 0,
|
|
AR_READ|AR_WRITE,
|
|
&finfo);
|
|
if (ncp_read(server, finfo.file_id, 0, 1024, buf, &bytes_read) == 0) {
|
|
printf("bytes: %d\n", bytes_read);
|
|
buf[bytes_read]=0;
|
|
puts(buf);
|
|
}
|
|
|
|
ncp_close_file(server, finfo.file_id);
|
|
}
|
|
|
|
void
|
|
testcreate(struct ncp_server *server)
|
|
{
|
|
|
|
if (ncp_rename_file(server, 0, "sys:\\me\\blub.txt", 0,
|
|
0, "sys:\\me\\blub1.txt") != 0) {
|
|
printf("create war nix\n");
|
|
}
|
|
if (ncp_create_directory(server, 0, "sys:\\me\\blubdir", 0xff) != 0) {
|
|
printf("mkdir war nix\n");
|
|
}
|
|
if (ncp_rename_directory(server, 0, "sys:\\me\\blubdir",
|
|
"\\me\\blubneu") != 0) {
|
|
printf("mvdir war nix\n");
|
|
return;
|
|
}
|
|
if (ncp_delete_directory(server, 0, "sys:\\me\\blubneu") != 0) {
|
|
printf("rmdir war nix\n");
|
|
return;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void
|
|
test_lookup(struct ncp_server *server)
|
|
{
|
|
struct nw_info_struct sys;
|
|
struct nw_info_struct me;
|
|
struct nw_file_info blub;
|
|
|
|
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
|
|
if (ncp_open_create_file_or_subdir(server, &me, "BLUB.TXT",
|
|
OC_MODE_CREATE, 0, 0xffff,
|
|
&blub) != 0) {
|
|
printf("open error\n");
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void
|
|
test_trunc(struct ncp_server *server)
|
|
{
|
|
struct nw_info_struct sys;
|
|
struct nw_info_struct me;
|
|
struct nw_file_info blub;
|
|
int written;
|
|
|
|
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
if (ncp_do_lookup(server, &me, "BLUB.TXT", &(blub.i)) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
|
|
if (ncp_open_create_file_or_subdir(server, &(blub.i), NULL,
|
|
OC_MODE_OPEN, 0, AR_READ | AR_WRITE,
|
|
&blub) != 0) {
|
|
printf("open error\n");
|
|
return;
|
|
}
|
|
|
|
if (ncp_write(server, blub.file_handle, 4, 0, "", &written) != 0) {
|
|
printf("trunc error\n");
|
|
return;
|
|
}
|
|
|
|
if (ncp_close_file(server, blub.file_handle) != 0) {
|
|
printf("close error\n");
|
|
return;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
test_touch(struct ncp_server *server)
|
|
{
|
|
struct nw_info_struct sys;
|
|
struct nw_info_struct me;
|
|
struct nw_info_struct blub;
|
|
int info_mask;
|
|
struct nw_modify_dos_info info;
|
|
|
|
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
if (ncp_do_lookup(server, &me, "BLUB.TXT", &blub) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
|
|
info_mask = 0;
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
info_mask |= DM_MODIFY_DATE;
|
|
info_mask |= DM_MODIFY_TIME;
|
|
|
|
if (ncp_modify_file_or_subdir_dos_info(server, &blub, info_mask,
|
|
&info) != 0) {
|
|
printf("modify error\n");
|
|
return;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
test_ls(struct ncp_server *server)
|
|
{
|
|
struct nw_info_struct sys;
|
|
struct nw_search_sequence seq;
|
|
struct nw_info_struct found;
|
|
int res;
|
|
|
|
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
if (ncp_initialize_search(server, &sys, &seq) != 0) {
|
|
printf("init error\n");
|
|
return;
|
|
}
|
|
while ((res=ncp_search_for_file_or_subdir(server,&seq,&found)) == 0) {
|
|
printf("found %s: %s\n",
|
|
(found.attributes & aDIR) ? "dir " : "file",
|
|
found.entryName);
|
|
}
|
|
|
|
if (res == 0xfe) {
|
|
printf("result: no more files\n");
|
|
}
|
|
else
|
|
{
|
|
printf("other error: %x\n", res);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void
|
|
test_ren(struct ncp_server *server)
|
|
{
|
|
struct nw_info_struct sys;
|
|
struct nw_info_struct me;
|
|
|
|
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
if (ncp_ren_or_mov_file_or_subdir(server, &me, "BLUB.TXT",
|
|
&me, "BLUB1.TXT") != 0) {
|
|
printf("ren error\n");
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
test_rm(struct ncp_server *server)
|
|
{
|
|
struct nw_info_struct sys;
|
|
struct nw_info_struct me;
|
|
|
|
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
if (ncp_del_file_or_subdir(server, &me, "BLUB1.TXT") != 0) {
|
|
printf("ren error\n");
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
test_mkdir(struct ncp_server *server)
|
|
{
|
|
struct nw_info_struct sys;
|
|
struct nw_info_struct me;
|
|
struct nw_file_info dir1;
|
|
struct nw_file_info dir2;
|
|
|
|
|
|
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
|
|
printf("lookup error\n");
|
|
return;
|
|
}
|
|
if (ncp_open_create_file_or_subdir(server, &me, "DIR1",
|
|
OC_MODE_CREATE, aDIR, 0xffff, &dir1)
|
|
!= 0) {
|
|
printf("mkdir1 error\n");
|
|
return;
|
|
}
|
|
if (ncp_open_create_file_or_subdir(server, &me, "DIR2",
|
|
OC_MODE_CREATE, aDIR, 0xffff, &dir2)
|
|
!= 0) {
|
|
printf("mkdir2 error\n");
|
|
return;
|
|
}
|
|
|
|
if (ncp_del_file_or_subdir(server, &me, "DIR1") != 0) {
|
|
printf("rmdir error\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
test_print(struct ncp_server *server)
|
|
{
|
|
struct ncp_bindery_object q;
|
|
struct queue_job j;
|
|
struct print_job_record pj;
|
|
int written;
|
|
|
|
if (ncp_get_bindery_object_id(server, NCP_BINDERY_PQUEUE,
|
|
"Q_DJ500", &q) != 0) {
|
|
printf("get oid error\n");
|
|
return;
|
|
}
|
|
|
|
memset(&j, 0, sizeof(j));
|
|
|
|
j.j.TargetServerID = 0xffffffff; /* any server */
|
|
memset(&(j.j.TargetExecTime), 0xff, sizeof(j.j.TargetExecTime)); /* at once */
|
|
j.j.JobType = 0xffff;
|
|
strcpy(j.j.JobTextDescription, "Test Job");
|
|
|
|
memset(&pj, 0, sizeof(pj));
|
|
|
|
pj.Version = 0;
|
|
pj.TabSize = 0;
|
|
pj.Copies = 1;
|
|
pj.CtrlFlags = 0;
|
|
pj.Lines = 0;
|
|
pj.Rows = 0;
|
|
strcpy(pj.FormName, "");
|
|
strcpy(pj.Banner, "");
|
|
strcpy(pj.FnameBanner, "");
|
|
strcpy(pj.FnameHeader, "");
|
|
strcpy(pj.Path, "");
|
|
|
|
memcpy(j.j.ClientRecordArea, &pj, sizeof(pj));
|
|
|
|
if (ncp_create_queue_job_and_file(server, q.object_id, &j) != 0) {
|
|
printf("create error\n");
|
|
return;
|
|
}
|
|
|
|
if (ncp_write(server, j.file_handle, 0, 5, "hallo", &written) != 0) {
|
|
printf("write error\n");
|
|
return;
|
|
}
|
|
|
|
if (ncp_close_file_and_start_job(server, q.object_id, &j) != 0) {
|
|
printf("close error\n");
|
|
return;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
struct ncp_server serv;
|
|
struct ncp_server *server = &serv;
|
|
|
|
progname = argv[0];
|
|
|
|
if (argc != 2) {
|
|
printf("usage: %s server\n", argv[0]);
|
|
exit(1);
|
|
}
|
|
|
|
if (ipx_sap_find_server(argv[1], IPX_SAP_FILE_SERVER,
|
|
3, &(serv.addr)) != 0) {
|
|
printf("could not find server %s\n", argv[1]);
|
|
exit(1);
|
|
}
|
|
|
|
if (ncp_connect(server) != 0) {
|
|
printf("could not connect\n");
|
|
exit(1);
|
|
}
|
|
|
|
if (ncp_login_user(server, "me", "ME") != 0) {
|
|
printf("login error\n");
|
|
exit(1);
|
|
}
|
|
|
|
getchar();
|
|
|
|
ncp_disconnect(server);
|
|
|
|
|
|
return 0;
|
|
}
|
|
|