4 * Server functions which handle file transfers and room directories.
22 #if TIME_WITH_SYS_TIME
23 # include <sys/time.h>
27 # include <sys/time.h>
36 #include "dynloader.h"
39 #include "sysdep_decls.h"
45 #include "citserver.h"
47 void cmd_delf(char *filename)
52 if (CtdlAccessCheck(ac_room_aide)) return;
54 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
55 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
59 if (strlen(filename)==0) {
60 cprintf("%d You must specify a file name.\n",
61 ERROR+FILE_NOT_FOUND);
64 for (a=0; a<strlen(filename); ++a)
65 if (filename[a]=='/') filename[a] = '_';
66 snprintf(pathname,sizeof pathname,"./files/%s/%s",
67 CC->quickroom.QRdirname,filename);
69 if (a==0) cprintf("%d File '%s' deleted.\n",OK,pathname);
70 else cprintf("%d File '%s' not found.\n",ERROR+FILE_NOT_FOUND,pathname);
77 * move a file from one room directory to another
79 void cmd_movf(char *cmdbuf)
87 struct quickroom qrbuf;
89 extract(filename,cmdbuf,0);
90 extract(newroom,cmdbuf,1);
92 if (CtdlAccessCheck(ac_room_aide)) return;
94 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
95 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
99 if (strlen(filename)==0) {
100 cprintf("%d You must specify a file name.\n",
101 ERROR+FILE_NOT_FOUND);
105 for (a=0; a<strlen(filename); ++a)
106 if (filename[a]=='/') filename[a] = '_';
107 snprintf(pathname,sizeof pathname,"./files/%s/%s",
108 CC->quickroom.QRdirname,filename);
109 if (access(pathname,0)!=0) {
110 cprintf("%d File '%s' not found.\n",
111 ERROR+FILE_NOT_FOUND,pathname);
115 if (getroom(&qrbuf, newroom)!=0) {
116 cprintf("%d '%s' does not exist.\n",
120 if ((qrbuf.QRflags & QR_DIRECTORY) == 0) {
121 cprintf("%d '%s' is not a directory room.\n",
122 ERROR+NOT_HERE,qrbuf.QRname);
125 snprintf(newpath,sizeof newpath,"./files/%s/%s",qrbuf.QRdirname,
127 if (link(pathname,newpath)!=0) {
128 cprintf("%d Couldn't move file: %s\n",ERROR,strerror(errno));
133 /* this is a crude method of copying the file description */
134 snprintf(buf, sizeof buf,
135 "cat ./files/%s/filedir |grep %s >>./files/%s/filedir",
136 CC->quickroom.QRdirname,
140 cprintf("%d File '%s' has been moved.\n",OK,filename);
145 * send a file over the net
147 void cmd_netf(char *cmdbuf)
149 char pathname[SIZ],filename[SIZ],destsys[SIZ],buf[SIZ],outfile[SIZ];
155 extract(filename,cmdbuf,0);
156 extract(destsys,cmdbuf,1);
158 if (CtdlAccessCheck(ac_room_aide)) return;
160 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
161 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
165 if (strlen(filename)==0) {
166 cprintf("%d You must specify a file name.\n",
167 ERROR+FILE_NOT_FOUND);
171 for (a=0; a<strlen(filename); ++a)
172 if (filename[a]=='/') filename[a] = '_';
173 snprintf(pathname,sizeof pathname,"./files/%s/%s",
174 CC->quickroom.QRdirname,filename);
175 if (access(pathname,0)!=0) {
176 cprintf("%d File '%s' not found.\n",
177 ERROR+FILE_NOT_FOUND,pathname);
180 snprintf(buf,sizeof buf,"sysop@%s",destsys);
183 cprintf("%d No such system: '%s'\n",
184 ERROR+NO_SUCH_SYSTEM,destsys);
187 snprintf(outfile, sizeof outfile,
188 "%s/network/spoolin/nsf.%04x.%04x",
189 BBSDIR, getpid(), ++seq);
190 ofp=fopen(outfile,"a");
192 cprintf("%d internal error\n",ERROR);
197 putc(MES_NORMAL,ofp);
199 fprintf(ofp,"Pcit%ld",CC->usersupp.usernum); putc(0,ofp);
201 fprintf(ofp,"T%ld",(long)now); putc(0,ofp);
202 fprintf(ofp,"A%s",CC->usersupp.fullname); putc(0,ofp);
203 fprintf(ofp,"O%s",CC->quickroom.QRname); putc(0,ofp);
204 fprintf(ofp,"N%s",NODENAME); putc(0,ofp);
205 fprintf(ofp,"D%s",destsys); putc(0,ofp);
206 fprintf(ofp,"SFILE"); putc(0,ofp);
210 snprintf(buf,sizeof buf,
211 "cd ./files/%s; uuencode %s <%s 2>/dev/null >>%s",
212 CC->quickroom.QRdirname,filename,filename,outfile);
215 ofp = fopen(outfile,"a");
219 cprintf("%d File '%s' has been sent to %s.\n",OK,filename,destsys);
220 system("nohup ./netproc -i >/dev/null 2>&1 &");
225 * This code is common to all commands which open a file for downloading.
226 * It examines the file and displays the OK result code and some information
227 * about the file. NOTE: this stuff is Unix dependent.
229 void OpenCmdResult(char *filename, char *mime_type) {
234 fstat(fileno(CC->download_fp), &statbuf);
235 filesize = (long) statbuf.st_size;
236 modtime = (time_t) statbuf.st_mtime;
238 cprintf("%d %ld|%ld|%s|%s\n",
239 OK, filesize, modtime, filename, mime_type);
244 * open a file for downloading
246 void cmd_open(char *cmdbuf)
252 extract(filename,cmdbuf,0);
254 if (CtdlAccessCheck(ac_logged_in)) return;
256 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
257 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
261 if (strlen(filename)==0) {
262 cprintf("%d You must specify a file name.\n",
263 ERROR+FILE_NOT_FOUND);
267 if (CC->download_fp != NULL) {
268 cprintf("%d You already have a download file open.\n",ERROR);
272 for (a=0; a<strlen(filename); ++a)
273 if (filename[a]=='/') filename[a] = '_';
275 snprintf(pathname,sizeof pathname,
276 "./files/%s/%s",CC->quickroom.QRdirname,filename);
277 CC->download_fp = fopen(pathname,"r");
279 if (CC->download_fp==NULL) {
280 cprintf("%d cannot open %s: %s\n",
281 ERROR,pathname,strerror(errno));
285 OpenCmdResult(filename, "application/octet-stream");
291 void cmd_oimg(char *cmdbuf)
295 struct usersupp usbuf;
300 extract(filename,cmdbuf,0);
302 if (strlen(filename)==0) {
303 cprintf("%d You must specify a file name.\n",
304 ERROR+FILE_NOT_FOUND);
308 if (CC->download_fp != NULL) {
309 cprintf("%d You already have a download file open.\n",ERROR);
313 if (!strcasecmp(filename, "_userpic_")) {
314 extract(which_user, cmdbuf, 1);
315 if (getuser(&usbuf, which_user) != 0) {
316 cprintf("%d No such user.\n", ERROR+NO_SUCH_USER);
319 snprintf(pathname, sizeof pathname, "./userpics/%ld.gif",
322 else if (!strcasecmp(filename, "_floorpic_")) {
323 which_floor = extract_int(cmdbuf, 1);
324 snprintf(pathname, sizeof pathname, "./images/floor.%d.gif",
327 else if (!strcasecmp(filename, "_roompic_")) {
328 assoc_file_name(pathname, &CC->quickroom, "images");
331 for (a=0; a<strlen(filename); ++a) {
332 filename[a] = tolower(filename[a]);
333 if (filename[a]=='/') filename[a] = '_';
335 snprintf(pathname,sizeof pathname,"./images/%s.gif",filename);
338 CC->download_fp = fopen(pathname,"r");
339 if (CC->download_fp == NULL) {
340 cprintf("%d Cannot open %s: %s\n",
341 ERROR+FILE_NOT_FOUND,pathname,strerror(errno));
345 OpenCmdResult(pathname, "image/gif");
349 * open a file for uploading
351 void cmd_uopn(char *cmdbuf)
355 extract(CC->upl_file,cmdbuf,0);
356 extract(CC->upl_comment,cmdbuf,1);
358 if (CtdlAccessCheck(ac_logged_in)) return;
360 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
361 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
365 if (strlen(CC->upl_file)==0) {
366 cprintf("%d You must specify a file name.\n",
367 ERROR+FILE_NOT_FOUND);
371 if (CC->upload_fp != NULL) {
372 cprintf("%d You already have a upload file open.\n",ERROR);
376 for (a=0; a<strlen(CC->upl_file); ++a)
377 if (CC->upl_file[a]=='/') CC->upl_file[a] = '_';
378 snprintf(CC->upl_path,sizeof CC->upl_path,"./files/%s/%s",
379 CC->quickroom.QRdirname,CC->upl_file);
380 snprintf(CC->upl_filedir,sizeof CC->upl_filedir,"./files/%s/filedir",
381 CC->quickroom.QRdirname);
383 CC->upload_fp = fopen(CC->upl_path,"r");
384 if (CC->upload_fp != NULL) {
385 fclose(CC->upload_fp);
386 CC->upload_fp = NULL;
387 cprintf("%d '%s' already exists\n",
388 ERROR+ALREADY_EXISTS,CC->upl_path);
392 CC->upload_fp = fopen(CC->upl_path,"wb");
393 if (CC->upload_fp == NULL) {
394 cprintf("%d Cannot open %s: %s\n",
395 ERROR,CC->upl_path,strerror(errno));
398 cprintf("%d Ok\n",OK);
404 * open an image file for uploading
406 void cmd_uimg(char *cmdbuf)
408 int is_this_for_real;
413 if (num_parms(cmdbuf) < 2) {
414 cprintf("%d Usage error.\n", ERROR);
418 is_this_for_real = extract_int(cmdbuf,0);
419 extract(basenm, cmdbuf, 1);
420 if (CC->upload_fp != NULL) {
421 cprintf("%d You already have an upload file open.\n", ERROR);
425 strcpy(CC->upl_path, "");
427 for (a=0; a<strlen(basenm); ++a) {
428 basenm[a] = tolower(basenm[a]);
429 if (basenm[a]=='/') basenm[a] = '_';
432 if (CC->usersupp.axlevel >= 6) {
433 snprintf(CC->upl_path, sizeof CC->upl_path, "./images/%s",
437 if (!strcasecmp(basenm, "_userpic_")) {
438 snprintf(CC->upl_path, sizeof CC->upl_path,
439 "./userpics/%ld.gif", CC->usersupp.usernum);
442 if ( (!strcasecmp(basenm, "_floorpic_")) && (CC->usersupp.axlevel >= 6) ) {
443 which_floor = extract_int(cmdbuf, 2);
444 snprintf(CC->upl_path, sizeof CC->upl_path,
445 "./images/floor.%d.gif", which_floor);
448 if ( (!strcasecmp(basenm, "_roompic_")) && (is_room_aide()) ) {
449 assoc_file_name(CC->upl_path, &CC->quickroom, "images");
452 if (strlen(CC->upl_path) == 0) {
453 cprintf("%d Higher access required.\n",
454 ERROR+HIGHER_ACCESS_REQUIRED);
458 if (is_this_for_real == 0) {
459 cprintf("%d Ok to send image\n", OK);
463 CC->upload_fp = fopen(CC->upl_path,"wb");
464 if (CC->upload_fp == NULL) {
465 cprintf("%d Cannot open %s: %s\n",
466 ERROR,CC->upl_path,strerror(errno));
469 cprintf("%d Ok\n",OK);
470 CC->upload_type = UPL_IMAGE;
475 * close the download file
477 void cmd_clos(void) {
480 if (CC->download_fp == NULL) {
481 cprintf("%d You don't have a download file open.\n",ERROR);
485 fclose(CC->download_fp);
486 CC->download_fp = NULL;
488 if (CC->dl_is_net == 1) {
490 snprintf(buf,sizeof buf,"%s/network/spoolout/%s",BBSDIR,
495 cprintf("%d Ok\n",OK);
502 void abort_upl(struct CitContext *who)
504 if (who->upload_fp != NULL) {
505 fclose(who->upload_fp);
506 who->upload_fp = NULL;
507 unlink(CC->upl_path);
514 * close the upload file
516 void cmd_ucls(char *cmd)
519 char upload_notice[512];
521 if (CC->upload_fp == NULL) {
522 cprintf("%d You don't have an upload file open.\n",ERROR);
526 fclose(CC->upload_fp);
527 CC->upload_fp = NULL;
529 if ((!strcasecmp(cmd,"1")) && (CC->upload_type != UPL_FILE)) {
530 CC->upload_type = UPL_FILE;
531 cprintf("%d Upload completed.\n", OK);
533 if (CC->upload_type == UPL_NET) {
535 execlp("./netproc", "netproc", "-i", NULL);
543 if (!strcasecmp(cmd,"1")) {
544 cprintf("%d File '%s' saved.\n",OK,CC->upl_path);
545 fp = fopen(CC->upl_filedir,"a");
546 if (fp==NULL) fp=fopen(CC->upl_filedir,"w");
548 fprintf(fp,"%s %s\n",CC->upl_file,CC->upl_comment);
552 /* put together an upload notice */
553 sprintf(upload_notice,
554 "NEW UPLOAD: '%s'\n %s\n",
555 CC->upl_file,CC->upl_comment);
556 quickie_message(CC->curr_user, NULL, CC->quickroom.QRname,
561 cprintf("%d File '%s' aborted.\n",OK,CC->upl_path);
568 * read from the download file
570 void cmd_read(char *cmdbuf)
576 start_pos = extract_long(cmdbuf,0);
577 bytes = extract_int(cmdbuf,1);
579 if (CC->download_fp == NULL) {
580 cprintf("%d You don't have a download file open.\n",ERROR);
585 cprintf("%d You may not read more than 4096 bytes.\n",ERROR);
589 fseek(CC->download_fp,start_pos,0);
590 fread(buf,bytes,1,CC->download_fp);
591 cprintf("%d %d\n",BINARY_FOLLOWS,bytes);
592 client_write(buf, bytes);
598 * write to the upload file
600 void cmd_writ(char *cmdbuf)
605 bytes = extract_int(cmdbuf,0);
607 if (CC->upload_fp == NULL) {
608 cprintf("%d You don't have an upload file open.\n",ERROR);
613 cprintf("%d You may not write more than 4096 bytes.\n",ERROR);
617 cprintf("%d %d\n",SEND_BINARY,bytes);
618 client_read(buf, bytes);
619 fwrite(buf,bytes,1,CC->upload_fp);
625 * cmd_netp() - identify as network poll session
627 void cmd_netp(char *cmdbuf)
631 extract(buf,cmdbuf,1);
632 if (strcasecmp(buf,config.c_net_password)) {
633 cprintf("%d authentication failed\n",ERROR);
636 extract(CC->net_node,cmdbuf,0);
637 cprintf("%d authenticated as network node '%s'\n",OK,CC->net_node);
641 * cmd_ndop() - open a network spool file for downloading
643 void cmd_ndop(char *cmdbuf)
648 if (strlen(CC->net_node)==0) {
649 cprintf("%d Not authenticated as a network node.\n",
650 ERROR+NOT_LOGGED_IN);
654 if (CC->download_fp != NULL) {
655 cprintf("%d You already have a download file open.\n",ERROR);
659 snprintf(pathname,sizeof pathname,"%s/network/spoolout/%s",BBSDIR,
662 /* first open the file in append mode in order to create a
663 * zero-length file if it doesn't already exist
665 CC->download_fp = fopen(pathname,"a");
666 if (CC->download_fp != NULL) fclose(CC->download_fp);
669 CC->download_fp = fopen(pathname,"r");
670 if (CC->download_fp==NULL) {
671 cprintf("%d cannot open %s: %s\n",
672 ERROR,pathname,strerror(errno));
677 /* set this flag so other routines know that the download file
678 * currently open is a network spool file
682 stat(pathname,&statbuf);
683 cprintf("%d %ld\n",OK,statbuf.st_size);
687 * cmd_nuop() - open a network spool file for uploading
689 void cmd_nuop(char *cmdbuf)
693 if (strlen(CC->net_node)==0) {
694 cprintf("%d Not authenticated as a network node.\n",
695 ERROR+NOT_LOGGED_IN);
699 if (CC->upload_fp != NULL) {
700 cprintf("%d You already have an upload file open.\n",ERROR);
704 snprintf(CC->upl_path, sizeof CC->upl_path,
705 "%s/network/spoolin/%s.%04x.%04x",
706 BBSDIR, CC->net_node, getpid(), ++seq);
708 CC->upload_fp = fopen(CC->upl_path,"r");
709 if (CC->upload_fp != NULL) {
710 fclose(CC->upload_fp);
711 CC->upload_fp = NULL;
712 cprintf("%d '%s' already exists\n",
713 ERROR+ALREADY_EXISTS,CC->upl_path);
717 CC->upload_fp = fopen(CC->upl_path,"w");
718 if (CC->upload_fp == NULL) {
719 cprintf("%d Cannot open %s: %s\n",
720 ERROR,CC->upl_path,strerror(errno));
724 CC->upload_type = UPL_NET;
725 cprintf("%d Ok\n",OK);