home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------------------*
- * tnet.c -- network client application
- *
- * The main routine establishes communications with the
- * tnet ``server,'' then accepts commands from the user.
- * Each command is then serviced by one of the ``cmd_xxx()''
- * routines below.
- *
- * T. Nolan - 11/20/89
- *-------------------------------------------------------------------------*/
-
- #include <dos.h>
- #include <process.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
-
- #include "netbios.h"
- #include "network.h"
-
- #define NARGS 10 /* max number of command arguments */
-
- int exitflag;
- char local[16]; /* node name of local machine */
- char remote[16]; /* node name of remote server */
- char buf[4096]; /* buffer for file read/write */
-
- extern int nb_errno; /* netbios error return */
-
- /*-------------------------------------------------------------------------*/
- main(int ac, char **av)
- {
- ACTION ncmd, rcmd; /* send and receive cmd blocks */
- NCB ncb; /* NetBIOS ncb */
- long ltime; /* for timeout */
- char *argv[NARGS]; /* array of parsed command args */
- int argc; /* number of command args */
- char line[80]; /* buffer for command line */
-
- printf("Tnet - T. Nolan 11/20/89\n");
-
- /* Post a receive-datagram, and send out a connect request.
- * Use the command-line arg as the server node name and
- * request via datagram. Set a 5-second timeout, and wait for
- * something to happen.
- */
-
- if(ac == 1)
- {
- printf("Format is TNET \\\\nodeid");
- exit(1);
- }
-
- clear_ncb(&ncb);
- nw_recv_datagram(&rcmd, sizeof(ACTION), &ncb);
- ncmd.type = NET_CNCT;
- ncmd.code = 0;
- while(1)
- {
- time(<ime);
- printf("Trying to locate Tnet server...\n");
- strcpy(remote, av[1]);
- send_datagram(remote, &ncmd, sizeof(ACTION));
-
- while((time(0) < ltime + 5) && !kbhit() && (ncb.cmdcplt == 0xff))
- ;
-
- /* Figure out what happened. */
-
- if(kbhit()) /* keyboard interrupt */
- {
- if(!getch())
- getch();
- nb_cancel(&ncb);
- exit(1);
- }
-
- if(ncb.cmdcplt != 0xff) /* command completed */
- {
- if(ncb.retcode)
- {
- printf("NetBIOS error %x\n", ncb.retcode);
- exit(1);
- }
- if(rcmd.type != NET_CNCT || rcmd.code != NET_ACK)
- {
- printf("NetBIOS not installed\n");
- exit(1);
- }
- break; /* exit from loop */
- }
- } /* must have timed out.. try again */
-
- /* If we get here, we've had a successful datagram exchange
- * with the server. The server's node name appears in
- * the ncb, and our node name appears in the rcmd.
- */
-
- namecpy(remote, ncb.callname);
- namecpy(local, rcmd.name);
-
- printf("\Tnet node %s connected to server node %s\n", local, remote);
-
- /* Command loop. Write the prompt, get a command. Split
- * the command into its component strings and tokenize
- * the command name. Invoke the appropriate handler.
- */
-
- while(!exitflag)
- {
- printf("\nTnet> "); /* prompt user for command */
- gets(line); /* read command line */
- argc = reargv(strlwr(line), argv); /* separate arguments */
- if(!argc)
- continue; /* nothing to do... */
- if(*argv[0] == '!') /* "shell out" prefix */
- {
- argv[0]++;
- shell(argc, argv);
- continue;
- }
-
- switch(parse(argv[0])) /* look at 1st arg */
- {
- case -1 :
-
- printf("Ambiguous command\n");
- cmd_help();
- break;
-
- case 0 :
-
- cmd_remote(argc, argv);
- break;
-
- case 1 :
-
- cmd_get (argc, argv);
- break;
-
- case 2 :
-
- cmd_put (argc, argv);
- break;
-
- case 3 :
-
- cmd_chd (argc, argv);
- break;
-
- case 4 :
-
- cmd_help(argc, argv);
- break;
-
- case 5 :
-
- cmd_bye (argc, argv);
- break;
-
- case 6 :
-
- cmd_dir (argc, argv);
- break;
-
- case 7 :
- case 8 :
-
- cmd_del (argc, argv);
- break;
-
- case 9 :
-
- exitflag = 1;
- break;
- }
- }
- exit(0);
- }
-
- /*-------------------------------------------------------------------------*/
- int reargv(char *cmd, char **av) /* turn command line into argc, argv[] */
- {
- int c;
- int inwhite = 1;
- int ac;
-
- /* This is a simple lexical scanner that looks for
- * white space separating command arguments. Each
- * argument found is terminated by a null byte. The
- * count and the array of arguments are returned.
- */
-
- for(ac = 0; ac < NARGS; ac++) /* zero all arg pointers */
- av[ac] = '\0';
- ac = 0; /* zero arg count */
-
- while(*cmd) /* scan the command line */
- {
- if(inwhite && *cmd != ' ') /* found the start of a word... */
- {
- inwhite = 0;
- av[ac++] = cmd; /* ...so set the next arg pointer */
- }
- else if(!inwhite && *cmd == ' ') /* found end of a word... */
- {
- inwhite = 1;
- *cmd = '\0'; /* ...so null-terminate it */
- }
- cmd++;
- }
- return(ac); /* return count of args found */
- }
-
- /*-------------------------------------------------------------------------*/
- int parse(char *cmd) /* tokenize the command word */
- {
- /* This tokenizer finds a command in the table matching the
- * given string, and returns its index in the table. It
- * returns 0 if no match is found. Abbreviated commands
- * are accepted, and -1 is returned if the string matches
- * more than one command.
- */
- static char *cmd_table[] =
- {
- "get", /* 1 */
- "put", /* 2 */
- "cd", /* 3 */
- "help", /* 4 */
- "kill", /* 5 */
- "dir", /* 6 */
- "del", /* 7 */
- "erase", /* 8 */
- "quit", /* 9 */
- 0
- };
-
- int i = 0;
- int match = -1;
- char **cp = cmd_table;
-
- while(*cp) /* loop through the cmd table */
- {
- i++;
- if(!strncmp(*cp, cmd, strlen(cmd)))
- {
- if(match != -1)
- return(-1); /* ambiguous command */
- else
- match = i; /* set match index */
- }
- cp++;
- }
-
- if(match == -1)
- return(0); /* no match */
- else
- return(match); /* successful match */
- }
-
- /*-------------------------------------------------------------------------*/
- cmd_get(int ac, char **av) /* get files from server */
- {
- ACTION ncmd, rcmd;
- NCB ncb;
- int len;
- int lsn = 0;
- FILE *fp;
- long size;
-
- if(ac < 2)
- {
- printf("error - no file name supplied\n");
- return;
- }
-
- ncmd.type = NET_GET;
- ncmd.code = 0;
- strcpy(ncmd.name, av[1]);
- clear_ncb(&ncb); /* post 1st receive */
- nw_recv_datagram(&rcmd, sizeof(ACTION), &ncb);
- send_datagram(remote, &ncmd, sizeof(ACTION)); /* send our request */
-
- while(1)
- {
- while(ncb.cmdcplt == 0xff)
- ;
- if(rcmd.code == NET_ERR) /* no more files */
- break; /* ..so get out */
-
- if(!lsn)
- lsn = listen(remote, local); /* establish session */
- /* (1st time only) */
- size = rcmd.size; /* save file size */
- printf("file %s", rcmd.name);
- fp = fopen(rcmd.name, "wb"); /* open it */
- while(size > 0) /* get the data */
- {
- printf(".");
- len = receive(lsn, buf, sizeof(buf));
- if(fp)
- fwrite(buf, 1, len, fp);
- size -= len;
- }
-
- size = rcmd.size; /* save size again */
- clear_ncb(&ncb); /* post next receive */
- nw_recv_datagram(&rcmd, sizeof(ACTION), &ncb);
- send(lsn, 0, 0); /* ACK this file */
- if(fp)
- {
- printf(" %ld bytes received.\n", size);
- fclose(fp);
- }
- else
- printf(" error opening file.\n");
- } /* loop for more */
- hangup(lsn);
- }
-
- /*-------------------------------------------------------------------------*/
- cmd_put(int ac, char **av) /* put files to remote server */
- {
- ACTION ncmd;
- NCB ncb;
- FILE *fp;
- int lsn = 0;
- int len;
- struct find_t info;
- int found;
- long size;
- char fname[80];
- char *dir_end;
-
- if(ac < 2)
- {
- printf("error - no file spec supplied\n");
- return;
- }
-
- strcpy(fname, av[1]); /* copy file specification */
- dir_end = strrchr(fname, '\\'); /* locate last '\' char */
- if(!dir_end) /* none there, so */
- dir_end = fname; /* no directory string */
- else /* found one, so */
- dir_end++; /* point one char past it */
-
- /* find matching file in current working directory */
-
- found = !_dos_findfirst(av[1], _A_NORMAL, &info);
- while(found) /* do for all matching files */
- {
- *dir_end = '\0'; /* prepare to concatenate */
- strcat(fname, info.name); /* file name onto dir string */
- if((fp = fopen(fname, "rb")) == NULL) /* open file */
- break;
- ncmd.size = size = info.size; /* extract file size */
- strcpy(ncmd.name, info.name); /* copy to cmd blk */
- ncmd.type = NET_PUT;
- ncmd.code = 0;
- clear_ncb(&ncb); /* issue a receive */
- nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb);
- send_datagram(remote, &ncmd, sizeof(ACTION)); /* req put */
- while(ncb.cmdcplt == 0xff) /* wait for receive */
- ;
- printf("file %s", fname);
- if(ncmd.code == NET_ERR) /* req rejected */
- {
- printf(" error sending file\n");
- continue; /* skip this one */
- }
- lsn = listen(remote, local); /* establish session */
-
- while(size > 0) /* send the data */
- {
- printf(".");
- len = fread(buf, 1, sizeof(buf), fp);
- send(lsn, buf, len);
- size -= len;
- }
- receive(lsn, 0, 0); /* wait for hangup */
- fclose(fp); /* close file */
- printf(" %ld bytes sent.\n", info.size);
- found = !_dos_findnext(&info); /* find next file */
- }
- }
-
- /*-------------------------------------------------------------------------*/
- cmd_chd(int ac, char **av) /* change remote directory */
- {
- ACTION ncmd;
- NCB ncb;
-
- ncmd.type = NET_CHD;
- ncmd.code = 0;
- strcpy(ncmd.name, av[1]);
- clear_ncb(&ncb);
- nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb); /* post receive */
- send_datagram(remote, &ncmd, sizeof(ACTION)); /* send chd req */
- while(ncb.cmdcplt == 0xff) /* wait for recv */
- ;
- if(ncmd.code != NET_ACK) /* check for error */
- printf("directory or drive not found\n");
- printf("current directory is %s\n", ncmd.name); /* print cwd */
- }
-
- /*-------------------------------------------------------------------------*/
- cmd_dir(int ac, char **av) /* remote directory listing */
- {
- ACTION ncmd;
- NCB ncb;
- int lsn;
- int len;
-
- ncmd.type = NET_DIR;
- ncmd.code = 0;
- strcpy(ncmd.name, av[1]);
-
- clear_ncb(&ncb);
- nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb); /* post receive */
- send_datagram(remote, &ncmd, sizeof(ACTION)); /* send dir request */
- while(ncb.cmdcplt == 0xff) /* wait for recv */
- ;
- if(ncmd.code != NET_ACK) /* check for error */
- {
- printf("error getting directory\n");
- return;
- }
-
- lsn = listen(remote, local); /* establish session */
-
- while(ncmd.size > 0) /* receive dir list */
- {
- len = receive(lsn, buf, sizeof(buf));
- fwrite(buf, 1, len, stdout); /* put to screen */
- ncmd.size -= len;
- }
- hangup(lsn); /* hang up session */
- }
-
- /*-------------------------------------------------------------------------*/
- cmd_del(int ac, char **av) /* delete remote files */
- {
- ACTION ncmd;
- NCB ncb;
-
- if(ac < 2)
- {
- printf("error - no file specified\n");
- return;
- }
-
- ncmd.type = NET_DEL;
- ncmd.code = 0;
- strcpy(ncmd.name, av[1]);
- clear_ncb(&ncb);
- nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb); /* post receive */
- send_datagram(remote, &ncmd, sizeof(ACTION)); /* send del request */
- while(ncb.cmdcplt == 0xff) /* wait for recv */
- ;
- printf("%d files deleted\n", ncmd.size); /* print information */
- }
-
- /*-------------------------------------------------------------------------*/
- cmd_remote(int ac, char **av) /* execute a remote command */
- {
- ACTION ncmd;
- NCB ncb;
- char *bp;
-
- ncmd.type = NET_REMOTE;
- ncmd.code = 0;
- ncmd.size = ac; /* number of args in cmd */
- for(bp = ncmd.name; ac; --ac, ++av) /* copy the rest of the args */
- {
- strcpy(bp, *av);
- bp += strlen(*av) + 1;
- }
-
- clear_ncb(&ncb);
- nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb); /* post receive */
- send_datagram(remote, &ncmd, sizeof(ACTION)); /* send cmd req */
- while(ncb.cmdcplt == 0xff) /* wait for recv */
- ;
- printf("command returned %d\n",ncmd.code);
- }
-
- /*-------------------------------------------------------------------------*/
- cmd_bye(void) /* shut down remote server */
- {
- ACTION ncmd;
- char buf[10];
-
- printf("Shut down remote server (y/n): ");
- gets(buf);
- if(toupper(*buf) == 'Y')
- {
- ncmd.type = NET_BYE;
- ncmd.code = 0;
- send_datagram(remote, &ncmd, sizeof(ACTION));
- exitflag = 1; /* force this program to exit too */
- }
- }
-
- /*-------------------------------------------------------------------------*/
- shell(int ac, char **av) /* shell out one command and return */
- {
- char *cmd;
- int i;
-
- cmd = getenv("COMSPEC");
-
- if(*av[0]) /* something appears after the !... */
- {
- ac += 2; /* so fill in command args */
- for(i = ac - 1; i >= 2; i--)
- av[i] = av[i - 2];
- av[0] = cmd; /* 1st arg is command.com pathname */
- av[1] = "/C"; /* 2nd arg is /C (transient command) */
- av[ac] = 0; /* terminate parameter list */
- }
- else /* otherwise shell out until exit */
- {
- av[0] = cmd;
- av[1] = 0;
- printf("EXIT to return to Tnet\n"); /* remind user */
- }
-
- spawnv(P_WAIT, cmd, av);
- }
-
- /*-------------------------------------------------------------------------*/
- cmd_help() /* help screen */
- {
- printf( "\n"
- " Commands to remote server:\n"
- " get <filename>\n"
- " put <filename>\n"
- " cd <dirname>\n"
- " dir <filename>\n"
- " del <filename>\n"
- " erase <filename>\n"
- " kill\n"
- "\n"
- " Local commands:\n"
- " !<command>\n"
- " help\n"
- " quit\n"
- "\n"
- " <filename> may contain wildcards\n"
- "\n");
- }
-