/****************************************************************************** * Metal Enter (send) message routine. * * File name: MESEND.C * * Metal and Metal Message System are Trademarked and * Copyright (c) 1984,1985,1986 Tim Gary * All rights reserved. * * This module contains the message entry routine (enter, reply, etc) * ***************************************************************************** * * 1.50xx 08/13/86 User.phone klude stuff added, fix for new free_space * 1.50xx 08/04/86 Disable wrap flag set for upload mode. * 1.50xx 04/12/86 Warning added for max message lines.. * 1.50xx 03/17/86 Group menu fixed, allow full/partial group "Name" selection * 1.50xx 03/10/86 Group/section menu added for entering a message.. * 1.50xx 03/06/86 Faster summary lookup.. * 1.50xx 03/04/86 Fix bug causing messages to be tagged.. * 1.40xx 02/28/86 Deleted msg[].reply references.. use msg_reply().. * 1.40xx 02/10/86 Help displays from help library.. * 1.40xx 02/06/86 Check for sysop made before valid receiver test.. * 1.40xx 02/05/86 Added check for valid user when entering message.. * 1.40xx 01/26/86 New format of time/date, etc.. * 1.31a 10/13/85 Release version. Cosmetic changes, Check for disk space * remaining before allowing message entry. * 1.30xx 6/15/85 Subject of APPLY command 'New User Application'. * 1.30xx 6/09/85 EOL char added for edit command, subject ok prompt fixed. * 1.30xx 3/03/85 Z3 stuff looked into and general touchups * 1.20b 01/10/85 Add link to messages for sysop enter message.. * 1.20b 01/07/85 Alternate end of message text char, and blank line accept * 1.20a 11/07/84 Subject confirmation on reply. * 1.20a 11/04/84 Apply stuff added, private msg to sysop. * 1.10e 11/02/84 Fixed for new get/put counters. * 1.10e 10/30/84 Added privmsgs counter. * 1.10b 10/02/84 Cosmetics (deleted extra spaces). * 1.10a 9/28/84 Edit bug looked into. * 1.10a 9/27/84 More cosmetic fixes. * 1.10a 9/14/84 Added simplistic line edit of message text... * 1.10a 9/01/84 Routine taken from MS.C for overlay metal. * * 1.01a 7/14/84 Message editing bugs fixed (delete line.. movmem changed). * Added subject truncation notice on message entry. * 1.01a 6/30/84 Cleaned up more functions. * 1.01a 6/26/84 Cleaned up a few functions, and added MULTI_USER stuff. * 1.01a 6/10/84 Fixed to work with Aztec C 1.06. Started Multi-user stuff. * * 1.0b 4/13/84 Modified for upper/lower case names, and added check for * maximum messages allowed (killed and active ones). * * 1.0a 3/16/84 Fixed reply bug. * * 1.0 1/20/84 New format of Message file headers. * p3.0 12/14/83 pre-release version 3.0 mods for MCONFIG.. * *****************************************************************************/ #include "xpm.h" /* CPMIO header file for i/o operations.*/ #include "megen.h" /* general defines */ #include "meglob.h" /* global variable definitions */ #include "meovfn.h" /* overlay function numbers */ #include "mefiles.h" /* file names */ #include "ctype.h" #define NOPOSTHLP "MSGNOPSTHLP" #define PRIVHLP "MSGPRIV HLP" #define ENTERHELP "MSGENTERHLP" #define UPLOADHLP "MSGUPLD HLP" static char *lp[MAXMLINES]; /* array of pointers to msg text lines */ /************************************************************************** * enter a message, or reply to a message... mode=0 to enter, -1 to reply * * or msg # to reply without asking for #.. (ie for read/reply) * ************************************************************************** * if func=0, then reply or enter, if func=1 then APPLY command, private * message to sysop (subject 'New User Application'), func=2 then comments * to the system.. */ ovmain(func,mode) int func; /* definition required, but variable not used */ unsigned mode; { char *ptr,temp[81],*reserve; /* reserve=reserved alloc block for files */ int a,b,c,edit_mode; unsigned space_left,free_space(); register int loop,line; if (!(user.type_ptr->privflags & POSTMSG) && func<1) { ltype(METHELP,NOPOSTHLP); /* user can't post messages til sysop.. */ return; } summary=open(SUMMARY,F_RD); space_left=free_space(summary->_fcb.f_drive); close(summary); /* effect of loging disk */ if ((totalmsgs>=O.MAXTOTMSGS) || (msgcount>=O.MAXMSGS) || space_left<10) { send("\nSorry, the message base is full.\nPlease try to leave your message at a later time."); return; } if (mode==0) /* regular msg entry */ { if (func<1) { GET_TO: ask("Who to (RETURN for all) ? ", message.receiver,NAMELEN,UPLOW); capstr(message.receiver); if (message.receiver[0]=='\0') strcpy(message.receiver,"ALL USERS"); else { users=open(USERFILE,0); if (ustrcmp(message.receiver,"sysop")) if (find_user(message.receiver)<0) { send("\n[There is nobody on the system by that name]\n"); ask("Enter message anyway (y/n)? ",temp,2,UP); users=close(users); putchar('\n'); if (*temp=='N') goto GET_TO; } users=close(users); } } else { strcpy(message.receiver,"Sysop"); send("To: Sysop\n"); } if (func!=1) { if (get_topic(message.topic)==ERROR) return; } else { strcpy(message.topic,"* New User Application *"); askquest(); /* ask sysop defined qestion */ } } else { /* reply to message */ if ((int)mode==-1) /* regular reply command.. */ { ask("Reply to what message ? ",temp,6,UP); if (!isdigit(*temp)) return; /* not alpha, return to command */ mode=atoi(temp); /* convert to number */ if (!mode) return; /* invalid message #=0 */ messages=open(MESSAGES,F_RD | F_UNLOCK); /* the following assumes open file */ } /* both regular and read/reply use the following */ /* mode=message number replying to */ /* file must be open before... from read, or whatever.. */ a=getindex(mode); /* get index into msg array, of msg mode */ if (a==ERROR) { close(messages); send("\n[Message not found]\n"); return; } setarec(messages,msg[a].seek); /* seek to message replying to */ read(messages,0); /* get the header */ movmem(bufloc(messages),&message,128); /* get stuff into structure */ strcpy(message.receiver,message.sender); printf("\nTo: %s\nAbout: %s ** %s **", message.receiver,message.topic,group[message.group].name); close(messages); /* close the file */ do send("\n[Is the subject ok (y/n)? ] "); while ((c=tolower(getd()))!='n' && c!='y'); if (c=='n') { send("[no]\n"); if (get_topic(message.topic)==ERROR) return; } else send("[yes]\n"); if (message.status==DEADMSG) mode=0; /* make rest of stuff nonrep */ } /* end of initial reply stuff all the rest of entermsg is as it was, except to end where pointers are setup to the reply */ if (func>=1) { send("\nMessage will be Private.\n"); message.status=PRIVMSG; } else do { message.status=NORMMSG; /* default to normal message */ if (strcmp(message.receiver,"ALL USERS") || !(user.type_ptr->privflags & POSTPRIV)) { send("(Private/Normal) ?"); getl(buffer,UP); *buffer=tolower(*buffer); } else *buffer='n'; if (*buffer=='p') message.status=PRIVMSG; /* private msg */ else if (*buffer=='?') { ltype(METHELP,PRIVHLP); continue; /* and ask again */ } else if (*buffer!='n') send("[Normal (public) message]\n"); break; /* what, you say??? yeh, yeh.. see the continue above?? */ } while (TRUE); if ( !(user.flags&EXPERT) ) /* not expert.. tell him what to do */ { sprintf(buffer, "\nEnter message text following each line number.\ \nTo edit or end, hit RETURN alone on a line.\ \nUp to %d characters (letters/numbers) on a line,\ \nand %d lines maximum.\n",O.MAXMSGLINE,O.MLINES); send(buffer); } reserve=malloc(2*(sizeof(FILE))+10); /* make sure there's room for files */ edit_mode=ON; /* blank line to enter editor */ /********************************/ /* Lines may be up to MAXMSGLINE long, and up to MLINES lines */ /* can be entered... limitted by avaliable memory only! */ /********************************/ /* Main loop */ /****************/ for (line=1; line<=O.MLINES; line++) { cont: printf("%2d%c ",line,edit_mode ? ':' : '/'); getl(buffer,UPLOW+(edit_mode ? MSGLINE : 0)); /* get line up to MAXLINE long */ if ((edit_mode==ON && *buffer=='\0') || (edit_mode==OFF && !strcmp(buffer,"/")) ) break; if (save_line(line,buffer)==ERROR) break; /* above allocs space, and puts line there if room.. ERROR==no room */ if (line>O.MLINES-3) send("::: 3 lines left :::\n"); } do { if ( !(user.flags&EXPERT) ) { send("\n(A)bort, (C)ontinue, (D)elete, (E)dit,\n\ (I)nsert, (L)ist, (R)eplace, (S)ave"); if (user.status==SYSOP) send("\n(F)ile read"); send(" :: Select"); } else if (user.status!=SYSOP) send("\nA,C,D,E,I,L,R,S,U"); else send("\nA,C,D,E,I,L,R,S,U,F"); sepstr=' '; ask(" ? ",temp,10,UP|NOTOS); sepstr='\0'; switch (*temp) { case '?': ltype(METHELP,ENTERHELP); if (user.status==SYSOP) send("\n(F)ile transfer to message text\n"); break; case 'A': ask("Are you sure you wish to abort message entry? ", buffer,3,UP); if (*buffer!='Y') break; /* nope, not sure */ for (loop=0; loopO.MLINES+10) break; /* can cheat 10 times */ goto cont; /* yuk!!!!!!!!!!!!! */ case 'D': line=del_line(line); break; case 'E': edit_line(line); break; case 'F': if (user.status==SYSOP) line=read_file(line); break; case 'I': line=ins_line(line); break; case 'L': for (loop=1; (loopnumber; movmem(&user,bufloc(users),128); /* get user vars */ user.number=un; write(users,0); /* write record, no increment... */ close(users); /* either method called closes the users file */ return NULL; /* NULL=all's well */ } get_topic(s) char *s; { char temp[81],temp1[81]; register int gr; sprintf(temp1,"Group (return=** %s **, '?' for list) ? ",group[0].name); do { gr=0; ask(temp1,temp,40,UP); if (*temp=='\0') break; if (*temp=='?') /* display available groups */ { send("\nEnter one of the following numbers:\n\n"); for (gr=0; gr0 && gr<=n_groups) { if (group[gr-1].read_flags & user.group_flags) { --gr; break; } send("\n[Group not found]\n"); } else if (!gr) { int i; for (i=(-1),gr=0; grTOPICLEN) /* tell him it's too long.. */ { temp[TOPICLEN]='\0'; /* truncate topic */ printf("\nSubject truncated to: %s\n",temp); ask("Is this ok (y/n)? ",temp+TOPICLEN+2,2,UP); if (temp[TOPICLEN+2]=='N') goto about; /* ask topic again */ if (temp[TOPICLEN+2]!='Y') send("[Yes assumed]\n"); } /* I'm sick of slandering goto, in certain cases, it makes life much easier... */ strcpy(message.topic,temp); if (!(*message.topic)) return ERROR; /* return hit? yep->return */ return NULL; } /******************************************************** * save line pointed to by buf, in message buffer.. * ********************************************************/ save_line(line,buf) register int line; register char *buf; { if ((lp[line-1]=malloc(strlen(buf)+2))==0) /* try to get space */ { send("\n[Message buffer full!! Line not entered]\n\ [Please save message, and continue in a new one]\n"); return ERROR; /* and exit to enter command mode */ } strcpy(lp[line-1],buf); /* setup line pointer for later use */ return NULL; } /***************************************** * read in a message from a regular file * *****************************************/ read_file(line) register int line; { char file[20]; register FILE *fd; register int oline; char *bp; int i; oline=line; /* for ending output of # lines read */ ask("\nFile to copy to message text? ",file,19,UP); if ((fd=open(file,0))!=NULL) /* try to open file */ { read(fd,1); /* fgets needs initial read */ while (line<=O.MLINES && i!=0x1a && i!=EOF) { bp=buffer; while (1) { if ((i=getc(fd))==EOF) break; if (i=='\r' || i==0x1a) break; if (i!='\n') *bp++=i; } *bp='\0'; /* terminate string */ if (save_line(line,buffer)==ERROR) break; /* no space */ send("\n"); /* to allow ^s */ printf("%2d: %s",line++,buffer); } printf("\n\n[%d lines read from %s]\n",line-oline,file); close(fd); } else send("[File NOT found]"); return line; } ins_line(cline) register int cline; { register char *ptr; register int ln,loop; char temp[11]; if (cline0) && (ln<=cline)) { printf("%3d: ",ln); getl(buffer,UPLOW+MSGLINE); if ((ptr=malloc(strlen(buffer)+2))==0) { send("\n[Message buffer FULL, line not entered!]\n"); return cline; } /* move line pos pointers up a line */ for (loop=cline+2; loop>=ln; loop--) lp[loop]=lp[loop-1]; lp[ln-1]=ptr; strcpy(ptr,buffer); /* insert the line */ cline++; /* one more line */ } else send("\n[Invalid line]"); } else { sprintf(buffer,"\n[Max of %d lines!!]",O.MLINES); send(buffer); } return cline; } /* ins_line */ del_line(cline) register int cline; { register int ln ,i; char temp[11]; ask("Delete which line ?",temp,10,UP); putchar('\n'); ln=atoi(temp); if ((ln>0) && (ln0) && (ln0) && (lnO.MAXMSGLINE) { send("\nNew line to long. Edit aborted.\n"); return; } printf("\n%3d: %s\n",ln,buffer); free(lp[ln-1]); save_line(ln,buffer); } else send("\n[Invalid line]"); } /* edit_line */ /* End of file */