* added RCS Id keyword strings to sources
[citadel.git] / citadel / netpoll.c
1 /* $Id$ */
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <stdio.h>
5 #include <fcntl.h>
6 #include <string.h>
7 #include <errno.h>
8 #include "citadel.h"
9
10 /*
11  * This variable defines the amount of network spool data that may be carried
12  * in one server transfer command.  For some reason, some networks get hung
13  * up on larger packet sizes.  We don't know why.  In any case, never set the
14  * packet size higher than 4096 or your server sessions will crash.
15  */
16 #define IGNET_PACKET_SIZE 64
17
18 long atol(const char *);
19
20 void attach_to_server(int argc, char **argv);
21 void serv_read(char *buf, int bytes);
22 void serv_write(char *buf, int nbytes);
23 void get_config(void);
24 struct config config;
25
26
27 /*
28  * num_parms()  -  discover number of parameters...
29  */
30 int num_parms(char *source)
31 {
32         int a;
33         int count = 1;
34
35         for (a=0; a<strlen(source); ++a) 
36                 if (source[a]=='|') ++count;
37         return(count);
38         }
39
40
41 /*
42  * extract()  -  extract a parameter from a series of "|" separated...
43  */
44 void extract(char *dest, char *source, int parmnum)
45 {
46         char buf[256];
47         int count = 0;
48         int n;
49
50         n = num_parms(source);
51
52         if (parmnum >= n) {
53                 strcpy(dest,"");
54                 return;
55                 }
56         strcpy(buf,source);
57         if ( (parmnum == 0) && (n == 1) ) {
58                 strcpy(dest,buf);
59                 return;
60                 }
61
62         while (count++ < parmnum) do {
63                 strcpy(buf,&buf[1]);
64                 } while( (strlen(buf)>0) && (buf[0]!='|') );
65         if (buf[0]=='|') strcpy(buf,&buf[1]);
66         for (count = 0; count<strlen(buf); ++count)
67                 if (buf[count] == '|') buf[count] = 0;
68         strcpy(dest,buf);
69         }
70
71 /*
72  * extract_int()  -  extract an int parm w/o supplying a buffer
73  */
74 int extract_int(char *source, int parmnum)
75 {
76         char buf[256];
77         
78         extract(buf,source,parmnum);
79         return(atoi(buf));
80         }
81
82 /*
83  * extract_long()  -  extract a long parm w/o supplying a buffer
84  */
85 long extract_long(char *source, int parmnum)
86 {
87         char buf[256];
88         
89         extract(buf,source,parmnum);
90         return(atol(buf));
91         }
92
93
94 void logoff(int code)
95 {
96         exit(code);
97         }
98
99
100 /*
101  * receive network spool from the remote system
102  */
103 void receive_spool(void) {
104         long download_len;
105         long bytes_received;
106         char buf[256];
107         static char pbuf[IGNET_PACKET_SIZE];
108         char tempfilename[64];
109         long plen;
110         FILE *fp;
111
112         sprintf(tempfilename,"/tmp/netpoll.%d",getpid());
113         serv_puts("NDOP");
114         serv_gets(buf);
115         printf("%s\n",buf);
116         if (buf[0]!='2') return;
117         download_len = extract_long(&buf[4],0);
118
119         bytes_received = 0L;
120         fp = fopen(tempfilename,"w");
121         if (fp==NULL) {
122                 perror("cannot open download file locally");
123                 return;
124                 }
125
126         while (bytes_received < download_len) {
127                 sprintf(buf,"READ %ld|%ld",
128                         bytes_received,
129                         ( (download_len - bytes_received > IGNET_PACKET_SIZE)
130                           ? IGNET_PACKET_SIZE : (download_len - bytes_received) ) );
131                 serv_puts(buf);
132                 serv_gets(buf);
133                 if (buf[0]=='6') {
134                         plen = extract_long(&buf[4],0);
135                         serv_read(pbuf,plen);
136                         fwrite((char *)pbuf,plen,1,fp);
137                         bytes_received = bytes_received + plen;
138                         }
139                 }
140
141         fclose(fp);
142         serv_puts("CLOS");
143         serv_gets(buf);
144         printf("%s\n",buf);
145         sprintf(buf,"mv %s %s/network/spoolin/netpoll.%d",
146                 tempfilename,BBSDIR,getpid());
147         system(buf);
148         system("exec nohup ./netproc >/dev/null 2>&1 &");
149         }
150
151 /*
152  * transmit network spool to the remote system
153  */
154 void transmit_spool(char *remote_nodename)
155 {
156         char buf[256];
157         char pbuf[4096];
158         long plen;
159         long bytes_to_write, thisblock;
160         int fd;
161         char sfname[128];
162
163         serv_puts("NUOP");
164         serv_gets(buf);
165         printf("%s\n",buf);
166         if (buf[0]!='2') return;
167
168         sprintf(sfname,"%s/network/spoolout/%s",BBSDIR,remote_nodename);
169         fd = open(sfname,O_RDONLY);
170         if (fd<0) {
171                 if (errno == ENOENT) {
172                         printf("Nothing to send.\n");
173                         }
174                 else {
175                         perror("cannot open upload file locally");
176                         }
177                 return;
178                 }
179
180         while ( plen=(long)read(fd,pbuf,IGNET_PACKET_SIZE), plen>0L) {
181                 bytes_to_write = plen; 
182                 while (bytes_to_write > 0L) {
183                         sprintf(buf,"WRIT %ld", bytes_to_write);
184                         serv_puts(buf);
185                         serv_gets(buf);
186                         thisblock = atol(&buf[4]);
187                         if (buf[0]=='7') {
188                                 serv_write(pbuf, (int)thisblock);
189                                 bytes_to_write = bytes_to_write - thisblock;
190                                 }
191                         else {
192                                 goto ABORTUPL;
193                                 }
194                         }
195                 }
196
197 ABORTUPL:
198         close(fd);
199         serv_puts("UCLS 1");
200         serv_gets(buf);
201         printf("%s\n",buf);
202         if (buf[0]=='2') unlink(sfname);
203         }
204
205
206
207
208 int main(int argc, char **argv)
209 {
210         char buf[256];
211         char remote_nodename[32];
212         int a;
213
214         if (argc != 4) {
215                 fprintf(stderr,
216                 "%s: usage: %s <address> <port number> <remote netpassword>\n",
217                         argv[0],argv[0]);
218                 exit(1);
219                 }
220
221         get_config();
222
223         attach_to_server(argc,argv);
224         serv_gets(buf);
225         printf("%s\n",buf);
226         if ((buf[0]!='2')&&(strncmp(buf,"551",3))) {
227                 fprintf(stderr,"%s: %s\n",argv[0],&buf[4]);
228                 logoff(atoi(buf));
229                 }
230
231         serv_puts("INFO");
232         serv_gets(buf);
233         if (buf[0]=='1') {
234                 a = 0;
235                 while (serv_gets(buf), strcmp(buf,"000")) {
236                         if (a==1) strcpy(remote_nodename,buf);
237                         if (a==1) printf("Connected to: %s ",buf);
238                         if (a==2) printf("(%s) ",buf);
239                         if (a==6) printf("%s\n",buf);
240                         ++a;
241                         }
242                 }
243
244         if (!strcmp(remote_nodename,config.c_nodename)) {
245                 fprintf(stderr,"Connected to local system\n");
246                 }
247         else {
248                 sprintf(buf,"NETP %s|%s",config.c_nodename,argv[3]);
249                 serv_puts(buf);
250                 serv_gets(buf);
251                 printf("%s\n",buf);
252         
253                 /* only do the transfers if we authenticated correctly! */
254                 if (buf[0]=='2') {
255                         receive_spool();
256                         transmit_spool(remote_nodename);
257                         }
258                 }
259
260         serv_puts("QUIT");
261         serv_gets(buf);
262         exit(0);
263         }