|
|
1.1 root 1: #include <stdio.h>
2: #include <curses.h>
3: #include "contents.h"
4:
5:
6:
7: main(argc, argv)
8: int argc;
9: char *argv[];
10:
11: {
12:
13: WINDOW *win1, *win2;
14: int x;
15: char dummy[50];
16:
17: printflag = 0;
18: strcpy(recdir,RECEIVER);
19: if(argc > 3)
20: {
21: printf("Too many arguments!\n");
22: exit(1);
23: }
24:
25: /* parse the command line argument for a 'p' or a 'P' so
26: * that we know to PRINT a file. If we hit a '?', then
27: * print a usage: message.
28: */
29:
30: bbsdatafile(); /* read the .mwcbbs data file, if it exists */
31:
32: if((argc==2)||(argc==3))
33: {
34: for(x=0;x<strlen(argv[1]);x++)
35: {
36:
37: /* test for v */ if( argv[1][x] == 'v' ){
38: printf("mwcbbs interface version %s\n",
39: VERSION);
40: exit(0);
41: }
42: /* test for pP */ if((argv[1][x] == 112) || (argv[1][x] == 80))
43: break;
44:
45: /* test for dD */ if((argv[1][x] == 100) || (argv[1][x] == 68))
46: {
47: strcpy(dummy,argv[2]);
48: if(argc < 3)
49: {
50: printf("No directory specified!\n");
51: exit(1);
52: }
53: if (strlen(dummy) < 2)
54: {
55: printf("Invalid destination specified!\n");
56: exit(1);
57: }
58: strcpy(recdir," ");
59: strcat(recdir,dummy);
60: break;
61: }
62:
63: if(argv[1][x] == '?')
64: {
65: printf("Usage:\tmwcbbs [options] directory\n");
66: printf("\tOptions:\n");
67: printf("\t -[Pp] print Contents files\n");
68: printf("\t -[Dd] specify destination directory\n");
69: printf("\t -[v] specify interface version\n");
70: printf("\t -[?] usage message\n");
71: exit(1);
72: }
73: }
74: }
75:
76: /* the following should only be executed if the above
77: * loop went all the way thru the argument passed, which means
78: * that we did not find a [pP].
79: */
80:
81: if ((argc==2) && (x==strlen(argv[1])))
82: {
83: printf("Unknown option %s\n",argv[1]);
84: exit(1);
85: }
86: else
87:
88: /* we found that there is one argument and that it is [pP],
89: * so set a printflag. We should only set this flag if argc = 2.
90: * The if statement ensures that printflag will only be set
91: * if there was one argument passed.
92: */
93: {
94: if(argc==2)
95: printflag = 1;
96: }
97:
98: initscr();
99: raw();
100: noecho();
101:
102: /* allocate memory for windows. print message on failure. */
103:
104: if((win1=newwin(20, 79, 0,0)) == NULL)
105: {
106: printf("\007Window Memroy allocation for win1 failed!\n");
107: exit(1);
108: }
109:
110: if((win2=newwin(20, 79, 0,0)) == NULL)
111: {
112: printf("\007Window Memroy allocation for win2 failed!\n");
113: exit(1);
114: }
115:
116: screen_num = 0;
117:
118:
119: /* now we get the user's choice of file to process */
120:
121: do {
122: getfilename();
123:
124:
125: /* if we're printing, call the print function. After
126: * completion, exit the program. We want to exit the
127: * because we don't want the user to automatically
128: * run the print function again and overwrite the
129: * data file written by the previous run-through.
130: */
131:
132:
133: /* added 11/21/91: If 'quit' was selected from the
134: * menu, we don't want to run the print option. Beta
135: * version 3 would allow the print routine to be entered
136: * and would later exit with a 'cannot find QUIT' message.
137: */
138:
139: if((printflag == 1) && (strcmp(workfile,"QUIT") != 0))
140: {
141: print(win2);
142: strcpy(workfile,"QUIT");
143: }
144:
145: /* if we did NOT select the mail option, then read the indicated
146: * Content file.
147: */
148:
149: if (strcmp(workfile,"QUIT")==0)
150: break;
151:
152: if (strstr(workfile,MAILFILE) == NULL)
153: x = rfile();
154: show_files(win1, win2, x);
155:
156: }
157: while( strcmp(workfile,FILE6) != 0);
158:
159: noraw();
160: endwin();
161:
162: }
163:
164:
165:
166:
167: /* show_files()
168: * This function will display the filenames read to a curses
169: * screen.
170: */
171:
172:
173: void show_files(win1, win2, EOF_FLAG)
174: WINDOW *win1, *win2;
175: int EOF_FLAG;
176:
177: {
178: char arrow;
179: int prevcol =1;
180: int prevrow =0; /* prevcol = column before arrow */
181: int newrow =0; /* prevrow = row before arrow */
182: int newcol =1; /* newrow = row after arrow */
183: int counter = 0; /* newcol = column after arrow */
184:
185:
186:
187:
188: /* if the mail option was selected, print the states to the window,
189: * else print the filenames from the read Contents file to the window.
190: */
191:
192: /* if we are in add/remove mode, then we want to print mail accounts
193: * by SITE to the workscreen, NOT the list of states.
194: */
195:
196: if ( (strstr(workfile,FILE4) != NULL) )
197: {
198: print_states(win1);
199: EOF_FLAG = -1;
200: }
201:
202: else
203: write_win(win1);
204:
205: menu();
206:
207:
208: /* highlite a filename. This is accomplished by going to a designated
209: * row and column, as determined by the row and counter nested loops.
210: * The innermost loop gets the character found, copies the retrieved
211: * character into a string and deletes the character from the screen.
212: * When the filename has been deleted from the screen, it is reprinted
213: * to the screen with highliting turned on. Padding for spaces must be
214: * accounted for since deleting chars shifts everything on the line one
215: * space to the left.
216: */
217:
218: /* print the first file in inverse video */
219:
220: lite (win1, prevrow, prevcol, 1,0);
221:
222: do
223: {
224: noecho();
225:
226: /* now we need to get a key (preferably an arrow) */
227:
228:
229:
230: arrow = getch(); /* This stupid code should allow to use arrows keys */
231: if (arrow == 27) /* that looks more frendly than hjkl. Vlad 8/15/91 */
232: {
233: getch();
234: arrow = getch(); /* When an arrow key is pressed, an escape */
235: if (arrow == 68) /* sequence is returned. The value '27' */
236: arrow = 'h'; /* begins the sequence and the relevant */
237: if (arrow == 67) /* values needed end the sequence. The */
238: arrow = 'l'; /* middle value is not needed, so it is */
239: if (arrow == 66) /* skipped over with a getch() statement */
240: arrow = 'j';
241: if (arrow == 65)
242: arrow = 'k';
243: }
244:
245:
246: /* each movement case in the following switch...case will test to see if the
247: * new position returns a space. If a space is returned, then we will hit
248: * an empty field, which we don't want to do. If we hit an empty space,
249: * then don't move the cursor.
250: */
251:
252: switch(arrow)
253: {
254: case 'h': /* move left */
255: newcol = prevcol - 15;
256: if (newcol < 1)
257: newcol = 61;
258: if (' ' == mvwinch(win1,newrow,newcol))
259: newcol = 1;
260: break;
261:
262:
263: case 'l': /* move right */
264: newcol = prevcol + 15;
265: if (newcol > 61)
266: newcol = 1;
267: if (' ' == mvwinch(win1,newrow,newcol))
268: newcol = 1;
269: break;
270:
271:
272: case 'j': /* move down */
273: newrow = prevrow + 1;
274: if (newrow == 20)
275: newrow = 0;
276: if (' ' == mvwinch(win1,newrow,newcol))
277: newrow = 0;
278: break;
279:
280:
281: case 'k': /* move up */
282: newrow = prevrow -1;
283: if (newrow == -1)
284: newrow = 19;
285: if (' ' == mvwinch(win1,newrow,newcol))
286: newrow = 0;
287: break;
288:
289:
290: case 'p':
291: screen_num --;
292: newrow = 0;
293: newcol = 1;
294: if (screen_num < 0)
295: screen_num = 0;
296: else
297: {
298: EOF_FLAG = rfile();
299: write_win(win1);
300: }
301: break;
302:
303:
304: case 'n':
305: newrow = 0;
306: newcol = 1;
307: if (EOF_FLAG == -1)
308: break;
309: else
310: {
311: screen_num ++;
312: EOF_FLAG = rfile();
313: write_win(win1);
314: }
315: break;
316:
317: /* when we 'quit', we need to make sure that the screen number
318: * is set to 0 so that when the next file is selected, we begin
319: * at the start of the file. If not, we run the risk of reading
320: * something and causing a dump, or worse, system corruption.
321: */
322:
323: case 'Q':
324: case 'q':
325: screen_num = 0;
326: break;
327:
328: case 13:
329: case 'S':
330: case 's':
331: wclear(win1);
332: wrefresh(win1);
333: wclear(win2);
334:
335: if((strstr(workfile,mapfile[0]) != NULL) || (strstr(workfile,mapfile[1])!= NULL) || (strstr(workfile,mapfile[2])!= NULL))
336: {
337: map_command(win2,prevrow,prevcol,screen_num);
338: wclear(win1);
339: rfile();
340: write_win(win1);
341: wrefresh(win1);
342: break;
343: }
344:
345: if( strstr(workfile,MAILFILE) != NULL)
346: {
347: print_mail_states(win2);
348: wclear(win2);
349: wrefresh(win2);
350: refresh();
351: wrefresh(win1);
352: wclear(win1);
353: print_states(win1);
354: wrefresh(win1);
355: break;
356: }
357:
358: /* if we're not working on a mailfile record, display the Contents
359: * form.
360: */
361: if(strstr(workfile,MAILFILE) == NULL)
362: {
363: display_form(win2);
364: display_record(win2,prevrow,prevcol,screen_num);
365:
366: write_win(win1);
367: wclear(win2);
368: wrefresh(win2);
369: menu();
370: refresh();
371: wrefresh(win1);
372: break;
373: }
374:
375: default:
376: newcol = prevcol;
377: newrow = prevrow;
378: break;
379:
380: }
381:
382: /* print previous file highlited in normal video */
383: lite (win1, prevrow, prevcol, 0,0);
384:
385: /* print new filename selection in inverse video */
386:
387: lite (win1, newrow, newcol, 1,0);
388:
389: /* set our previous coordinates so that we can go back
390: * and unlite a field when the next directin is given.
391: */
392:
393: prevrow = newrow;
394: prevcol = newcol;
395:
396:
397: }
398: while (arrow != 'q');
399:
400: }
401:
402:
403:
404:
405: int rfile()
406:
407: {
408:
409: FILE *infp;
410: int EOF_FLAG;
411:
412:
413: /* open file, abort on error */
414:
415: if ((infp = fopen(workfile,"r")) == NULL)
416: {
417: printf("\007ERROR opening file %s for input!\n", workfile);
418: exit(1);
419: }
420:
421: /* open a file then go to a an offset calculated by a
422: * value passed from the calling program. Once we hit
423: * the max number of records that can be held by a screen,
424: * terminate the read and set a flag to show that we did
425: * not hit EOF. If we did hit EOF, terminate the loop
426: * and set a flag to show that we did hit EOF.
427: */
428:
429: /* start reading from a specified point in the file */
430:
431: if((strstr(workfile,mapfile[0])!= NULL) || (strstr(workfile,mapfile[1])!= NULL) || (strstr(workfile,mapfile[2])!= NULL))
432: fseek(infp,(sizeof (struct map) * (screen_num * 100)),0l);
433: else
434: fseek(infp, (sizeof (struct entry) * (screen_num * 100)), 0l);
435:
436: limit = 0;
437:
438:
439: if((strstr(workfile,mapfile[0])!= NULL) || (strstr(workfile,mapfile[1])!= NULL) || (strstr(workfile,mapfile[2])!= NULL))
440: {
441: while((fread(&map_rec,sizeof(struct map),1,infp)) != 0)
442: {
443: strcpy(filenames[limit], map_rec.name);
444: place[limit] = limit;
445: limit ++;
446: if (limit == 100)
447: break;
448: }
449: }
450: else
451: {
452: while((fread(&record, sizeof(struct entry),1, infp)) != 0)
453: {
454: strcpy(filenames[limit], record.filename);
455: place[limit] = limit;
456: limit++;
457: if (limit == 100)
458: break;
459: }
460: }
461:
462:
463:
464: /* if x made it to 100, then we did NOT hit EOF */
465:
466: if((strstr(workfile,mapfile[0])!= NULL) || (strstr(workfile,mapfile[1])!= NULL) || (strstr(workfile,mapfile[2])!= NULL))
467: {
468: if ( (limit == 100) && (fread (&map_rec,sizeof(struct map),1,infp)) != 0)
469: EOF_FLAG = 0;
470: else
471: EOF_FLAG = -1;
472: }
473: else
474: {
475: if ( (limit == 100) && (fread (&record,sizeof(struct entry),1,infp)) != 0)
476: EOF_FLAG = 0;
477: else
478: EOF_FLAG = -1;
479: }
480: fclose(infp);
481: return (EOF_FLAG);
482:
483: }
484:
485:
486:
487: /*
488: * writewin();
489: * this routine does the actual work of writing filenames to a window
490: */
491:
492: void write_win(win1)
493:
494: WINDOW *win1;
495:
496: {
497:
498: int r,c; /* these are our rows and columns */
499: int counter = 0; /* this counts the number of files written */
500:
501:
502:
503: /* clear the window */
504: wclear(win1);
505:
506: /* the following loop will write the filenames to the window.
507: * 15 characters per screen field are allowed, since a filename
508: * can only be 14 chars in length. This will leave at least one
509: * space between filenames.
510: */
511:
512: for (r = 0; r < 20; r++)
513: {
514:
515: /* if we've run out of files, terminate loop */
516:
517: if (counter == limit)
518: break;
519:
520: /* increment column by 15 positions. This
521: * will cause the filenames to line up
522: * on the window.
523: */
524:
525: for (c = 1; c < 75; c+= 15)
526: {
527: wmove(win1, r, c);
528: waddstr(win1, filenames[counter]);
529:
530: /* increment counter. When it equals the number of
531: * records, passed as 'limit', the loop should
532: * terminate.
533: */
534:
535: counter ++;
536: if (counter == limit)
537: break;
538: }
539: }
540:
541:
542: }
543:
544: /* this function will draw a template for the selected record */
545:
546: void display_form(win2)
547: WINDOW *win2;
548:
549:
550: {
551: int x;
552:
553: clear();
554: wclear(win2);
555:
556: /* print field labels */
557:
558: wmove (win2, NAMELOCATE );
559: waddstr (win2,"Filename:");
560:
561: wmove (win2, DESCLOCATE);
562: waddstr(win2,"Description:");
563:
564: wmove(win2, DATELOCATE );
565: waddstr(win2,"Date added/modified:");
566:
567: wmove(win2, SIZELOCATE);
568: waddstr(win2,"File size:");
569:
570: wmove(win2, REQLOCATE );
571: waddstr(win2,"Requires these other files:");
572:
573: wmove(win2, NOTELOCATE);
574: waddstr(win2,"Other notes:");
575:
576:
577: /* highlite available fields */
578:
579: wstandout(win2);
580:
581: wmove (win2, NAMEHI);
582: waddstr(win2," ");
583:
584: wmove (win2,DESCHI);
585: for (x=1;x<79;x++)
586: waddstr(win2," ");
587:
588: wmove(win2, DATEHI);
589: waddstr(win2," ");
590:
591: wmove(win2, SIZEHI);
592: waddstr(win2," ");
593:
594: wmove (win2,REQHI);
595: for (x=1;x<61;x++)
596: waddstr(win2," ");
597:
598: wmove (win2,NOTEHI);
599: for (x=1;x<69;x++)
600: waddstr(win2," ");
601:
602: wstandend(win2);
603: refresh();
604: wrefresh(win2);
605:
606:
607:
608: }
609:
610: /* following function prints the menu at the bottom of stdscr */
611:
612: void menu()
613:
614: {
615: /* print a menu of options to stdscr. They will appear at the bottom of
616: * the screen with the first letter highlited as an indication to
617: * the user that pressing the highlited key will result in the indicated
618: * action.
619: */
620:
621: move (21,0);
622: if(strstr(workfile,MAILFILE) != NULL)
623: printw("Select state/other to view.");
624: else
625: printw("Select file to download. ");
626: refresh();
627:
628:
629: move(21, 50);
630: standout();
631: printw("Options:");
632: move(22,46);
633: printw("n");
634: move(23,46);
635: printw("p");
636: move(22,60);
637: printw("q");
638: move(23,60);
639: printw("s");
640: standend();
641: move(22,47);
642: addstr("ext page");
643: move(23,47);
644: addstr("rev. page");
645: move(22,61);
646: addstr("uit");
647: move(23,61);
648: addstr("elect file");
649:
650:
651: }
652:
653:
654:
655: /* this function will take the pathname and append the necessary
656: * character(s) to generate the multiple requests necessary to
657: * download multipart files.
658: */
659:
660: void build_uucp(record)
661:
662:
663: {
664: int x,y,z;
665:
666: y = strlen(record.pathname);
667:
668: for(x=0;x< record.noparts;x++){
669: strcpy(getfiles[x],HOST);
670: record.pathname[y] = 97 + x;
671: record.pathname[y+1] = '\0';
672: strcat(getfiles[x],record.pathname);
673: strcat(getfiles[x],recdir);
674:
675: for(z=strlen(getfiles[x]) ; z < sizeof(getfiles[x]) ; z++){
676: getfiles[x][z] = '\0';
677: }
678:
679: }
680:
681:
682: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.