home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / fido / pup_v2b.zip / PUP.C < prev    next >
C/C++ Source or Header  |  1988-01-28  |  12KB  |  438 lines

  1. #include <puppy.h>
  2. #include <pupmem.h>
  3. #include <ascii.h>
  4.  
  5. /*
  6.     Puppy's Main Section. 
  7.  
  8. This handles one caller then returns. This source contains the
  9. command prompt and the message base commands below it.
  10.  
  11. */
  12.  
  13. static int msgnbr;        /* current message number */
  14. static WORD last_topic;        /* topic from last msg read */
  15. static int topic;        /* currently selected topic(s) */
  16.  
  17. puppy() {
  18. char *cp;
  19.  
  20.     clr_clk();                /* start counting */
  21.     lmtstate= 0;                /* initialize the warning msg */
  22.  
  23. /* The set_abort(), was_abort() frc_abort() trio are the mechanism that
  24. takes care of the problem of inline carrier checks sprinkled throughout 
  25. the code. They are all contained in ABORT.ASM. It's really quite simple; it
  26. relies on the fact that as you call functions deeper and deeper, the "top
  27. level" (here) is safely stored on the stack somewhere. 
  28.  
  29. What set_abort does is just remember the stack pointer at this point, and
  30. clears a flag private to the ???_abort() functions. If the flag is clear
  31. (it is, set_abort cleared it) then was_abort() returns FALSE. So the first
  32. time through, the code sequence here is set_abort(), was_abort(), openmsg(),
  33. etc. 
  34.  
  35. The I/O drivers call frc_abort() if carrier is lost or a time limit expires.
  36. (Well, it calls logoff() which does) What frc_abort() does is restore the
  37. saved stack pointer (losing the one called from) and set the flag, and 
  38. just "returns". Where it goes to though is where the first set_abort() 
  39. call returned from!
  40.  
  41. This time though the flag is SET (remember that?) so was_abort() takes
  42. its TRUE branch, and Pup cleans up. */
  43.  
  44.     set_abort(0);                /* set carrier loss trap */
  45.     if (was_abort()) {            /* if we get a frc_abort() */
  46.         printf("\r\n\r\n");        /* close up */
  47.         closemsg();            /* close the message base, */
  48.         closeclr();            /* close the caller file */
  49.         putsys();            /* write system file */
  50.         close_up();            /* close aborted files */
  51.         return(0);            /* not TSYNC */
  52.     }
  53.     openmsg();                /* open message base, */
  54.     openclr();                /* open the caller file */
  55.     mconflush();                /* flush interrupt buffers */
  56.     cmdflush();                /* flush command buffers */
  57.  
  58.     login();                /* login some user */
  59.  
  60. /* Now execute commands forever. */
  61.  
  62.     msgnbr= oldest_msg();            /* first time through */
  63.     topic= 0;
  64.  
  65.     while (1) {
  66.         cp= getarg("Command: M)essages H)ello! G)oodbye! D)ownload U)pload (?=help): ");
  67.         switch (tolower(*cp)) {
  68.             case 'm': msg_base(); break;
  69.             case 'h': setscreen();        /* LOGIN.C */
  70.                 if (ask("Want to see the \"Hello\" display again")) dspfile("welcome.pup");
  71.                 stuff(); break;        /* LOGIN.C */
  72.             case 'd': download(); break;    /* FILES.C */
  73.             case 'u': upload(); break;    /* FILES.C */
  74.             case 'g': goodbye(); break;
  75.             case '?': dspfile("main.hlp"); break;
  76.             case NUL: break;
  77.             default:
  78.                 mprintf("eh?\r\n");
  79.                 cmdflush();
  80.                 break;
  81.         }
  82.     }
  83. }
  84.  
  85. /* Me, I disconnect from you. */
  86.  
  87. goodbye() {
  88.  
  89.     if (ask("Want to disconnect now")) logoff(0,1);
  90. }
  91.  
  92. /*
  93.     Message Base commands
  94.  
  95. */
  96.  
  97. msg_base() {
  98. char *cp;
  99. FLAG again;
  100. int n;
  101.  
  102.     gettopic();                    /* select initial topic, */
  103.  
  104.     while (1) {
  105.         mputs("\r\n");
  106.         if (ismsg(msgnbr,topic)) {        /* (msgnbr set elsewere) */
  107.             last_topic= getmsg(msgnbr)-> topic;
  108.             listhdr(msgnbr);        /* display current message */
  109.             n= line;            /* remember current line */
  110.             again= ques("Read it? ");    /* ask the question, */
  111.             mputs("\r");
  112.             if (again) {            /* if it was Yes, */
  113.                 line= n;        /* keep header on screen */
  114.                 listmsg(msgnbr);    /* read it */
  115.                 updclr(msgnbr,topic);    /* update newest read */
  116.             }
  117.         }
  118.         do {
  119.             again= 0;            /* command error flag */
  120.             cp= getarg("E)nter P)revious J)ump! G)oodbye! T)opic Q)uit (?=help CR=Next-Msg): ");
  121.             switch (tolower(*cp)) {
  122.                 case 't': gettopic(); break;
  123.                 case 'j': pickmsg(); break;
  124.                 case NUL: nxtnbr(1); break;
  125.                 case 'p': nxtnbr(-1); break;
  126.                 case 'q': return;
  127.  
  128.                 case 'g': again= 1; goodbye(); break;
  129.                 case '?': again= 1; dspfile("message.hlp"); break;
  130.                 case 'e': again= 1; msend(); break;
  131.                 default: again= 1; mprintf("eh?\r\n"); break;
  132.             }
  133.         } while (again);
  134.     }
  135. }
  136.  
  137. /* Pick a place to start reading messages. OK, now we might get anything as 
  138. input, since there's no agreeing on the "right" way to enter dates. This 
  139. mess below will accept "12 dec", "dec 12", "dec" (means 1 Dec) "12 dec 87", 
  140. "dec 12 87" or "dec" when this is Jan; it assumes you mean Dec. of the 
  141. previous year. */
  142.  
  143. pickmsg() {
  144. int i;
  145. char *cp,buff[SS];
  146. WORD w;
  147.  
  148.     cp= getarg("Jump to message: T)oday U)nread S)earch, or enter a date: ");
  149.  
  150. /* This isnt pretty, but it means we can use any single letter as a 
  151. command name, even if it is the first letter of a month name. */
  152.  
  153.     if (ismonth(cp)) goto manual;
  154.  
  155.     switch (tolower(*cp)) {
  156.         case NUL: return;            /* blank line */
  157.         case 's': mfind(); break;        /* text search */
  158.         case 't': w= gdate(); break;        /* from today */
  159.         case 'u': w= oldest(topic); break;    /* from last call */
  160. manual:;    default: w= getdate(cp); break;        /* get a date, */
  161.     }
  162.     if (w) getnext(w);                 /* duh, do it */
  163.  
  164. /* This is due to a design defeciency in the command line code; no way to
  165. tell it "I took (n) args". So we'll take 'em all! */
  166.  
  167.     cmdflush();
  168. }
  169.  
  170. /* Convert the passed string into a date in a standard time WORD;
  171. return 0 if it failed. Fill in date components not specified with
  172. "today", ie year, month. */
  173.  
  174. getdate(cp)
  175. char *cp;
  176. {
  177. int i;
  178. WORD now;
  179. char day,month,year;
  180.  
  181.     day= atoi(cp);                /* maybe day is first */
  182.     if (day) cp= next_arg(cp);        /* if so month follows */
  183.     month= ismonth(cp);            /* does it? */
  184.     if (! month) return(0);            /* sorry */
  185.  
  186.     year= 0;                /* no year specified */
  187.     cp= next_arg(cp);            /* if a number follows */
  188.     i= atoi(cp);                /* its the day or year */
  189.     if (i > 1900) year= i - 1900;        /* its year, obviously */
  190.     else if (!day && (i < 32)) day= i;    /* if no day yet assume that */
  191.     else year= i;                /* damfino */
  192.     i= atoi(next_arg(cp));            /* if another follows */
  193.     if (i) year= i;                /* gotta be the year */
  194.  
  195. /* If the specified month is after this month, then assume its the
  196. previous year thats wanted. Otherwise the fool doesnt know what month it 
  197. is, or they are calling from beyond the International Date Line, which is
  198. their problem. */
  199.  
  200.     if (! year) {                /* if no year specified */
  201.         now= gdate();
  202.         year= ((now >> 9) & 0x3f) + 80;    /* default to this year */
  203.         if (month > ((now >> 5) & 0x0f)) --year; /* make it last year */
  204.     }
  205.     if (! day) day= 1;            /* in case no day specified */
  206.  
  207.     return(((year - 80) << 9) | (month << 5) | day);
  208. }
  209.  
  210. /* Return the number of the month (1 - 12) if this is a month name, or 0 if
  211. its not a month name. */
  212.  
  213. ismonth(cp)
  214. char *cp;
  215. {
  216. char m[SS];
  217. int i;
  218.  
  219.     cpyarg(m,cp);                /* a clean copy, */
  220.     m[3]= NUL;                /* first three chars only */
  221.     stolower(m); m[0]= toupper(m[0]);    /* lower case first char upper */
  222.     for (i= 1; i < 13; i++) {        /* 0 is "Eh?" */
  223.         if (strcmp(m,months[i]) == 0) return(i);
  224.     }
  225.     return(0);                /* not a month */
  226. }
  227.  
  228. /* Locate the first message since the passed time & date. */
  229.  
  230. getnext(date)
  231. WORD date;
  232. {
  233. int n;
  234.  
  235.     n= msgnbr= oldest_msg();        /* start at the bottom, */
  236.  
  237. /* If the message was created on or after the callers last login ... break */
  238.  
  239.     while (1) {
  240.         if (getmsg(msgnbr)-> date >= date) break;
  241.         if (! nxtnbr(1)) break;        /* try the next one */
  242.         n= msgnbr;            /* remember last good one */
  243.     }
  244.     msgnbr= n;
  245. }
  246.  
  247. /* Pick the next message number that exists and is in the right topic.
  248. This sets & returns 0 if we hit the top or the bottom. */
  249.  
  250. nxtnbr(direction)
  251. int direction;
  252. {
  253.  
  254.     while (1) {
  255.         if (msgnbr > oldest_msg()) {    /* at the bottom? */
  256.             msgnbr= oldest_msg();
  257.             mprintf("\r\nOLDEST MESSAGE\r\n");
  258.             return(0);
  259.  
  260.         } 
  261.         if (msgnbr < newest_msg()) {    /* hit the top? */
  262.             msgnbr= newest_msg();
  263.             mprintf("\r\nNEWEST MESSAGE\r\n");
  264.             return(0);
  265.         }
  266.         msgnbr -= direction;        /* next number, */
  267.         if (ismsg(msgnbr,topic)) return(msgnbr);
  268.     }
  269. }
  270.  
  271. /* Make the user select a topic; return the bit fields set. */
  272.  
  273. gettopic() {
  274. int n;
  275. char *cp;
  276.  
  277.     while (1) {
  278.         if (! isargs()) {
  279.             mputs("Choose one or more TOPIC numbers:\r\n");
  280.             for (n= 0; n < 16; n++) {    /* list them all, */
  281.                 if (*pup.topic[n].name) 
  282.                     mprintf("#%d %-8s %s\r\n",n + 1,pup.topic[n].name,pup.topic[n].desc);
  283.             }
  284.             mprintf("#A          Choose ALL topics\r\n");
  285.         }
  286.         topic= 0;                /* start with this */
  287.         cp= getarg("Choose topic(s) #");    /* ask for them, */
  288.         while (*cp) {                /* check each one */
  289.             if (tolower(*cp) == 'a') {    /* if ALL */
  290.                 topic= alltopics();    /* select all */
  291.  
  292.             } else {            /* must be a number */
  293.                 n= atoi(cp);
  294.                 if ((n > 0) && (n < 16)) { /* if in range, */
  295.                     --n;
  296.                     if (*pup.topic[n].name) 
  297.                         topic |= (1 << n);
  298.                 }
  299.             }
  300.             cp= next_arg(cp);        /* ptr to next arg (if any) */
  301.         }
  302.         cmdflush();                /* pitch input line we just ate */
  303.         if (topic) break;
  304.     }    
  305.     last_topic= topic;                /* change of topics */
  306.     getnext(oldest(topic));                /* select the next to read */
  307.     return(topic);                    /* return 'em when we get 'em */
  308. }
  309.  
  310. /* Search the message base for content. Return true if the thing was found. */
  311.  
  312. mfind() {
  313. char pattern[SS];
  314. struct _msg *m;
  315.  
  316. char *strfnd();
  317.  
  318.     while (1) {
  319.         cpyarg(pattern,getarg("Search for what? (CR=Quit, ?=Help): "));
  320.         if (*pattern == '?') dspfile("find.hlp"); /* ? is help */
  321.         else if (! *pattern) return(0);        /* just a CR */
  322.         else break;                /* anything else */
  323.     }
  324.     mputs("Wait ... (Control-C to abort)\r\n");
  325.     while (nxtnbr(1)) {                /* find a message, */
  326.         pollkbd();                /* check the keyboard */
  327.         if (abort) break;            /* allow stopping */
  328.         m= getmsg(msgnbr);            /* get this msg */
  329.         if (strfnd(m-> to,pattern)) return(1);    /* check each field */
  330.         if (strfnd(m-> from,pattern)) return(1);
  331.         if (strfnd(m-> subj,pattern)) return(1);
  332.         loadmsg(msgnbr);            /* get the msg body, */
  333.         if (strfnd(text,pattern)) return(1);    /* search that */
  334.     }
  335.     return(0);
  336. }
  337.  
  338. /* Edit-message commands. Returns true if the message should be saved. */
  339.  
  340. msend() {
  341. int lineno;        /* last used line number */
  342. char *cp;
  343. int i;
  344. struct _msg *msg;    /* ptr to new message */
  345.  
  346.     msg= newmsg();                /* ptr to our new message */
  347.     msg-> date= gdate();            /* get the current time, */
  348.     msg-> time= gtime();
  349.     strcpy(msg-> from,caller.name);        /* set From: */
  350.     mprintf("FROM: %s\r\n",caller.name);
  351.     input("TO: ",msg-> to,sizeof(msg-> to));
  352.     if (! *msg-> to) return;
  353.     msg-> topic= last_topic;        /* same as previous topic */
  354.     if (! msg-> topic) msg-> topic= topic;    /* or a new one */
  355.     mputs("TOPIC:"); topics(msg-> topic); mputs("\r\n");
  356.     input("TITLE: ",msg-> subj,sizeof(msg-> subj));
  357.     if (! *msg-> subj) return;
  358.  
  359.     cp= text; i= pup.msgsize;        /* clear out the text buffer */
  360.     while (i--) *cp++= NUL;
  361.  
  362.     mprintf("Enter your message,\r\nControl-C or Control-K to end\r\n");
  363.     lineno= edit(0);            /* get some new text */
  364.  
  365.     while (1) {
  366.         cp= "\r\nEdit: C)ancel A)dd L)ist I)ns D)el S)ave (?=help): ";
  367.         cp= getarg(cp);
  368.         switch (tolower(*cp)) { 
  369.             case '?': dspfile("edit.hlp"); break;
  370.             case NUL: break;
  371.             case 'c': if (ask("Cancel this message")) return(0); break;
  372.             case 'a': lineno= edit(lineno); break;
  373.             case 'l': listhdr(oldest_msg());
  374.                 for (i= 0; i < lineno; i++) {
  375.                     msgline(i);
  376.                     if (abort) break;
  377.                 }
  378.                 break;
  379.  
  380.             case 'i':
  381.                 i= getlno("Insert before line #",lineno);
  382.                 if (i < 0) break;
  383.                 lineno= edit(i);
  384.                 break;
  385.  
  386.             case 'd':
  387.                 i= getlno("Delete line #",lineno);
  388.                 if (i < 0) break;
  389.                 lineno= del_line(i,lineno);
  390.                 break;
  391.  
  392.             case 's':
  393.                 mprintf("Saving new message\r\n");
  394.                 savemsg(lineno);
  395.                 ++msgnbr;        /* new top means all shift down */
  396.                 return(1);
  397.  
  398.             default:
  399.                 mprintf("eh?\r\n");
  400.                 cmdflush();
  401.                 break;
  402.         }
  403.     } 
  404. }
  405.  
  406. /* Display a message line. */
  407.  
  408. msgline(n)
  409. int n;
  410. {
  411. char *s;
  412.  
  413.     s= &text[n * caller.cols];        /* s == ptr to line to display */
  414.     mprintf("%2u: ",n + 1);            /* display line number, */
  415.     while (*s && !abort) {            /* until done or Control-K */
  416.         if (*s >= ' ') mconout(*s);    /* output them */
  417.         ++s;
  418.     }
  419.     mputs("\r\n");
  420. }
  421.  
  422. /* Get a line number; return -1 if invalid number. */
  423.  
  424. getlno(ps,lim)
  425. char *ps;
  426. int lim;
  427. {
  428. char *cp;
  429. int n;
  430.  
  431.     n= atoi(getarg(ps)) - 1;        /* get one, (garbage becomes -1) */
  432.     if (n >= lim) {
  433.         mprintf("Must be 1 to %d\r\n",lim);
  434.         n= -1;
  435.     }
  436.     return(n);
  437. }
  438.