home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / dos / sbbs_src.exe / SBBS / SMM / SMM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-25  |  102.3 KB  |  3,992 lines

  1. /* SMM.C */
  2.  
  3. /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
  4.  
  5. /* Synchronet Match Maker */
  6.  
  7. #include "xsdk.h"
  8. #include "crc32.h"
  9. #include "smmdefs.h"
  10. #include "smmvars.c"
  11.  
  12. /* RCIOLL.ASM */
  13.  
  14. int  rioini(int com,int irq);          /* initialize com,irq */
  15. int  setbaud(int rate);                /* set baud rate */
  16. int  rioctl(int action);               /* remote i/o control */
  17. int  dtr(char onoff);                  /* set/reset dtr */
  18. int  outcom(int ch);                   /* send character */
  19. int  incom(void);                      /* receive character */
  20. int  ivhctl(int intcode);              /* local i/o redirection */
  21.  
  22. /************************/
  23. /* Remote I/O Constants */
  24. /************************/
  25.  
  26.                             /* i/o mode and state flags */
  27. #define CTSCK 0x1000         /* check cts (mode only) */
  28. #define RTSCK 0x2000        /* check rts (mode only) */
  29. #define TXBOF 0x0800        /* transmit buffer overflow (outcom only) */
  30. #define ABORT 0x0400         /* check for ^C (mode), aborting (state) */
  31. #define PAUSE 0x0200         /* check for ^S (mode), pausing (state) */
  32. #define NOINP 0x0100         /* input buffer empty (incom only) */
  33.  
  34.                             /* status flags */
  35. #define RIODCD    0x80        /* DCD on */
  36. #define RI        0x40        /* Ring indicate */
  37. #define DSR     0x20        /* Dataset ready */
  38. #define CTS     0x10           /* CTS on */
  39. #define FERR     0x08        /* Frameing error */
  40. #define PERR     0x04        /* Parity error */
  41. #define OVRR     0x02        /* Overrun */
  42. #define RXLOST     0x01           /* Receive buffer overflow */
  43.  
  44. /* rioctl() arguments */
  45. /* returns mode or state flags in high 8 bits, status flags in low 8 bits */
  46.  
  47.                             /* the following return mode in high 8 bits */
  48. #define IOMODE 0            /* no operation */
  49. #define IOSM 1              /* i/o set mode flags */
  50. #define IOCM 2              /* i/o clear mode flags */
  51.                             /* the following return state in high 8 bits */
  52. #define IOSTATE 4           /* no operation */
  53. #define IOSS 5              /* i/o set state flags */
  54. #define IOCS 6              /* i/o clear state flags */
  55. #define IOFB 0x308          /* i/o buffer flush */
  56. #define IOFI 0x208          /* input buffer flush */
  57. #define IOFO 0x108          /* output buffer flush */
  58. #define IOCE 9              /* i/o clear error flags */
  59.  
  60.                             /* return count (16bit)    */
  61. #define RXBC    0x0a        /* get receive buffer count */
  62. #define TXBC    0x0b        /* get transmit buffer count */
  63. #define TXSYNC  0x0c        /* sync transmition (seconds<<8|0x0c) */
  64. #define IDLE    0x0d        /* suspend communication routines */
  65. #define RESUME  0x10d        /* return from suspended state */
  66. #define RLERC    0x000e        /* read line error count and clear */
  67. #define CPTON    0x0110        /* set input translation flag for ctrl-p on */
  68. #define CPTOFF    0x0010        /* set input translation flag for ctrl-p off */
  69. #define GETCPT    0x8010        /* return the status of ctrl-p translation */
  70. #define MSR     0x0011        /* read modem status register */
  71. #define FIFOCTL 0x0012        /* FIFO UART control */
  72. #define TSTYPE    0x0013        /* Time-slice API type */
  73. #define GETTST  0x8013      /* Get Time-slice API type */
  74.  
  75.  
  76. #define I14DB    0x001d        /* DigiBoard int 14h driver */
  77. #define I14PC    0x011d        /* PC int 14h driver */
  78. #define I14PS    0x021d        /* PS/2 int 14h driver */
  79. #define I14FO   0x031d      /* FOSSIL int 14h driver */
  80.  
  81.  
  82.                             /* ivhctl() arguments */
  83. #define INT29R 1             /* copy int 29h output to remote */
  84. #define INT29L 2            /* Use _putlc for int 29h */
  85. #define INT16  0x10          /* return remote chars to int 16h calls */
  86. #define INTCLR 0            /* release int 16h, int 29h */
  87.  
  88. #define CLREOL        256     /* Character to erase to end of line        */
  89. #define HIGH        8       /* High intensity for curatr             */
  90.  
  91. extern uint riobp;
  92. extern int mswtyp;
  93.  
  94. unsigned _stklen=16000;     /* Set stack size in code, not header */
  95.  
  96. int cbreakh(void);            /* ctrl-break handler */
  97.  
  98. char getage(char *birth);
  99. char long_user_info(user_t user);
  100. void main_user_info(user_t user);
  101.  
  102. char *nulstr="";
  103. char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
  104. char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
  105.             ,"Jul","Aug","Sep","Oct","Nov","Dec"};
  106. char tmp[256],door_sys[128];
  107.  
  108. char io_int=0;
  109. struct date date;
  110. struct time curtime;
  111. time_t now;
  112. int smm_pause=1,node_scrnlen;
  113. questionnaire_t *que[5];
  114. int total_ques;
  115. user_t useron,tmpuser;
  116. ixb_t ixb;
  117. ulong useron_record,system_crc;
  118. FILE *stream,*index,*trashfile;
  119.  
  120. char *PrevReadSendQuitOrMore="\r\n\1n\1b\1h[\1cP\1b]revious screen, "
  121.     "[\1cR\1b]ead profile, [\1cS\1b]end telegram, [\1cQ\1b]uit, or "
  122.     "[\1cM\1b]ore: \1w";
  123.  
  124. int intocm(int in)
  125. {
  126. return(in*2.538071);
  127. }
  128.  
  129. int cmtoin(int cm)
  130. {
  131.     int i;
  132.  
  133. i=cm*0.394;
  134. if(((float)cm*0.394)-(float)i>=.5)
  135.     i++;
  136. return(i);
  137. }
  138.  
  139. int kgtolp(int kg)
  140. {
  141. return(kg*2.2046);
  142. }
  143.  
  144. int lptokg(int lp)
  145. {
  146.     int i;
  147.  
  148. i=lp*0.453597;
  149. if(((float)lp*0.453597)-(float)i>=.5)
  150.     i++;
  151. return(i);
  152. }
  153.  
  154. /****************************************************************************/
  155. /* Performs printf() through local assembly routines                        */
  156. /* Called from everywhere                                                   */
  157. /****************************************************************************/
  158. int lprintf(char *fmat, ...) {
  159.     char sbuf[256];
  160.     int chcount;
  161.  
  162. chcount=vsprintf(sbuf,fmat,_va_ptr);
  163. lputs(sbuf);
  164. return(chcount);
  165. }
  166.  
  167. /*****************************************************************************/
  168. /* Returns command line generated from instr with %c replacments             */
  169. /*****************************************************************************/
  170. char *cmdstr(char *instr, char *fpath, char *fspec, char *outstr)
  171. {
  172.     static char static_cmd[128];
  173.     char str[256],str2[128],*cmd;
  174.     int i,j,len;
  175.  
  176. if(outstr==NULL)
  177.     cmd=static_cmd;
  178. else
  179.     cmd=outstr;
  180. len=strlen(instr);
  181. for(i=j=0;i<len && j<128;i++) {
  182.     if(instr[i]=='%') {
  183.         i++;
  184.         cmd[j]=0;
  185.         switch(toupper(instr[i])) {
  186.             case 'A':   /* User alias */
  187.                 strcat(cmd,user_name);
  188.                 break;
  189.             case 'B':   /* Baud (DTE) Rate */
  190.                 strcat(cmd,ultoa(com_rate,str,10));
  191.                 break;
  192.             case 'C':   /* Connect Description */
  193.                 strcat(cmd,ultoa(user_dce,str,10));
  194.                 break;
  195.             case 'F':   /* File path */
  196.                 strcat(cmd,fpath);
  197.                 break;
  198.             case 'G':   /* Temp directory */
  199.                 strcat(cmd,temp_dir);
  200.                 break;
  201.             case 'I':   /* UART IRQ Line */
  202.                 strcat(cmd,itoa(com_irq,str,10));
  203.                 break;
  204.             case 'J':
  205.                 strcat(cmd,data_dir);
  206.                 break;
  207.             case 'K':
  208.                 strcat(cmd,ctrl_dir);
  209.                 break;
  210.             case 'N':   /* Node Directory (same as SBBSNODE environment var) */
  211.                 strcat(cmd,node_dir);
  212.                 break;
  213.             case 'O':   /* SysOp */
  214.                 strcat(cmd,sys_op);
  215.                 break;
  216.             case 'P':   /* COM Port */
  217.                 strcat(cmd,itoa(com_port,str,10));
  218.                 break;
  219.             case 'Q':   /* QWK ID */
  220.                 strcat(cmd,sys_id);
  221.                 break;
  222.             case 'R':   /* Rows */
  223.                 strcat(cmd,itoa(user_rows,str,10));
  224.                 break;
  225.             case 'S':   /* File Spec */
  226.                 strcat(cmd,fspec);
  227.                 break;
  228.             case 'T':   /* Time left in seconds */
  229.                 strcat(cmd,itoa(time(NULL)-starttime,str,10));
  230.                 break;
  231.             case 'U':   /* UART I/O Address (in hex) */
  232.                 strcat(cmd,itoa(com_base,str,16));
  233.                 break;
  234.             case 'W':   /* Time-slice API type (mswtype) */
  235. #ifndef __OS2__
  236.                 strcat(cmd,itoa(mswtyp,str,10));
  237. #endif
  238.                 break;
  239.             case '&':   /* Address of msr */
  240.                 sprintf(str,"%lu",&riobp-1);
  241.                 strcat(cmd,str);
  242.                 break;
  243.             case 'Z':
  244.                 strcat(cmd,text_dir);
  245.                 break;
  246.             case '!':   /* EXEC Directory */
  247.                 strcat(cmd,exec_dir);
  248.                 break;
  249.             case '#':   /* Node number (same as SBBSNNUM environment var) */
  250.                 sprintf(str,"%d",node_num);
  251.                 strcat(cmd,str);
  252.                 break;
  253.             case '*':
  254.                 sprintf(str,"%03d",node_num);
  255.                 strcat(cmd,str);
  256.                 break;
  257.             case '$':   /* Credits */
  258.                 strcat(cmd,ultoa(user_cdt,str,10));
  259.                 break;
  260.             case '%':   /* %% for percent sign */
  261.                 strcat(cmd,"%");
  262.                 break;
  263.             default:    /* unknown specification */
  264.                 if(isdigit(instr[i])) {
  265.                     sprintf(str,"%0*d",instr[i]&0xf,user_number);
  266.                     strcat(cmd,str); }
  267.                 break; }
  268.         j=strlen(cmd); }
  269.     else
  270.         cmd[j++]=instr[i]; }
  271. cmd[j]=0;
  272.  
  273. return(cmd);
  274. }
  275.  
  276. char *base41(unsigned int i, char *str)
  277. {
  278.     char c;
  279.     unsigned int j=41*41,k;
  280.  
  281. for(c=0;c<3;c++) {
  282.     k=i/j;
  283.     str[c]='0'+k;
  284.     i-=(k*j);
  285.     j/=41;
  286.     if(str[c]>=':')
  287.         str[c]='A'+(str[c]-':');
  288.     if(str[c]>='[')
  289.         str[c]='#'+(str[c]-'['); }
  290. str[c]=0;
  291. return(str);
  292. }
  293.  
  294. /****************************************************************************/
  295. /* Updates 16-bit "rcrc" with character 'ch'                                */
  296. /****************************************************************************/
  297. void ucrc16(uchar ch, ushort *rcrc) {
  298.     ushort i, cy;
  299.     uchar nch=ch;
  300.  
  301. for (i=0; i<8; i++) {
  302.     cy=*rcrc & 0x8000;
  303.     *rcrc<<=1;
  304.     if (nch & 0x80) *rcrc |= 1;
  305.     nch<<=1;
  306.     if (cy) *rcrc ^= 0x1021; }
  307. }
  308.  
  309. /****************************************************************************/
  310. /* Returns 16-crc of string (not counting terminating NULL)                 */
  311. /****************************************************************************/
  312. ushort crc16(char *str)
  313. {
  314.     int     i=0;
  315.     ushort  crc=0;
  316.  
  317. ucrc16(0,&crc);
  318. while(str[i])
  319.     ucrc16(str[i++],&crc);
  320. ucrc16(0,&crc);
  321. ucrc16(0,&crc);
  322. return(crc);
  323. }
  324.  
  325.  
  326. int cdt_warning(long cdt)
  327. {
  328. if(cdt==0)
  329.     return(1);
  330. if(cdt>0) {
  331.     bprintf("\1m\1hYou will receive \1w%luk\1m in credits for this action!\r\n"
  332.         ,cdt/1024L);
  333.     return(1); }
  334.  
  335. bprintf("\1m\1hThis action will cost you \1w%luk\1m in credits.",(-cdt)/1024L);
  336. if(user_cdt+cdt_adjustment<-cdt) {
  337.     bprintf("\r\n\r\n\1r\1hSorry, you only have \1w%luk\1m in credits.\r\n"
  338.         ,(user_cdt+cdt_adjustment)/1024L);
  339.     return(0); }
  340. return(!noyes(" Continue"));
  341. }
  342.  
  343. void adjust_cdt(long cdt)
  344. {
  345. if(cdt==0)
  346.     return;
  347. cdt_adjustment+=cdt;
  348. }
  349.  
  350. int got_flags(char *req, char *got)
  351. {
  352.     int i,j;
  353.  
  354. for(i=0;req[i];i++) {
  355.     for(j=0;got[j];j++)
  356.         if(req[i]==got[j])
  357.             break;
  358.     if(!got[j])
  359.         break; }
  360. if(!req[i])
  361.     return(1);
  362. return(0);
  363. }
  364.  
  365. int can_add()
  366. {
  367.     uchar age=getage(user_birth);
  368.  
  369. if(user_level<min_level || (age && getage(user_birth)<min_age)
  370.     || !got_flags(req_flags1,user_flags1)
  371.     || !got_flags(req_flags2,user_flags2)
  372.     || !got_flags(req_flags3,user_flags3)
  373.     || !got_flags(req_flags4,user_flags4)
  374.     )
  375.     return(0);
  376. return(1);
  377. }
  378.  
  379.  
  380. int trash(char *instr)
  381. {
  382.     char str[128],word[128];
  383.  
  384. if(!trashfile)
  385.     return(0);
  386. strcpy(str,instr);
  387. strupr(str);
  388. rewind(trashfile);
  389. while(!ferror(trashfile)) {
  390.     if(!fgets(word,125,trashfile))
  391.         break;
  392.     truncsp(word);
  393.     if(!word[0])
  394.         continue;
  395.     strupr(word);
  396.     if(strstr(str,word))
  397.         return(1); }
  398. return(0);
  399. }
  400.  
  401. long fdate_dir(char *filespec)
  402. {
  403.     struct ffblk f;
  404.     struct date fd;
  405.     struct time ft;
  406.  
  407. if(findfirst(filespec,&f,FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC)==NULL) {
  408.     fd.da_day=f.ff_fdate&0x1f;
  409.     fd.da_mon=(f.ff_fdate>>5)&0xf;
  410.     fd.da_year=1980+((f.ff_fdate>>9)&0x7f);
  411.     ft.ti_hour=(f.ff_ftime>>11)&0x1f;
  412.     ft.ti_min=(f.ff_ftime>>5)&0x3f;
  413.     ft.ti_sec=(f.ff_ftime&0xf)*2;
  414.     return(dostounix(&fd,&ft)); }
  415. else return(NULL);
  416. }
  417.  
  418. /****************************************************************************/
  419. /* Generates a 24 character ASCII string that represents the time_t pointer */
  420. /* Used as a replacement for ctime()                                        */
  421. /****************************************************************************/
  422. char *timestr(time_t *intime)
  423. {
  424.     static char str[256];
  425.     char mer[3],hour;
  426.     struct tm *gm;
  427.  
  428. gm=localtime(intime);
  429. if(gm->tm_hour>=12) {
  430.     if(gm->tm_hour==12)
  431.         hour=12;
  432.     else
  433.         hour=gm->tm_hour-12;
  434.     strcpy(mer,"pm"); }
  435. else {
  436.     if(gm->tm_hour==0)
  437.         hour=12;
  438.     else
  439.         hour=gm->tm_hour;
  440.     strcpy(mer,"am"); }
  441. sprintf(str,"%s %s %02d %4d %02d:%02d %s"
  442.     ,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
  443.     ,hour,gm->tm_min,mer);
  444. return(str);
  445. }
  446.  
  447.  
  448. void puttgram(int usernumber, char *strin)
  449. {
  450.     char str[256];
  451.     int file,i;
  452.  
  453. sprintf(str,"%4.4u.MSG",usernumber);
  454. if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
  455.     printf("\7Error opening/creating %s for creat/append access\n",str);
  456.     return; }
  457. i=strlen(strin);
  458. if(write(file,strin,i)!=i) {
  459.     close(file);
  460.     printf("\7Error writing %u bytes to %s\n",i,str);
  461.     return; }
  462. close(file);
  463. }
  464.  
  465.  
  466. int send_telegram(user_t user)
  467. {
  468.     uchar str[256],line[256],buf[1024];
  469.     int i;
  470.  
  471. if(!useron.number) {
  472.     bputs("\r\n\1h\1rYou must create a profile first.\r\n");
  473.     pause();
  474.     return(1); }
  475.  
  476. if(user_level<telegram_level) {
  477.     bputs("\r\n\1h\1rYou have insufficient access to send telegrams."
  478.         "\r\n");
  479.     pause();
  480.     return(1); }
  481.  
  482. main_user_info(user);
  483. CRLF;
  484. if(!cdt_warning(telegram_cdt))
  485.     return(0);
  486. if(telegram_cdt)
  487.     CRLF;
  488. bprintf("\1n\1hSending a telegram to \1y%s\1w:\r\n\r\n"
  489.     ,user.name);
  490. now=time(NULL);
  491. memset(buf,0,512);
  492. sprintf(buf,"\1n\1c\1hMatch Maker\1b telegram from \1c%s\1b "
  493.     "on %s:\1y\r\n"
  494.     ,useron.name,timestr(&now));
  495. for(i=0;i<5 && !aborted;i++) {
  496.     bprintf("\1n\1h\1g%u of 5: \1n\1g",i+1);
  497.     if(!getstr(line,70,i==4 ? K_MSG:K_MSG|K_WRAP))
  498.         break;
  499.     sprintf(str,"\1n\1g%4s%s\r\n",nulstr,line);
  500.     strcat(buf,str); }
  501. if(!i || aborted || !yesno("\r\nSave"))
  502.     return(0);
  503. if(!(user.misc&USER_FROMSMB)) {
  504.     putsmsg(user.number,TGRAM_NOTICE);
  505.     puttgram(user.number,buf); }
  506. else {
  507.     if((i=nopen("TELEGRAM.DAB",O_WRONLY|O_CREAT|O_APPEND|SH_DENYNO))
  508.         ==-1) {
  509.         bprintf("\r\n\1r\1h\1iError writing telegram!\r\n");
  510.         pause();
  511.         return(1); }
  512.     write(i,useron.system,sizeof(useron.system));
  513.     write(i,user.system,sizeof(user.system));
  514.     write(i,&user.number,sizeof(user.number));
  515.     write(i,buf,512);
  516.     close(i); }
  517. adjust_cdt(telegram_cdt);
  518. if(notify_user && notify_user!=user_number) {
  519.     sprintf(str,"\1n\1hSMM: \1y%s\1m sent a telegram to \1y%s\1m "
  520.         "from the Match Maker\r\n",user_name,user.name);
  521.     if(node_dir[0])
  522.         putsmsg(notify_user,str);
  523.     else
  524.         puttgram(notify_user,str); }
  525. return(1);
  526. }
  527.  
  528. /****************************************************************************/
  529. /* Returns 32-crc of string (not counting terminating NULL)                 */
  530. /****************************************************************************/
  531. ulong crc32(char *str)
  532. {
  533.     int i=0;
  534.     ulong crc=0xffffffffUL;
  535.  
  536.     while(str[i])
  537.         crc=ucrc32(str[i++],crc);
  538.     crc=~crc;
  539.     return(crc);
  540. }
  541.  
  542.  
  543. /****************************************************************************/
  544. /* Converts unix time format (long - time_t) into a char str MM/DD/YY        */
  545. /****************************************************************************/
  546. char *unixtodstr(time_t unix, char *str)
  547. {
  548.  
  549. if(!unix)
  550.     strcpy(str,"00/00/00");
  551. else {
  552.     unixtodos(unix,&date,&curtime);
  553.     if((unsigned)date.da_mon>12) {      /* DOS leap year bug */
  554.         date.da_mon=1;
  555.         date.da_year++; }
  556.     if((unsigned)date.da_day>31)
  557.         date.da_day=1;
  558.     sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
  559.         ,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
  560. return(str);
  561. }
  562.  
  563. /****************************************************************************/
  564. /* Converts a date string in format MM/DD/YY into unix time format            */
  565. /****************************************************************************/
  566. time_t dstrtounix(char *str)
  567. {
  568.  
  569. if(!strcmp(str,"00/00/00") || !str[0])
  570.     return(NULL);
  571. curtime.ti_hour=curtime.ti_min=curtime.ti_sec=0;
  572. if(str[6]<'7')
  573.     date.da_year=2000+((str[6]&0xf)*10)+(str[7]&0xf);
  574. else
  575.     date.da_year=1900+((str[6]&0xf)*10)+(str[7]&0xf);
  576. date.da_mon=((str[0]&0xf)*10)+(str[1]&0xf);
  577. date.da_day=((str[3]&0xf)*10)+(str[4]&0xf);
  578. return(dostounix(&date,&curtime));
  579. }
  580.  
  581. /****************************************************************************/
  582. /* Returns the age derived from the string 'birth' in the format MM/DD/YY    */
  583. /****************************************************************************/
  584. char getage(char *birth)
  585. {
  586.     char age;
  587.  
  588. if(birth[0]<=SP)
  589.     return(0);
  590. getdate(&date);
  591. age=(date.da_year-1900)-(((birth[6]&0xf)*10)+(birth[7]&0xf));
  592. if(atoi(birth)>12 || atoi(birth+3)>31)
  593.     return(0);
  594. if(((birth[0]&0xf)*10)+(birth[1]&0xf)>date.da_mon ||
  595.     (((birth[0]&0xf)*10)+(birth[1]&0xf)==date.da_mon &&
  596.     ((birth[3]&0xf)*10)+(birth[4]&0xf)>date.da_day))
  597.     age--;
  598. if(age<0)
  599.     return(0);
  600. return(age);
  601. }
  602.  
  603. char marital_ch(char user_marital)
  604. {
  605. switch(user_marital) {
  606.     case MARITAL_SINGLE:
  607.         return('S');
  608.     case MARITAL_DIVORCED:
  609.         return('D');
  610.     case MARITAL_MARRIED:
  611.         return('M');
  612.     case MARITAL_WIDOWED:
  613.         return('W');
  614.     case MARITAL_OTHER:
  615.         return('O'); }
  616. if(user_marital)
  617.     return('*');
  618. return(SP);
  619. }
  620.  
  621. char race_ch(char user_race)
  622. {
  623. switch(user_race) {
  624.     case RACE_WHITE:
  625.         return('W');
  626.     case RACE_BLACK:
  627.         return('B');
  628.     case RACE_HISPANIC:
  629.         return('H');
  630.     case RACE_AMERINDIAN:
  631.         return('I');
  632.     case RACE_ASIAN:
  633.         return('A');
  634.     case RACE_MIDEASTERN:
  635.         return('M');
  636.     case RACE_OTHER:
  637.         return('O'); }
  638. if(user_race)
  639.     return('*');
  640. return(SP);
  641. }
  642.  
  643. char *hair(char user_hair)
  644. {
  645. switch(user_hair) {
  646.     case HAIR_BLONDE:
  647.         return("BLN");
  648.     case HAIR_BROWN:
  649.         return("BRN");
  650.     case HAIR_RED:
  651.         return("RED");
  652.     case HAIR_BLACK:
  653.         return("BLK");
  654.     case HAIR_GREY:
  655.         return("GRY");
  656.     case HAIR_OTHER:
  657.         return("OTH"); }
  658. if(user_hair)
  659.     return("*");
  660. return(nulstr);
  661. }
  662.  
  663. char *eyes(char user_eyes)
  664. {
  665. switch(user_eyes) {
  666.     case EYES_BLUE:
  667.         return("BLU");
  668.     case EYES_BROWN:
  669.         return("BRN");
  670.     case EYES_GREEN:
  671.         return("GRN");
  672.     case EYES_HAZEL:
  673.         return("HAZ");
  674.     case EYES_OTHER:
  675.         return("OTH"); }
  676. if(user_eyes)
  677.     return("*");
  678. return(nulstr);
  679. }
  680.  
  681. char *marital(char user_marital)
  682. {
  683. switch(user_marital) {
  684.     case MARITAL_SINGLE:
  685.         return("Single");
  686.     case MARITAL_MARRIED:
  687.         return("Married");
  688.     case MARITAL_DIVORCED:
  689.         return("Divorced");
  690.     case MARITAL_WIDOWED:
  691.         return("Widowed");
  692.     case MARITAL_OTHER:
  693.         return("Other"); }
  694. if(user_marital)
  695.     return("*");
  696. return(nulstr);
  697. }
  698.  
  699. char *race(char user_race)
  700. {
  701. switch(user_race) {
  702.     case RACE_WHITE:
  703.         return("White");
  704.     case RACE_BLACK:
  705.         return("Black");
  706.     case RACE_HISPANIC:
  707.         return("Hispanic");
  708.     case RACE_ASIAN:
  709.         return("Asian");
  710.     case RACE_AMERINDIAN:
  711.         return("American Indian");
  712.     case RACE_MIDEASTERN:
  713.         return("Middle Eastern");
  714.     case RACE_OTHER:
  715.         return("Other"); }
  716. if(user_race)
  717.     return("*");
  718. return(nulstr);
  719. }
  720.  
  721. ushort getzodiac(char *birth)
  722. {
  723. if((!strncmp(birth,"03",2) && atoi(birth+3)>=21)
  724.     || (!strncmp(birth,"04",2) && atoi(birth+3)<=19))
  725.     return(ZODIAC_ARIES);
  726. if((!strncmp(birth,"04",2) && atoi(birth+3)>=20)
  727.     || (!strncmp(birth,"05",2) && atoi(birth+3)<=20))
  728.     return(ZODIAC_TAURUS);
  729. if((!strncmp(birth,"05",2) && atoi(birth+3)>=21)
  730.     || (!strncmp(birth,"06",2) && atoi(birth+3)<=20))
  731.     return(ZODIAC_GEMINI);
  732. if((!strncmp(birth,"06",2) && atoi(birth+3)>=21)
  733.     || (!strncmp(birth,"07",2) && atoi(birth+3)<=22))
  734.     return(ZODIAC_CANCER);
  735. if((!strncmp(birth,"07",2) && atoi(birth+3)>=23)
  736.     || (!strncmp(birth,"08",2) && atoi(birth+3)<=22))
  737.     return(ZODIAC_LEO);
  738. if((!strncmp(birth,"08",2) && atoi(birth+3)>=23)
  739.     || (!strncmp(birth,"09",2) && atoi(birth+3)<=22))
  740.     return(ZODIAC_VIRGO);
  741. if((!strncmp(birth,"09",2) && atoi(birth+3)>=23)
  742.     || (!strncmp(birth,"10",2) && atoi(birth+3)<=22))
  743.     return(ZODIAC_LIBRA);
  744. if((!strncmp(birth,"10",2) && atoi(birth+3)>=23)
  745.     || (!strncmp(birth,"11",2) && atoi(birth+3)<=21))
  746.     return(ZODIAC_SCORPIO);
  747. if((!strncmp(birth,"11",2) && atoi(birth+3)>=22)
  748.     || (!strncmp(birth,"12",2) && atoi(birth+3)<=21))
  749.     return(ZODIAC_SAGITTARIUS);
  750. if((!strncmp(birth,"12",2) && atoi(birth+3)>=22)
  751.     || (!strncmp(birth,"01",2) && atoi(birth+3)<=19))
  752.     return(ZODIAC_CAPRICORN);
  753. if((!strncmp(birth,"01",2) && atoi(birth+3)>=20)
  754.     || (!strncmp(birth,"02",2) && atoi(birth+3)<=18))
  755.     return(ZODIAC_AQUARIUS);
  756. if((!strncmp(birth,"02",2) && atoi(birth+3)>=19)
  757.     || (!strncmp(birth,"03",2) && atoi(birth+3)<=20))
  758.     return(ZODIAC_PISCES);
  759. return(0xff);
  760. }
  761.  
  762. char *zodiac(short user_zodiac)
  763. {
  764. switch(user_zodiac)
  765. {
  766.     case ZODIAC_ARIES:
  767.         return("Aries");
  768.     case ZODIAC_TAURUS:
  769.         return("Taurus");
  770.     case ZODIAC_GEMINI:
  771.         return("Gemini");
  772.     case ZODIAC_CANCER:
  773.         return("Cancer");
  774.     case ZODIAC_LEO:
  775.         return("Leo");
  776.     case ZODIAC_VIRGO:
  777.         return("Virgo");
  778.     case ZODIAC_LIBRA:
  779.         return("Libra");
  780.     case ZODIAC_SCORPIO:
  781.         return("Scorpio");
  782.     case ZODIAC_SAGITTARIUS:
  783.         return("Sagittarius");
  784.     case ZODIAC_CAPRICORN:
  785.         return("Capricorn");
  786.     case ZODIAC_AQUARIUS:
  787.         return("Aquarius");
  788.     case ZODIAC_PISCES:
  789.         return("Pisces"); }
  790. return(nulstr);
  791. }
  792.  
  793. short ans2bits(char *str)
  794. {
  795.     int i,j;
  796.     ushort bits=0;
  797.  
  798. j=strlen(str);
  799. for(i=0;i<j;i++) {
  800.     if(str[i]=='*')
  801.         return(0xffff);
  802.     bits|=(1<<str[i]-'A'); }
  803. return(bits);
  804. }
  805.  
  806. uchar ans2uchar(char *str)
  807. {
  808.     int i,j;
  809.     uchar bits=0;
  810.  
  811. j=strlen(str);
  812. for(i=0;i<j;i++) {
  813.     if(str[i]=='*')
  814.         return(0xff);
  815.     bits|=(1<<str[i]-'A'); }
  816. return(bits);
  817. }
  818.  
  819.  
  820. void bits2ans(ushort bits, char *str)
  821. {
  822.     char    tmp[25];
  823.     int     i;
  824.  
  825. str[0]=0;
  826. if(bits==0xffff) {
  827.     strcpy(str,"*");
  828.     return; }
  829. for(i=0;i<16;i++)
  830.     if(bits&(1<<i)) {
  831.         tmp[0]='A'+i;
  832.         tmp[1]=0;
  833.         strcat(str,tmp); }
  834. }
  835.  
  836. void bits2str(ushort user, char *str)
  837. {
  838.     int     i;
  839.  
  840. str[0]=0;
  841. if(user==0xffff) {
  842.     strcpy(str,"*");
  843.     return; }
  844. for(i=0;i<16;i++)
  845.     if(user&(1<<i))
  846.         str[i]='A'+i;
  847.     else
  848.         str[i]=SP;
  849. str[i]=0;
  850. }
  851.  
  852. void uchar2ans(uchar bits, char *str)
  853. {
  854.     char    tmp[25];
  855.     int     i;
  856.  
  857. str[0]=0;
  858. if(bits==0xff) {
  859.     strcpy(str,"*");
  860.     return; }
  861. for(i=0;i<8;i++)
  862.     if(bits&(1<<i)) {
  863.         tmp[0]='A'+i;
  864.         tmp[1]=0;
  865.         strcat(str,tmp); }
  866. }
  867.  
  868. int basic_match(user_t user, user_t mate)
  869. {
  870.     int max=0,match=0,age=getage(mate.birth),zodiac=getzodiac(mate.birth);
  871.  
  872. if(user.pref_sex!='*' && user.pref_sex!=mate.sex
  873.     && !(user.misc&USER_FRIEND))
  874.     return(0);
  875.  
  876. if(zodiac&user.pref_zodiac) match++;
  877. else if(user.misc&USER_REQZODIAC)
  878.     return(0);
  879. if(zodiac==user.pref_zodiac) match++;
  880. max+=2;
  881.  
  882. if(stricmp(mate.zipcode,user.min_zipcode)>=0
  883.     && stricmp(mate.zipcode,user.max_zipcode)<=0) match+=2;
  884. else if(user.misc&USER_REQZIP) return(0);
  885. max+=2;
  886.  
  887. if(mate.marital&user.pref_marital) match++;
  888. else if(user.misc&USER_REQMARITAL)
  889.     return(0);
  890. if(mate.marital==user.pref_marital) match++;
  891. max+=2;
  892.  
  893. if(mate.race&user.pref_race) match++;
  894. else if(user.misc&USER_REQRACE)
  895.     return(0);
  896. if(mate.race==user.pref_race) match++;
  897. max+=2;
  898.  
  899. if(mate.hair&user.pref_hair) match++;
  900. else if(user.misc&USER_REQHAIR)
  901.     return(0);
  902. if(mate.hair==user.pref_hair) match++;
  903. max+=2;
  904.  
  905. if(mate.eyes&user.pref_eyes) match++;
  906. else if(user.misc&USER_REQEYES)
  907.     return(0);
  908. if(mate.eyes==user.pref_eyes) match++;
  909. max+=2;
  910.  
  911. if(age>=user.min_age
  912.     && (!user.max_age || age<=user.max_age)) match+=2;
  913. else {
  914.     if(user.misc&USER_REQAGE) return(0);
  915.     if(age<user.min_age-((user.max_age-user.min_age)/2)
  916.         || (user.max_age && age>user.max_age+((user.max_age-user.min_age)/2)))
  917.         match-=4;
  918.     else if(age<user.min_age-((user.max_age-user.min_age)/3)
  919.         || (user.max_age && age>user.max_age+((user.max_age-user.min_age)/3)))
  920.         match-=3;
  921.     else if(age<user.min_age-((user.max_age-user.min_age)/4)
  922.         || (user.max_age && age>user.max_age+((user.max_age-user.min_age)/4)))
  923.         match-=2;
  924.     else if(age<user.min_age-((user.max_age-user.min_age)/5)
  925.         || (user.max_age && age>user.max_age+((user.max_age-user.min_age)/5)))
  926.         match--; }
  927.  
  928. max+=2;
  929.  
  930. if(mate.weight>=user.min_weight
  931.     && (!user.max_weight || mate.weight<=user.max_weight)) match+=2;
  932. else {
  933.     if(user.misc&USER_REQWEIGHT) return(0);
  934.     if(mate.weight<user.min_weight-((user.max_weight-user.min_weight)/2)
  935.         || (user.max_weight
  936.         && mate.weight>user.max_weight+((user.max_weight-user.min_weight)/2)))
  937.         match-=4;
  938.     else if(mate.weight<user.min_weight-((user.max_weight-user.min_weight)/3)
  939.         || (user.max_weight
  940.         && mate.weight>user.max_weight+((user.max_weight-user.min_weight)/3)))
  941.         match-=3;
  942.     else if(mate.weight<user.min_weight-((user.max_weight-user.min_weight)/4)
  943.         || (user.max_weight
  944.         && mate.weight>user.max_weight+((user.max_weight-user.min_weight)/4)))
  945.         match-=2;
  946.     else if(mate.weight<user.min_weight-((user.max_weight-user.min_weight)/5)
  947.         || (user.max_weight
  948.         && mate.weight>user.max_weight+((user.max_weight-user.min_weight)/5)))
  949.         match--; }
  950. max+=2;
  951.  
  952. if(mate.height>=user.min_height
  953.     && (!user.max_height || mate.height<=user.max_height)) match+=2;
  954. else {
  955.     if(user.misc&USER_REQHEIGHT) return(0);
  956.     if(mate.height<user.min_height-((user.max_height-user.min_height)/2)
  957.         || (user.max_height
  958.         && mate.height>user.max_height+((user.max_height-user.min_height)/2)))
  959.         match-=4;
  960.     else if(mate.height<user.min_height-((user.max_height-user.min_height)/3)
  961.         || (user.max_height
  962.         && mate.height>user.max_height+((user.max_height-user.min_height)/3)))
  963.         match-=3;
  964.     else if(mate.height<user.min_height-((user.max_height-user.min_height)/4)
  965.         || (user.max_height
  966.         && mate.height>user.max_height+((user.max_height-user.min_height)/4)))
  967.         match-=2;
  968.     else if(mate.height<user.min_height-((user.max_height-user.min_height)/5)
  969.         || (user.max_height
  970.         && mate.height>user.max_height+((user.max_height-user.min_height)/5)))
  971.         match--; }
  972. max+=2;
  973.  
  974. if(mate.income>=user.min_income
  975.     && (!user.max_income || mate.income==0xffffffffUL
  976.     || mate.income<=user.max_income)) match++;
  977. else {
  978.     if(user.misc&USER_REQINCOME) return(0);
  979.     if(mate.income<user.min_income-((user.max_income-user.min_income)/2)
  980.         || (user.max_income
  981.         && mate.income>user.max_income+((user.max_income-user.min_income)/2)))
  982.         match-=4;
  983.     else if(mate.income<user.min_income-((user.max_income-user.min_income)/3)
  984.         || (user.max_income
  985.         && mate.income>user.max_income+((user.max_income-user.min_income)/3)))
  986.         match-=3;
  987.     else if(mate.income<user.min_income-((user.max_income-user.min_income)/4)
  988.         || (user.max_income
  989.         && mate.income>user.max_income+((user.max_income-user.min_income)/4)))
  990.         match-=2;
  991.     else if(mate.income<user.min_income-((user.max_income-user.min_income)/5)
  992.         || (user.max_income
  993.         && mate.income>user.max_income+((user.max_income-user.min_income)/5)))
  994.         match--; }
  995. max++;
  996.  
  997. if(match<=0)
  998.     return(0);
  999.  
  1000. return(((float)match/max)*100.0);
  1001. }
  1002.  
  1003. int sys_quenum(char *name)
  1004. {
  1005.     int i;
  1006.  
  1007. for(i=0;i<total_ques;i++)
  1008.     if(!stricmp(que[i]->name,name))
  1009.         break;
  1010. if(i<total_ques)
  1011.     return(i);
  1012. return(-1);
  1013. }
  1014.  
  1015. int user_quenum(char *name, user_t user)
  1016. {
  1017.     int i;
  1018.  
  1019. for(i=0;i<5;i++)
  1020.     if(!stricmp(user.queans[i].name,name))
  1021.         break;
  1022. if(i<5)
  1023.     return(i);
  1024. return(-1);
  1025. }
  1026.  
  1027. int total_match(user_t user, user_t mate)
  1028. {
  1029.     int i,j,s,u,match1,match2,quematches=0,quemax=0,quematch;
  1030.  
  1031. match1=basic_match(user,mate);
  1032. if(!match1) return(0);
  1033. match2=basic_match(mate,user);
  1034. if(!match2) return(0);
  1035.  
  1036. for(i=0;i<5;i++) {
  1037.     if(!user.queans[i].name[0])
  1038.         continue;
  1039.     s=sys_quenum(user.queans[i].name);
  1040.     if(s==-1)
  1041.         continue;
  1042.     u=user_quenum(user.queans[i].name,mate);
  1043.     if(u==-1)
  1044.         continue;
  1045.     for(j=0;j<que[s]->total_ques;j++) {
  1046.         if(user.queans[u].pref[j]&mate.queans[i].self[j]) quematches+=4;
  1047.         if(user.queans[u].pref[j]==mate.queans[i].self[j]) quematches+=2;
  1048.         if(user.queans[u].self[j]&mate.queans[i].pref[j]) quematches+=2;
  1049.         if(user.queans[u].self[j]==mate.queans[i].pref[j]) quematches++;
  1050.         quemax+=9; } }
  1051.  
  1052. if(!quemax)     /* no questionnaires in common */
  1053.     return((match1+match1+match1+match1+match2+match2)/6);
  1054.  
  1055. quematch=((float)quematches/quemax)*100.0;
  1056. return((match1+match1+match1+match1+match2+match2+quematch)/7);
  1057. }
  1058.  
  1059.  
  1060. void main_user_info(user_t user)
  1061. {
  1062.     char str[128],min[64],max[64];
  1063.     int i;
  1064.  
  1065. attr(LIGHTGRAY);
  1066. cls();
  1067. if(SYSOP)
  1068.     bprintf("\1n\1gReal: \1h%.25s #%lu (%.40s)\r\n"
  1069.         ,user.realname,user.number,user.system);
  1070. bprintf("\1n\1gName: \1h%-25.25s     \1b%-10s   \1c%-15s  \1m%s\r\n"
  1071.     ,user.name
  1072.     ,marital(user.marital),race(user.race)
  1073.     ,user.sex=='M' ? "Male":"Female");
  1074. if(smm_misc&SMM_METRIC)
  1075.     sprintf(str," %-4u",intocm(user.height));
  1076. else
  1077.     sprintf(str,"%2u'%-2u",user.height/12,user.height%12);
  1078. bprintf("\1n\1gHair: \1h%3s  \1n\1gEyes: \1h%3s  \1n\1gHeight:"
  1079.     "\1h%s  \1n\1gWeight: \1h%-3u  \1n\1gAge: \1h%-3u "
  1080.     "\1n\1gZodiac: \1h%s\r\n"
  1081.     ,hair(user.hair),eyes(user.eyes),str
  1082.     ,smm_misc&SMM_METRIC ? lptokg(user.weight) : user.weight
  1083.     ,getage(user.birth),zodiac(getzodiac(user.birth)));
  1084. bprintf("\1n\1gFrom: \1h%-30.30s   \1n\1gZip: \1h%-10.10s    "
  1085.     "\1n\1gIncome: \1h$%sK\1n\1g/year\r\n"
  1086.     ,user.location,user.zipcode
  1087.     ,user.income==0xffffffffUL ? "?":ultoa(user.income/1000UL,tmp,10));
  1088. if(smm_misc&SMM_METRIC) {
  1089.     sprintf(min,"%u",intocm(user.min_height));
  1090.     sprintf(max,"%u",intocm(user.max_height)); }
  1091. else {
  1092.     sprintf(min,"%u'%u",user.min_height/12,user.min_height%12);
  1093.     sprintf(max,"%u'%u",user.max_height/12,user.max_height%12); }
  1094. bprintf("\1n\1gPref: \1h\1%c%c\1%c%c\1m%c \1%c%3u\1n\1g-\1h\1%c%u\1n\1h  "
  1095.     "\1%c%s \1n\1ghair  \1h\1%c%s \1n\1geyes  \1h\1%c%s\1n\1g-\1h\1%c%s  "
  1096.     "\1%c%u\1n\1g-\1h\1%c%u\1n\1glbs  \1h\1%c$%luK\1n\1g-\1h\1%c%luK\1n\1%c  "
  1097.     "\1h%.3s\r\n"
  1098.     ,user.misc&USER_REQMARITAL ? 'w':'b'
  1099.     ,marital_ch(user.pref_marital)
  1100.     ,user.misc&USER_REQRACE ? 'w':'g'
  1101.     ,race_ch(user.pref_race)
  1102.     ,user.pref_sex
  1103.     ,user.misc&USER_REQAGE    ? 'w':'g'
  1104.     ,user.min_age
  1105.     ,user.misc&USER_REQAGE    ? 'w':'g'
  1106.     ,user.max_age
  1107.     ,user.misc&USER_REQHAIR  ? 'w':'g'
  1108.     ,hair(user.pref_hair)
  1109.     ,user.misc&USER_REQEYES  ? 'w':'g'
  1110.     ,eyes(user.pref_eyes)
  1111.     ,user.misc&USER_REQHEIGHT  ? 'w':'g'
  1112.     ,min
  1113.     ,user.misc&USER_REQHEIGHT  ? 'w':'g'
  1114.     ,max
  1115.     ,user.misc&USER_REQWEIGHT  ? 'w':'g'
  1116.     ,smm_misc&SMM_METRIC ? lptokg(user.min_weight) : user.min_weight
  1117.     ,user.misc&USER_REQWEIGHT  ? 'w':'g'
  1118.     ,smm_misc&SMM_METRIC ? lptokg(user.max_weight) : user.max_weight
  1119.     ,user.misc&USER_REQINCOME  ? 'w':'g'
  1120.     ,user.min_income/1000L
  1121.     ,user.misc&USER_REQINCOME  ? 'w':'g'
  1122.     ,user.max_income/1000L
  1123.     ,user.misc&USER_REQZODIAC  ? 'w':'g'
  1124.     ,zodiac(user.pref_zodiac));
  1125.  
  1126. bprintf("\1r\1i%s\1n\1w\1h\r\n",user.misc&USER_PHOTO ? "PHOTO":nulstr);
  1127. for(i=0;i<5;i++) {
  1128.     if(!user.note[i][0])
  1129.         break;
  1130.     bprintf("%15s%.50s\r\n",nulstr,user.note[i]); }
  1131. }
  1132.  
  1133. char long_user_info(user_t user)
  1134. {
  1135.     char str[128],fname[128],path[128],ch;
  1136.     int i,j,k,s,u,max,match1,match2,user_match,mate_match;
  1137.  
  1138. while(1) {
  1139. checkline();
  1140. main_user_info(user);
  1141.  
  1142. CRLF;
  1143. /**
  1144. if(user.misc&USER_FROMSMB)
  1145.     bprintf("\1r\1hImported via message base from \1w%s\1r.\r\n"
  1146.         ,user.system);
  1147. **/
  1148. bprintf("\1h\1mThis user meets your profile preferences:\1w%3u%%            "
  1149.     ,match1=basic_match(useron,user));
  1150. bprintf("\1n\1gCreated: \1h%s\r\n",unixtodstr(user.created,str));
  1151. bprintf("\1h\1mYou meet this user's profile preferences:\1w%3u%%            "
  1152.     ,match2=basic_match(user,useron));
  1153. bprintf("\1n\1gUpdated: \1h%s\r\n",unixtodstr(user.updated,str));
  1154.  
  1155. if(!smm_pause)
  1156.     lncntr=0;
  1157.  
  1158. CRLF;
  1159. bputs("\1n\1b\1hQuestionnaires:\r\n");
  1160. for(i=0;i<5;i++) {
  1161.     max=mate_match=user_match=0;
  1162.     if(!user.queans[i].name[0])
  1163.         continue;
  1164.     s=sys_quenum(user.queans[i].name);
  1165.     if(s==-1)
  1166.         continue;
  1167.     if(que[s]->req_age>getage(useron.birth))
  1168.         continue;
  1169.     if(match1 && match2)
  1170.         u=user_quenum(user.queans[i].name,useron);
  1171.     else
  1172.         u=-1;
  1173.     bprintf("\1h\1c%-25s ",que[s]->desc);
  1174.     if(u==-1) {
  1175.         CRLF;
  1176.         continue; }
  1177.     for(j=0;j<que[s]->total_ques;j++) {
  1178.         if(useron.queans[u].pref[j]&user.queans[i].self[j]) user_match+=2;
  1179.         if(useron.queans[u].pref[j]==user.queans[i].self[j]) user_match++;
  1180.         if(useron.queans[u].self[j]&user.queans[i].pref[j]) mate_match+=2;
  1181.         if(useron.queans[u].self[j]==user.queans[i].pref[j]) mate_match++;
  1182.         max+=3; }
  1183.     bprintf("\1n\1c%s matches your pref:\1h%3u%%  "
  1184.             "\1n\1cYou match %s pref:\1h%3u%%\r\n"
  1185.             ,user.sex=='M' ? "He":"She"
  1186.             ,(int)(((float)user_match/max)*100.0)
  1187.             ,user.sex=='M' ? "his":"her"
  1188.             ,(int)(((float)mate_match/max)*100.0)); }
  1189.  
  1190. bprintf("\r\n\1r\1hOverall match: \1w%u%%",total_match(useron,user));
  1191. if(user.purity)
  1192.     bprintf("        \1r\1hPurity test: \1w%u%%",user.purity);
  1193. if(user.mbtype[0])
  1194.     bprintf("        \1r\1hPersonality type: \1w%s",user.mbtype);
  1195. CRLF;
  1196.  
  1197. if(aborted) {
  1198.     aborted=0;
  1199.     return(0); }
  1200. if(!smm_pause) {
  1201.     if(kbhit())
  1202.         return(0);
  1203.     return(1); }
  1204. nodesync();
  1205. if(lncntr>=user_rows-2)
  1206.     lncntr=0;
  1207. CRLF;
  1208. bputs("\1h\1b[\1cV\1b]iew questionnaires, ");
  1209. if(user.misc&USER_PHOTO)
  1210.     bputs("[\1cD\1b]ownload photo, ");
  1211. bputs("[\1cS\1b]end telegram, [\1cQ\1b]uit, or [Next]: \1c");
  1212. strcpy(str,"VSQN\r");
  1213. if(user.misc&USER_PHOTO)
  1214.     strcat(str,"D");
  1215. if(SYSOP)
  1216.     strcat(str,"+");
  1217. switch(getkeys(str,0)) {
  1218.     case '+':
  1219.         user.misc|=USER_PHOTO;
  1220.         break;
  1221.     case 'Q':
  1222.         return(0);
  1223.     case CR:
  1224.     case 'N':
  1225.         return(1);
  1226.     case 'D':
  1227.         if(!useron.number) {
  1228.             bputs("\r\n\1h\1rYou must create a profile first.\r\n");
  1229.             pause();
  1230.             break; }
  1231.         if(!(useron.misc&USER_PHOTO)) {
  1232.             bputs("\r\n\1h\1rYou cannot download photos until your photo is "
  1233.                 "added.\r\n");
  1234.             pause();
  1235.             break; }
  1236.         for(i=0;user.system[i];i++)
  1237.             if(isalnum(user.system[i]))
  1238.                 break;
  1239.         if(!user.system[i])
  1240.             fname[0]='~';
  1241.         else
  1242.             fname[0]=user.system[i];
  1243.         for(i=strlen(user.system)-1;i>0;i--)
  1244.             if(isalnum(user.system[i]))
  1245.                 break;
  1246.         if(i<=0)
  1247.             fname[1]='~';
  1248.         else
  1249.             fname[1]=user.system[i];
  1250.         fname[2]=0;
  1251.         strupr(user.system);
  1252.         strcat(fname,base41(crc16(user.system),tmp));
  1253.         strcat(fname,base41(user.number,tmp));
  1254.         strcat(fname,".JPG");
  1255.         strupr(fname);
  1256.         sprintf(path,"PHOTO\\%s",fname);
  1257.         if(!fexist(path)) {
  1258.             bputs("\r\n\1n\1hUnpacking...");
  1259.             sprintf(str,"%spkunzip photo %s photo",exec_dir,fname);
  1260.             system(str);
  1261.             bputs("\r\n");
  1262.             if(!fexist(path)) {
  1263.                 bputs("\r\n\1n\1h\1i\1rUnpacking failed!\1n\r\n");
  1264.                 pause();
  1265.                 break; } }
  1266.         if(com_port) {
  1267.             cmdstr(zmodem_send,path,path,str);
  1268.             ivhctl(INTCLR);
  1269.             ivhctl(INT29L);
  1270.             system(str);
  1271.             ivhctl(INTCLR);
  1272.             i=INT29L;
  1273.             i|=(INT29R|INT16);
  1274.             ivhctl(i); }
  1275.         else
  1276.             system(cmdstr(local_view,path,path,str));
  1277.         pause();
  1278.         break;
  1279.  
  1280.  
  1281.     case 'S':
  1282.         send_telegram(user);
  1283.         break;
  1284.     case 'V':
  1285.  
  1286.         if(user_level<que_level) {
  1287.             bputs("\r\n\1h\1rYou have insufficient access to read "
  1288.                 "questoinnaires.\r\n");
  1289.             pause();
  1290.             break; }
  1291.  
  1292.         for(i=0;i<5;i++) {
  1293.             aborted=0;
  1294.             if(!user.queans[i].name[0])
  1295.                 continue;
  1296.             s=sys_quenum(user.queans[i].name);
  1297.             if(s==-1)
  1298.                 continue;
  1299.             if(que[s]->req_age>getage(useron.birth))
  1300.                 continue;
  1301.             if(match1 && match2)
  1302.                 u=user_quenum(user.queans[i].name,useron);
  1303.             else
  1304.                 u=-1;
  1305.             sprintf(str,"\r\nDo you wish to view the \1w%s\1b questionnaire"
  1306.                 ,que[s]->desc);
  1307.             if(!yesno(str))
  1308.                 continue;
  1309.             if(!cdt_warning(que_cdt))
  1310.                 continue;
  1311.             adjust_cdt(que_cdt);
  1312.             for(j=0;j<que[s]->total_ques && !aborted;) {
  1313.                 cls();
  1314.                 bprintf("\1n\1m\1hQuestionnaire: \1y%-25s \1mQuestion: "
  1315.                     "\1y%d \1mof \1y%d  \1h\1b(Ctrl-C to Abort)\r\n\r\n"
  1316.                     ,que[s]->desc,j+1,que[s]->total_ques);
  1317.                 bprintf("\1w\1h%s\r\n\r\n",que[s]->que[j].txt);
  1318.                 for(k=0;k<que[s]->que[j].answers;k++)
  1319.                     bprintf("\1h\1b%c\1w) \1g%s\r\n",'A'+k
  1320.                         ,que[s]->que[j].ans[k]);
  1321.                 bits2str(user.queans[i].self[j],str);
  1322.                 bprintf("\1n\1g\r\n%25s: \1h%-16s "
  1323.                     ,user.name,str);
  1324.                 bits2str(user.queans[i].pref[j],str);
  1325.                 bprintf("\1n\1g %15s: \1h%s","Preferred mate",str);
  1326.                 if(u!=-1) {
  1327.                     bits2str(useron.queans[u].pref[j],str);
  1328.                     bprintf("\1n\1g\r\n%25s: \1h%-16s "
  1329.                         ,"Your preferred mate",str);
  1330.                     bits2str(useron.queans[u].self[j],str);
  1331.                     bprintf("\1n\1g %15s: \1h%s","You",str); }
  1332.                 CRLF;
  1333.                 if(!aborted) {
  1334.                     lncntr=0;
  1335.                     bputs("\r\n\1h\1b[\1cP\1b]revious, [\1cQ\1b]uit, "
  1336.                         "or [Next]: \1c");
  1337.                     ch=getkeys("PQN\r",0);
  1338.                     if(ch=='P') {
  1339.                         if(j) j--;
  1340.                         continue; }
  1341.                     if(ch=='Q')
  1342.                         break;
  1343.                     j++; } } }
  1344.         break;
  1345.  
  1346.     } }
  1347. return(0);
  1348. }
  1349.  
  1350.  
  1351. /* Returns 0 if aborted, 1 if continue, negative if previous */
  1352. int short_user_info(user_t user)
  1353. {
  1354.     char str[128],height[64],ch;
  1355.     int i,match;
  1356.     int records;
  1357.     ulong  name_crc;
  1358.     static char name[26],lastname[26],highmatch;
  1359.     static long topixb,topdab,lastixb,lastdab;
  1360.     static int count;
  1361.  
  1362. if(!lncntr && smm_pause) {
  1363.     topdab=ftell(stream)-sizeof(user_t);
  1364.     topixb=ftell(index)-sizeof(ixb_t);
  1365.     if(!topdab)
  1366.         lastdab=lastixb=0;
  1367.     count=0;
  1368.     printfile("LIST_HDR.ASC");
  1369.     strcpy(lastname,name);
  1370.     name[0]=highmatch=0; }
  1371. if(user.number) {
  1372.     match=total_match(useron,user);
  1373.     if(!match) str[0]=0;
  1374.     else if(match>=90) sprintf(str,"\1w%u%%",match);
  1375.     else if(match>=80) sprintf(str,"\1c%u%%",match);
  1376.     else if(match>=70) sprintf(str,"\1y%u%%",match);
  1377.     else if(match>=60) sprintf(str,"\1g%u%%",match);
  1378.     else if(match>=50) sprintf(str,"\1m%u%%",match);
  1379.     else if(match>=40) sprintf(str,"\1r%u%%",match);
  1380.     else if(match>=30) sprintf(str,"\1b%u%%",match);
  1381.     else if(match>=20) sprintf(str,"\1n\1g%u%%",match);
  1382.     else if(match>=10) sprintf(str,"\1n\1c%u%%",match);
  1383.     else sprintf(str,"\1n%u%%",match);
  1384.     if(smm_misc&SMM_METRIC)
  1385.         sprintf(height," %-4u",intocm(user.height));
  1386.     else
  1387.         sprintf(height,"%2u'%-2u",user.height/12,user.height%12);
  1388.     bprintf("\1n\1h%c\1n\1g%c\1h\1c%c\1b%3u \1g%3s \1m%3s\1r%s \1y%-3u "
  1389.         "\1n\1g%-25.25s\1r\1h\1i%c\1n\1h%-25.25s%s\r\n"
  1390.         ,user.sex==user.pref_sex ? 'G':user.sex=='*' ? 'B'
  1391.             : marital_ch(user.marital)
  1392.         ,race_ch(user.race)
  1393.         ,user.sex
  1394.         ,getage(user.birth)
  1395.         ,hair(user.hair)
  1396.         ,eyes(user.eyes)
  1397.         ,height
  1398.         ,smm_misc&SMM_METRIC ? lptokg(user.weight) : user.weight
  1399.         ,user.location
  1400.         ,user.misc&USER_PHOTO ? '+':SP
  1401.         ,user.name
  1402.         ,str
  1403.         );
  1404.     if(match &&
  1405.         (!name[0] || !stricmp(name,lastname)
  1406.         || (stricmp(user.name,lastname) && match>highmatch))) {
  1407.         highmatch=match;
  1408.         sprintf(name,"%.25s",user.name);
  1409.         strupr(name); }
  1410.     }
  1411.  
  1412. if(lncntr>=user_rows-2 || !user.number) {
  1413.     lncntr=0;
  1414.     bputs(PrevReadSendQuitOrMore);
  1415.     ch=getkey(K_UPPER);
  1416.     if(ch=='Q') {
  1417.         cls();
  1418.         aborted=1; }
  1419.     else if(ch=='P') {
  1420.         cls();
  1421.         records=((ftell(stream)-topdab)/sizeof(user_t));
  1422.         fseek(stream,lastdab,SEEK_SET);
  1423.         fseek(index,lastixb,SEEK_SET);
  1424.         lastdab-=(records)*sizeof(user_t);
  1425.         lastixb-=(records)*sizeof(ixb_t);
  1426.         if(lastdab<0) lastdab=0;
  1427.         if(lastixb<0) lastixb=0;
  1428.         return(-count); }
  1429.     else if(ch=='R' || ch=='G' || ch=='S') {
  1430.         bprintf("\1n\r\1>\1y\1hUser name: ");
  1431.         if(getstr(name,25,K_NOCRLF|K_LINE|K_EDIT|K_AUTODEL|K_UPPER)) {
  1432.             truncsp(name);
  1433.             name_crc=crc32(name);
  1434.             cls();
  1435.             rewind(index);
  1436.             while(!feof(index)) {
  1437.                 if(!fread(&ixb,sizeof(ixb_t),1,index))
  1438.                     break;
  1439.                 if(!ixb.number)    /* DELETED */
  1440.                     continue;
  1441.                 if(ixb.name!=name_crc)
  1442.                     continue;
  1443.                 fseek(stream
  1444.                     ,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
  1445.                     *sizeof(user_t),SEEK_SET);
  1446.                 if(!fread(&user,sizeof(user_t),1,stream))
  1447.                     continue;
  1448.                 if(ch=='S' && send_telegram(user))
  1449.                     break;
  1450.                 if(ch!='S' && !long_user_info(user))
  1451.                     break; } }
  1452.         fseek(stream,topdab,SEEK_SET);
  1453.         fseek(index,topixb,SEEK_SET);
  1454.         cls();
  1455.         return(-1); }
  1456.     else {
  1457.         lastixb=topixb;
  1458.         lastdab=topdab;
  1459.         cls(); } }
  1460.  
  1461. count++;
  1462. if(aborted)
  1463.     return(0);
  1464. return(1);
  1465. }
  1466.  
  1467.  
  1468. int get_your_det(user_t *user)
  1469. {
  1470.     char    str[128],*p,*hdr;
  1471.     int     i;
  1472.  
  1473. while(1) {
  1474. checkline();
  1475. cls();
  1476. bputs("\1h\0014 Your Detailed Personal Information \1n  \1h\1b"
  1477.     "(Ctrl-C to Abort)\r\n\r\n");
  1478.  
  1479. nodesync();
  1480. bputs("\1h\1bPlease enter your name or alias: ");
  1481. strcpy(str,user->name);
  1482. if(!getstr(str,25,K_LINE|K_EDIT|K_AUTODEL|K_UPRLWR))
  1483.     return(0);
  1484. truncsp(str);
  1485. if(trash(str)) {
  1486.     bprintf("\r\n\1h\1rSorry, you can't use that name.\r\n\r\n\1p");
  1487.     continue; }
  1488. strcpy(user->name,str);
  1489.  
  1490. CRLF;
  1491. nodesync();
  1492. bprintf("\1h\1gPlease enter your height in %s: "
  1493.     ,smm_misc&SMM_METRIC ? "centimeters" : "feet'inches (example: 5'7)");
  1494. if(user->height) {
  1495.     if(smm_misc&SMM_METRIC)
  1496.         sprintf(str,"%u",intocm(user->height));
  1497.     else
  1498.         sprintf(str,"%u'%u",user->height/12,user->height%12); }
  1499. else
  1500.     str[0]=0;
  1501. if(!getstr(str,4,K_LINE|K_EDIT|K_AUTODEL))
  1502.     return(0);
  1503. if(smm_misc&SMM_METRIC)
  1504.     user->height=cmtoin(atoi(str));
  1505. else {
  1506.     user->height=atoi(str)*12;
  1507.     p=strchr(str,'\'');
  1508.     if(p) user->height+=atoi(p+1); }
  1509.  
  1510. CRLF;
  1511. nodesync();
  1512. bprintf("\1h\1mPlease enter your weight (in %s): "
  1513.     ,smm_misc&SMM_METRIC ? "kilograms":"pounds");
  1514. if(user->weight)
  1515.     sprintf(str,"%u"
  1516.         ,smm_misc&SMM_METRIC ? lptokg(user->weight) : user->weight);
  1517. else
  1518.     str[0]=0;
  1519. if(!getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL|K_LINE))
  1520.     return(0);
  1521. if(smm_misc&SMM_METRIC)
  1522.     user->weight=kgtolp(atoi(str));
  1523. else
  1524.     user->weight=atoi(str);
  1525.  
  1526. CRLF;
  1527. nodesync();
  1528. bputs("\1h\1rPlease enter your annual income in dollars (ENTER=undisclosed): ");
  1529. if(user->income && user->income!=0xffffffff)
  1530.     sprintf(str,"%luK",user->income/1000);
  1531. else
  1532.     str[0]=0;
  1533. getstr(str,6,K_UPPER|K_EDIT|K_AUTODEL|K_LINE);
  1534. if(aborted)
  1535.     return(0);
  1536. if(strchr(str,'K'))
  1537.     user->income=atol(str)*1000L;
  1538. else if(str[0]==0)
  1539.     user->income=0xffffffffUL;
  1540. else
  1541.     user->income=atol(str);
  1542.  
  1543. CRLF;
  1544. nodesync();
  1545. bputs("\1h\1cPlease enter your location (city, state): ");
  1546. strcpy(str,user->location);
  1547. if(!getstr(str,30,K_LINE|K_EDIT|K_AUTODEL|K_UPRLWR))
  1548.     return(0);
  1549. truncsp(str);
  1550. if(trash(str)) {
  1551.     bprintf("\r\n\1r\1hSorry, you can't use that location.\r\n\r\n\1p");
  1552.     continue; }
  1553. strcpy(user->location,str);
  1554.  
  1555.  
  1556. CRLF;
  1557. nodesync();
  1558. bputs("\1h\1gPlease enter your zip/postal code: ");
  1559. if(!getstr(user->zipcode,10,K_LINE|K_EDIT|K_AUTODEL))
  1560.     return(0);
  1561.  
  1562. CRLF;
  1563. nodesync();
  1564. for(i=0;i<5;i++) {
  1565.     bprintf("\1n\1gPersonal text - Line %u of 5: ",i+1);
  1566.     if(wordwrap[0])
  1567.         user->note[i][0]=0;
  1568.     strcpy(str,user->note[i]);
  1569.     if(!getstr(str,50,i==4 ? K_LINE|K_EDIT:K_LINE|K_EDIT|K_WRAP))
  1570.         break;
  1571.     if(trash(str)) {
  1572.         bprintf("\r\n\1r\1hSorry, you can't use that text.\r\n\r\n");
  1573.         i--;
  1574.         continue; }
  1575.     strcpy(user->note[i],str); }
  1576. while(i++<5)
  1577.     user->note[i][0]=0;
  1578. aborted=0;
  1579. nodesync();
  1580. if(yesno("\r\nIs the above information correct"))
  1581.     break; }
  1582. return(1);
  1583. }
  1584.  
  1585. int get_pref_det(user_t *user)
  1586. {
  1587.     char str[128],*p,*hdr;
  1588.     int i;
  1589.  
  1590. while(1) {
  1591. checkline();
  1592. cls();
  1593. bputs("\1h\0014 Detailed Information on Your Preferred Mate \1n  "
  1594.     "\1h\1b(Ctrl-C to Abort)\r\n\r\n");
  1595.  
  1596. nodesync();
  1597. bputs("\1n\1cPlease enter the minimum age of your preferred mate: \1h");
  1598. if(user->min_age)
  1599.     sprintf(str,"%u",user->min_age);
  1600. else
  1601.     str[0]=0;
  1602. getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL);
  1603. if(aborted)
  1604.     return(0);
  1605. user->min_age=atoi(str);
  1606.  
  1607. nodesync();
  1608. bputs("\1h\1cPlease enter the maximum age of your preferred mate: \1h");
  1609. if(user->max_age)
  1610.     sprintf(str,"%u",user->max_age);
  1611. else
  1612.     str[0]=0;
  1613. getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL);
  1614. if(aborted)
  1615.     return(0);
  1616. user->max_age=atoi(str);
  1617. if(user->min_age) {
  1618.     strcpy(str,"Do you require your mate's age fall within this range");
  1619.     if(user->misc&USER_REQAGE)
  1620.         i=yesno(str);
  1621.     else
  1622.         i=!noyes(str);
  1623.     if(i)
  1624.         user->misc|=USER_REQAGE;
  1625.     else
  1626.         user->misc&=~USER_REQAGE; }
  1627. else
  1628.     user->misc&=~USER_REQAGE;
  1629. if(aborted)
  1630.     return(0);
  1631.  
  1632. CRLF;
  1633. nodesync();
  1634. bprintf("\1n\1gPlease enter the minimum height of your preferred mate "
  1635.     "in %s: \1w\1h",smm_misc&SMM_METRIC ? "centimeters":"feet'inches");
  1636. if(user->min_height) {
  1637.     if(smm_misc&SMM_METRIC)
  1638.         sprintf(str,"%u",intocm(user->min_height));
  1639.     else
  1640.         sprintf(str,"%u'%u",user->min_height/12,user->min_height%12); }
  1641. else
  1642.     str[0]=0;
  1643. getstr(str,4,K_EDIT|K_AUTODEL);
  1644. if(aborted)
  1645.     return(0);
  1646. if(smm_misc&SMM_METRIC)
  1647.     user->min_height=cmtoin(atoi(str));
  1648. else {
  1649.     user->min_height=atoi(str)*12;
  1650.     p=strchr(str,'\'');
  1651.     if(p) user->min_height+=atoi(p+1); }
  1652. nodesync();
  1653. bprintf("\1h\1gPlease enter the maximum height of your preferred mate "
  1654.     "in %s: \1w",smm_misc&SMM_METRIC ? "centimeters":"feet'inches");
  1655. if(user->max_height) {
  1656.     if(smm_misc&SMM_METRIC)
  1657.         sprintf(str,"%u",intocm(user->max_height));
  1658.     else
  1659.         sprintf(str,"%u'%u",user->max_height/12,user->max_height%12); }
  1660. else
  1661.     str[0]=0;
  1662. getstr(str,4,K_EDIT|K_AUTODEL);
  1663. if(aborted)
  1664.     return(0);
  1665. if(smm_misc&SMM_METRIC)
  1666.     user->max_height=cmtoin(atoi(str));
  1667. else {
  1668.     user->max_height=atoi(str)*12;
  1669.     p=strchr(str,'\'');
  1670.     if(p) user->max_height+=atoi(p+1); }
  1671. strcpy(str,"Do you require your mate's height fall within this range");
  1672. if(user->misc&USER_REQHEIGHT)
  1673.     i=yesno(str);
  1674. else
  1675.     i=!noyes(str);
  1676. if(i)
  1677.     user->misc|=USER_REQHEIGHT;
  1678. else
  1679.     user->misc&=~USER_REQHEIGHT;
  1680. if(aborted)
  1681.     return(0);
  1682.  
  1683.  
  1684. CRLF;
  1685. nodesync();
  1686. bprintf("\1n\1mPlease enter the minimum weight of your preferred mate in %s:"
  1687.     " \1w\1h",smm_misc&SMM_METRIC ? "kilograms":"pounds");
  1688. if(user->min_weight) {
  1689.     if(smm_misc&SMM_METRIC)
  1690.         sprintf(str,"%u",lptokg(user->min_weight));
  1691.     else
  1692.         sprintf(str,"%u",user->min_weight); }
  1693. else
  1694.     str[0]=0;
  1695. getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL);
  1696. if(aborted)
  1697.     return(0);
  1698. if(smm_misc&SMM_METRIC)
  1699.     user->min_weight=kgtolp(atoi(str));
  1700. else
  1701.     user->min_weight=atoi(str);
  1702.  
  1703. nodesync();
  1704. bprintf("\1h\1mPlease enter the maximum weight of your preferred mate in %s:"
  1705.     " \1w",smm_misc&SMM_METRIC ? "kilograms":"pounds");
  1706. if(user->max_weight) {
  1707.     if(smm_misc&SMM_METRIC)
  1708.         sprintf(str,"%u",lptokg(user->max_weight));
  1709.     else
  1710.         sprintf(str,"%u",user->max_weight); }
  1711. else
  1712.     str[0]=0;
  1713. getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL);
  1714. if(aborted)
  1715.     return(0);
  1716. if(smm_misc&SMM_METRIC)
  1717.     user->max_weight=kgtolp(atoi(str));
  1718. else
  1719.     user->max_weight=atoi(str);
  1720. if(user->max_weight) {
  1721.     strcpy(str,"Do you require your mate's weight fall within this range");
  1722.     if(user->misc&USER_REQWEIGHT)
  1723.         i=yesno(str);
  1724.     else
  1725.         i=!noyes(str);
  1726.     if(i)
  1727.         user->misc|=USER_REQWEIGHT;
  1728.     else
  1729.         user->misc&=~USER_REQWEIGHT; }
  1730. else
  1731.     user->misc&=~USER_REQWEIGHT;
  1732. if(aborted)
  1733.     return(0);
  1734.  
  1735.  
  1736. CRLF;
  1737. nodesync();
  1738. bputs("\1h\1cPlease enter the lowest zip/postal code of your preferred "
  1739.     "mate: \1w");
  1740. getstr(user->min_zipcode,10,K_EDIT|K_AUTODEL|K_UPPER);
  1741. if(aborted)
  1742.     return(0);
  1743. bputs("\1h\1bPlease enter the highest zip/postal code of your preferred "
  1744.     "mate: \1w");
  1745. getstr(user->max_zipcode,10,K_EDIT|K_AUTODEL|K_UPPER);
  1746. if(aborted)
  1747.     return(0);
  1748. strcpy(str,"Do you require your mate's zip/postal code fall within this range");
  1749. if(user->misc&USER_REQZIP)
  1750.     i=yesno(str);
  1751. else
  1752.     i=!noyes(str);
  1753. if(i)
  1754.     user->misc|=USER_REQZIP;
  1755. else
  1756.     user->misc&=~USER_REQZIP;
  1757. if(aborted)
  1758.     return(0);
  1759.  
  1760.  
  1761. CRLF;
  1762. nodesync();
  1763. bputs("\1h\1gPlease enter the minimum annual income of your "
  1764.     "mate in dollars: \1w");
  1765. if(user->min_income)
  1766.     sprintf(str,"%lu",user->min_income);
  1767. else
  1768.     str[0]=0;
  1769. getstr(str,6,K_NUMBER|K_EDIT|K_AUTODEL);
  1770. if(aborted) return(0);
  1771. user->min_income=atol(str);
  1772.  
  1773. nodesync();
  1774. bputs("\1h\1yPlease enter the maximum annual income of your "
  1775.     "mate in dollars: \1w");
  1776. if(user->max_income)
  1777.     sprintf(str,"%lu",user->max_income);
  1778. else
  1779.     str[0]=0;
  1780. getstr(str,6,K_NUMBER|K_EDIT|K_AUTODEL);
  1781. if(aborted) return(0);
  1782. user->max_income=atol(str);
  1783. if(user->min_income) {
  1784.     strcpy(str,"Do you require that your mate's income fall within this range");
  1785.     if(user->misc&USER_REQINCOME)
  1786.         i=yesno(str);
  1787.     else
  1788.         i=!noyes(str);
  1789.     if(i)
  1790.         user->misc|=USER_REQINCOME;
  1791.     else
  1792.         user->misc&=~USER_REQINCOME; }
  1793. else
  1794.     user->misc&=~USER_REQINCOME;
  1795. if(aborted)
  1796.     return(0);
  1797.  
  1798.  
  1799. nodesync();
  1800. if(yesno("\r\nIs the above information correct"))
  1801.     break; }
  1802. return(1);
  1803. }
  1804.  
  1805. int get_your_multi(user_t *user)
  1806. {
  1807.     char str[128],*hdr,*p;
  1808.  
  1809. while(1) {
  1810. checkline();
  1811. hdr="\1n\1l\1h\0014 Your Profile \1n  \1h\1b(Ctrl-C to Abort)\r\n\r\n";
  1812. bputs(hdr);
  1813. bputs("\1n\1h\1cYour Marital Status:\r\n\r\n");
  1814. mnemonics("~A) Single\r\n~B) Married\r\n~C) Divorced\r\n~D) Widowed\r\n"
  1815.     "~E) Other\r\n");
  1816. nodesync();
  1817. bputs("\r\n\1y\1hWhich: \1w");
  1818. uchar2ans(user->marital,str);
  1819. if(!getstr(str,1,K_ALPHA|K_LINE|K_EDIT|K_AUTODEL|K_UPPER))
  1820.     return(0);
  1821. if(str[0]<='E')
  1822.     break; }
  1823. user->marital=ans2uchar(str);
  1824.  
  1825. while(1) {
  1826. checkline();
  1827. bputs(hdr);
  1828. bputs("\1n\1h\1cYour Race:\r\n\r\n");
  1829. mnemonics("~A) White\r\n~B) Black\r\n~C) Hispanic\r\n~D) Asian\r\n"
  1830.     "~E) American Indian\r\n~F) Middle Eastern\r\n~G) Other\r\n");
  1831. nodesync();
  1832. bputs("\r\n\1y\1hWhich: \1w");
  1833. uchar2ans(user->race,str);
  1834. if(!getstr(str,1,K_ALPHA|K_LINE|K_EDIT|K_AUTODEL|K_UPPER))
  1835.     return(0);
  1836. if(str[0]<='G')
  1837.     break; }
  1838. user->race=ans2uchar(str);
  1839.  
  1840. while(1) {
  1841. checkline();
  1842. bputs(hdr);
  1843. bputs("\1n\1h\1cYour Hair Color:\r\n\r\n");
  1844. mnemonics("~A) Blonde\r\n~B) Brown\r\n~C) Red\r\n~D) Black\r\n"
  1845.     "~E) Grey\r\n~F) Other\r\n");
  1846. nodesync();
  1847. bputs("\r\n\1y\1hWhich: \1w");
  1848. uchar2ans(user->hair,str);
  1849. if(!getstr(str,1,K_ALPHA|K_LINE|K_EDIT|K_AUTODEL|K_UPPER))
  1850.     return(0);
  1851. if(str[0]<='F')
  1852.     break; }
  1853. user->hair=ans2uchar(str);
  1854.  
  1855. while(1) {
  1856. checkline();
  1857. bputs(hdr);
  1858. bputs("\1n\1h\1cYour Eye Color:\r\n\r\n");
  1859. mnemonics("~A) Blue\r\n~B) Green\r\n~C) Hazel\r\n~D) Brown\r\n"
  1860.     "~E) Other\r\n");
  1861. nodesync();
  1862. bputs("\r\n\1y\1hWhich: \1w");
  1863. uchar2ans(user->eyes,str);
  1864. if(!getstr(str,1,K_ALPHA|K_LINE|K_EDIT|K_AUTODEL|K_UPPER))
  1865.     return(0);
  1866. if(str[0]<='E')
  1867.     break; }
  1868. user->eyes=ans2uchar(str);
  1869. return(1);
  1870. }
  1871.  
  1872. int get_pref_multi(user_t *user)
  1873. {
  1874.     char str[128],*hdr,*p;
  1875.     int i;
  1876.  
  1877. while(1) {
  1878. checkline();
  1879. hdr="\1n\1l\1h\0014 Profile of Your Preferred Mate \1n  \1h\1b"
  1880.     "(Ctrl-C to Abort)\r\n\r\n";
  1881. bputs(hdr);
  1882. bputs("\1n\1h\1cSex of Your Preferred (Intimate/Romantic) Mate:\r\n\r\n");
  1883. mnemonics("~M) Male\r\n~F) Female\r\n~*) Either\r\n");
  1884. nodesync();
  1885. bputs("\r\n\1y\1hWhich: ");
  1886. str[0]=user->pref_sex;
  1887. str[1]=0;
  1888. if(!getstr(str,1,K_UPPER|K_EDIT|K_AUTODEL|K_LINE))
  1889.     break;
  1890. if(user->sex==str[0] && noyes("\r\nYou are homosexual"))
  1891.     continue;
  1892. if(str[0]=='M' || str[0]=='F' || str[0]=='*')
  1893.     break; }
  1894. user->pref_sex=str[0];
  1895. if(aborted) return(0);
  1896.  
  1897. strcpy(str,"\r\nAre you seeking an any-sex (non-romantic) friendship");
  1898. if(user->misc&USER_FRIEND)
  1899.     i=yesno(str);
  1900. else
  1901.     i=!noyes(str);
  1902. if(i)
  1903.     user->misc|=USER_FRIEND;
  1904. else
  1905.     user->misc&=~USER_FRIEND;
  1906.  
  1907. bputs(hdr);
  1908. bputs("\1n\1h\1cMarital Status of Your Preferred Mate:\r\n\r\n");
  1909. mnemonics("~A) Single\r\n~B) Married\r\n~C) Divorced\r\n~D) Widowed\r\n"
  1910.     "~E) Other\r\n~*) Any of the above\r\n");
  1911. nodesync();
  1912. bputs("\r\n\1y\1hPlease enter up to 4 answers: ");
  1913. uchar2ans(user->pref_marital,str);
  1914. if(!getstr(str,4,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
  1915.     return(0);
  1916. user->pref_marital=ans2uchar(str);
  1917. if(user->pref_marital!=0xff) {
  1918.     strcpy(str,"\r\nDo you require your mate have the martial status you "
  1919.         "indicated");
  1920.     if(user->misc&USER_REQMARITAL)
  1921.         i=yesno(str);
  1922.     else
  1923.         i=!noyes(str);
  1924.     if(i)
  1925.         user->misc|=USER_REQMARITAL;
  1926.     else
  1927.         user->misc&=~USER_REQMARITAL; }
  1928. else
  1929.     user->misc&=~USER_REQMARITAL;
  1930. if(aborted) return(0);
  1931.  
  1932. bputs(hdr);
  1933. bputs("\1n\1h\1cRace of Your Preferred Mate:\r\n\r\n");
  1934. mnemonics("~A) White\r\n~B) Black\r\n~C) Hispanic\r\n~D) Asian\r\n"
  1935.     "~E) American Indian\r\n~F) Middle Eastern\r\n~G) Other\r\n"
  1936.     "~*) Any of the above\r\n");
  1937. nodesync();
  1938. bputs("\r\n\1y\1hPlease enter up to 6 answers: ");
  1939. uchar2ans(user->pref_race,str);
  1940. if(!getstr(str,6,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
  1941.     return(0);
  1942. user->pref_race=ans2uchar(str);
  1943. if(user->pref_race!=0xff) {
  1944.     strcpy(str,"\r\nDo you require your mate be of the race"
  1945.         " you indicated");
  1946.     if(user->misc&USER_REQRACE)
  1947.         i=yesno(str);
  1948.     else
  1949.         i=!noyes(str);
  1950.     if(i)
  1951.         user->misc|=USER_REQRACE;
  1952.     else
  1953.         user->misc&=~USER_REQRACE; }
  1954. else
  1955.     user->misc&=~USER_REQRACE;
  1956. if(aborted) return(0);
  1957.  
  1958. bputs(hdr);
  1959. bputs("\1n\1h\1cHair Color of Your Preferred Mate:\r\n\r\n");
  1960. mnemonics("~A) Blonde\r\n~B) Brown\r\n~C) Red\r\n~D) Black\r\n"
  1961.     "~E) Grey\r\n~F) Other\r\n~*) Any of the Above\r\n");
  1962. nodesync();
  1963. bputs("\r\n\1y\1hPlease enter up to 5 answers: ");
  1964. uchar2ans(user->pref_hair,str);
  1965. if(!getstr(str,5,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
  1966.     return(0);
  1967. user->pref_hair=ans2uchar(str);
  1968. if(user->pref_hair!=0xff) {
  1969.     strcpy(str,"\r\nDo you require your mate have the hair color"
  1970.         " you indicated");
  1971.     if(user->misc&USER_REQHAIR)
  1972.         i=yesno(str);
  1973.     else
  1974.         i=!noyes(str);
  1975.     if(i)
  1976.         user->misc|=USER_REQHAIR;
  1977.     else
  1978.         user->misc&=~USER_REQHAIR; }
  1979. else
  1980.     user->misc&=~USER_REQHAIR;
  1981. if(aborted) return(0);
  1982.  
  1983.  
  1984. bputs(hdr);
  1985. bputs("\1n\1h\1cEye Color of Your Preferred Mate:\r\n\r\n");
  1986. mnemonics("~A) Blue\r\n~B) Green\r\n~C) Hazel\r\n~D) Brown\r\n"
  1987.     "~E) Other\r\n~*) Any of the above\r\n");
  1988. nodesync();
  1989. bputs("\r\n\1y\1hPlease enter up to 4 answers: ");
  1990. uchar2ans(user->pref_eyes,str);
  1991. if(!getstr(str,4,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
  1992.     return(0);
  1993. user->pref_eyes=ans2uchar(str);
  1994. if(user->pref_eyes!=0xff) {
  1995.     strcpy(str,"\r\nDo you require your mate have the eye color"
  1996.         " you indicated");
  1997.     if(user->misc&USER_REQEYES)
  1998.         i=yesno(str);
  1999.     else
  2000.         i=!noyes(str);
  2001.     if(i)
  2002.         user->misc|=USER_REQEYES;
  2003.     else
  2004.         user->misc&=~USER_REQEYES; }
  2005. else
  2006.     user->misc&=~USER_REQEYES;
  2007. if(aborted) return(0);
  2008.  
  2009. bputs(hdr);
  2010. bputs("\1n\1h\1cZodiac Sign of Your Preferred Mate:\r\n\r\n");
  2011. mnemonics("~A) Aries\r\n~B) Taurus\r\n~C) Gemini\r\n~D) Cancer\r\n"
  2012.     "~E) Leo\r\n~F) Virgo\r\n~G) Libra\r\n~H) Scorpio\r\n");
  2013. mnemonics("~I) Sagittarius\r\n~J) Capricorn\r\n~K) Aquarius\r\n"
  2014.     "~L) Pisces\r\n~*) Any of the above\r\n");
  2015. nodesync();
  2016. bputs("\r\n\1y\1hPlease enter up to 11 answers: ");
  2017. bits2ans(user->pref_zodiac,str);
  2018. if(!getstr(str,11,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
  2019.     return(0);
  2020. user->pref_zodiac=ans2bits(str);
  2021. if(user->pref_zodiac!=0xffff) {
  2022.     strcpy(str,"\r\nDo you require your mate have the zodiac sign"
  2023.         " you indicated");
  2024.     if(user->misc&USER_REQZODIAC)
  2025.         i=yesno(str);
  2026.     else
  2027.         i=!noyes(str);
  2028.     if(i)
  2029.         user->misc|=USER_REQZODIAC;
  2030.     else
  2031.         user->misc&=~USER_REQZODIAC; }
  2032. else
  2033.     user->misc&=~USER_REQZODIAC;
  2034. if(aborted) return(0);
  2035.  
  2036. return(1);
  2037. }
  2038.  
  2039. void mbtype_desc(char *mbtype)
  2040. {
  2041.     char str[128],type[128];
  2042.  
  2043. while(1) {
  2044.     checkline();
  2045.     cls();
  2046.     printfile("MB-TYPE.ASC");
  2047.     nodesync();
  2048.     bprintf("\r\n\1y\1hYour Type: \1w%s\r\n",mbtype);
  2049.     bputs("\1y\1hLetter or Type to define: ");
  2050.     memset(type,0,5);
  2051.     if(!getstr(type,4,K_ALPHA|K_UPPER|K_LINE))
  2052.         break;
  2053.     sprintf(str,"MB-%s.ASC",type);
  2054.     if(!fexist(str)) {
  2055.         bputs("\r\nInvalid Letter or Type!\r\n\r\n");
  2056.         pause();
  2057.         continue; }
  2058.     cls();
  2059.     printfile(str);
  2060.     if(lncntr && !aborted)
  2061.         pause(); }
  2062. }
  2063.  
  2064.  
  2065. int get_mbtype(user_t *user)
  2066. {
  2067.     char str[256];
  2068.     int file,i=0,e=0,n=0,s=0,f=0,t=0,p=0,j=0,q=0,ch;
  2069.     FILE *stream;
  2070.  
  2071. aborted=0;
  2072. cls();
  2073. printfile("MB-INTRO.ASC");
  2074. if(aborted)
  2075.     return(0);
  2076. bputs("\1n\1hYour answers will be kept secret.\r\n\r\n"
  2077.     "Only your personality type will be visible to other users.\r\n\r\n");
  2078. nodesync();
  2079. if(!yesno("Continue with test"))
  2080.     return(0);
  2081.  
  2082. if((file=nopen("MB-TYPE.QUE",O_RDONLY))==-1 ||
  2083.     (stream=fdopen(file,"r"))==NULL) {
  2084.     bputs("\7\r\i\hCan't open MBTYPE.QUE\r\n\1p");
  2085.     return(0); }
  2086. while(!feof(stream)) {
  2087.     if(!fgets(str,200,stream))
  2088.         break;
  2089.     str[57]=0;
  2090.     truncsp(str);
  2091.     if(!str[0])
  2092.         break;
  2093.     cls();
  2094.     nodesync();
  2095.     bprintf("\1y\1hMyers-Briggs Personality Test  \1bQuestion #\1w%u  "
  2096.         "\1b(Ctrl-C to Abort)\r\n"
  2097.         "\r\n%s:\r\n\r\n"
  2098.         "[\1wA\1b] %.44s\r\n"
  2099.         "[\1wB\1b] %.44s\r\n"
  2100.         "[\1wC\1b] cannot decide\r\n\r\n"
  2101.         "Which: \1w"
  2102.         ,q+1,str,str+58,str+102);
  2103.     ch=getkeys("ABC",0);
  2104.     if(aborted) {
  2105.         fclose(stream);
  2106.         return(0); }
  2107.     if(ch=='C') {
  2108.         q++;
  2109.         continue; }
  2110.  
  2111.     if(ch=='A')
  2112.         ch=str[146];
  2113.     else
  2114.         ch=str[147];
  2115.  
  2116.     switch(ch) {
  2117.         case 'E':
  2118.             e++;
  2119.             break;
  2120.         case 'I':
  2121.             i++;
  2122.             break;
  2123.         case 'S':
  2124.             s++;
  2125.             break;
  2126.         case 'N':
  2127.             n++;
  2128.             break;
  2129.         case 'T':
  2130.             t++;
  2131.             break;
  2132.         case 'F':
  2133.             f++;
  2134.             break;
  2135.         case 'J':
  2136.             j++;
  2137.             break;
  2138.         case 'P':
  2139.             p++;
  2140.             break; }
  2141.     q++; }
  2142.  
  2143. fclose(stream);
  2144.  
  2145. if(i>e)
  2146.     user->mbtype[0]='I';
  2147. else if(i==e)
  2148.     user->mbtype[0]='*';
  2149. else
  2150.     user->mbtype[0]='E';
  2151.  
  2152. if(s>n)
  2153.     user->mbtype[1]='S';
  2154. else if(s==n)
  2155.     user->mbtype[1]='*';
  2156. else
  2157.     user->mbtype[1]='N';
  2158.  
  2159. if(t>f)
  2160.     user->mbtype[2]='T';
  2161. else if(t==f)
  2162.     user->mbtype[2]='*';
  2163. else
  2164.     user->mbtype[2]='F';
  2165.  
  2166. if(p>j)
  2167.     user->mbtype[3]='P';
  2168. else if(p==j)
  2169.     user->mbtype[3]='*';
  2170. else
  2171.     user->mbtype[3]='J';
  2172.  
  2173. bprintf("\1l\1y\1hYour Myers-Briggs Personality Type is \1w%s\r\n\r\n"
  2174.     ,user->mbtype);
  2175.  
  2176. if(yesno("Would you like to see the personality type descriptions"))
  2177.     mbtype_desc(user->mbtype);
  2178. return(1);
  2179. }
  2180.  
  2181.  
  2182. int get_purity(user_t *user)
  2183. {
  2184.     char str[128];
  2185.     int file,no_ans=0,pos_ans=0;
  2186.     FILE *stream;
  2187.  
  2188. aborted=0;
  2189. if(!fexist("PURITY.QUE") || purity_age>getage(user->birth))
  2190.     return(0);
  2191. cls();
  2192. printfile("PURITY.ASC");
  2193. if(aborted)
  2194.     return(0);
  2195. bputs("\1n\1hYour answers will be kept secret.\r\n\r\n"
  2196.     "Only your purity score will be visible to other users.\r\n\r\n");
  2197. nodesync();
  2198. if(!yesno("Continue with test"))
  2199.     return(0);
  2200. if((file=nopen("PURITY.QUE",O_RDONLY))==-1 ||
  2201.     (stream=fdopen(file,"r"))==NULL) {
  2202.     bputs("\7\r\i\hCan't open PURITY.QUE\r\n\1p");
  2203.     return(0); }
  2204. while(!feof(stream)) {
  2205.     if(!fgets(str,81,stream))
  2206.         break;
  2207.     truncsp(str);
  2208.     cls();
  2209.     if(str[0]=='*') {
  2210.         printfile(str+1);
  2211.         if(lncntr && !aborted)
  2212.             pause();
  2213.         if(aborted)
  2214.             break;
  2215.         continue; }
  2216.     nodesync();
  2217.     bprintf("\1y\1hPurity Test  \1bQuestion #\1w%u  \1b(Ctrl-C to Abort)\r\n"
  2218.         "\r\nHave you ever:\r\n\r\n"
  2219.         ,++pos_ans);
  2220.     if(noyes(str))
  2221.         no_ans++;
  2222.     if(aborted)
  2223.         break; }
  2224.  
  2225. fclose(stream);
  2226. if(aborted)
  2227.     return(0);
  2228.  
  2229. user->purity=((float)no_ans/pos_ans)*100.0;
  2230. bprintf("\1l\1y\1hCongratulations, you are \1w%u%%\1y pure!\r\n\r\n"
  2231.     ,user->purity);
  2232. pause();
  2233. return(1);
  2234. }
  2235.  
  2236. int get_que(int i, user_t *inuser)
  2237. {
  2238.     char str[128];
  2239.     int j,k,x,y,u;
  2240.     user_t user=*inuser;
  2241.  
  2242. if(que[i]->req_age>getage(inuser->birth))
  2243.     return(0);
  2244. for(j=0;j<que[i]->total_ques && !aborted;j++) {
  2245.  
  2246.     u=user_quenum(que[i]->name,user);
  2247.     if(u==-1) {             /* not already answered */
  2248.         for(u=0;u<5;u++)    /* search for unused questionnaire slot */
  2249.             if(sys_quenum(user.queans[u].name)==-1)
  2250.                 break;
  2251.         if(u==5) {        /* All questionnaire slots used!?? */
  2252.             bputs("\r\n\7Questionnaire error, inform sysop!\r\n");
  2253.             pause();
  2254.             return(0); } }
  2255.     strcpy(user.queans[u].name,que[i]->name);
  2256.     cls();
  2257.     bprintf("\1n\1m\1hQuestionnaire: \1y%-25s \1mQuestion: "
  2258.         "\1y%d \1mof \1y%d  \1h\1b(Ctrl-C to Abort)\r\n\r\n"
  2259.         ,que[i]->desc,j+1,que[i]->total_ques);
  2260.     bprintf("\1w\1h%s\r\n\r\n",que[i]->que[j].txt);
  2261.     for(k=0;k<que[i]->que[j].answers;k++)
  2262.         bprintf("\1h\1b%c\1w) \1g%s\r\n",'A'+k,que[i]->que[j].ans[k]);
  2263.     nodesync();
  2264.     bprintf("\1n\1g\r\nChoose %s%d answer%s to describe "
  2265.         "\1hyourself\1n\1g%s: "
  2266.         ,que[i]->que[j].allowed > 1 ? "up to ":""
  2267.         ,que[i]->que[j].allowed,que[i]->que[j].allowed > 1 ? "s":""
  2268.         ,j ? " or \1h-\1n\1g to go back" : "");
  2269.     bits2ans(user.queans[u].self[j],str);
  2270.     getstr(str,que[i]->que[j].allowed,K_UPPER|K_LINE|K_EDIT|K_AUTODEL);
  2271.     if(aborted)
  2272.         return(0);
  2273.     truncsp(str);
  2274.     if(!str[0]) {
  2275.         j--;
  2276.         continue; }
  2277.     if(str[0]=='-') {
  2278.         if(j) j-=2;
  2279.         else j--;
  2280.         continue; }
  2281.     y=strlen(str);
  2282.     for(x=0;x<y;x++)
  2283.         if(!isalpha(str[x]) || str[x]-'A'>que[i]->que[j].answers-1)
  2284.             break;
  2285.     if(x<y) {
  2286.         j--;
  2287.         continue; }
  2288.     user.queans[u].self[j]=ans2bits(str);
  2289.     nodesync();
  2290.     bprintf("\1n\1g\r\n%s%d answer%s to describe your \1hpreferred mate"
  2291.         "\1n\1g or \1h*\1n\1g for any: "
  2292.         ,que[i]->que[j].answers > 1 ? "Up to ":""
  2293.         ,que[i]->que[j].answers,que[i]->que[j].answers > 1 ? "s":"");
  2294.     if(user.queans[u].pref[j])
  2295.         bits2ans(user.queans[u].pref[j],str);
  2296.     getstr(str,que[i]->que[j].answers,K_UPPER|K_LINE|K_EDIT|K_AUTODEL);
  2297.     if(aborted)
  2298.         return(0);
  2299.     truncsp(str);
  2300.     if(!str[0]) {
  2301.         j--;
  2302.         continue; }
  2303.     y=strlen(str);
  2304.     for(x=0;x<y;x++)
  2305.         if(isalpha(str[x]) && str[x]-'A'>que[i]->que[j].answers-1)
  2306.             break;
  2307.     if(x<y) {
  2308.         j--;
  2309.         continue; }
  2310.     user.queans[u].pref[j]=ans2bits(str); }
  2311. *inuser=user;
  2312. return(1);
  2313. }
  2314.  
  2315. /* Gets/updates profile from user. Returns 0 if aborted. */
  2316.  
  2317. char get_user_info(user_t *user)
  2318. {
  2319.     char str[128],*p,*hdr;
  2320.     int i,j,k,x,y;
  2321.  
  2322. while(1) {
  2323.     checkline();
  2324.     timeleft=0xffff;
  2325.     aborted=0;
  2326.     main_user_info(*user);
  2327.     CRLF;
  2328.     bputs("\1n\1h");
  2329.     bputs("\1b[\1wA\1b] Your name, height, weight, income, location, and "
  2330.             "text\r\n"
  2331.           "\1b[\1wB\1b] Your marital status, race, hair color, and eye "
  2332.             "color\r\n"
  2333.           "\1b[\1wC\1b] Preferred age, height, weight, location, and income\r\n"
  2334.           "\1b[\1wD\1b] Preferred sex, marital status, race, hair color, eye "
  2335.             "color, and zodiac\r\n"
  2336.           );
  2337.     for(i=0;i<total_ques;i++) {
  2338.         if(que[i]->req_age>getage(user->birth))
  2339.             continue;
  2340.         bprintf("\1b[\1w%u\1b] \1w%s \1bquestionnaire\1b (%u questions) \1w%s\r\n"
  2341.             ,i+1,que[i]->desc,que[i]->total_ques
  2342.             ,user_quenum(que[i]->name,*user)==-1 ? "[Unanswered]":"[Answered]");
  2343.             }
  2344.     bprintf("\1b[\1wM\1b] Myers-Briggs personality test (70 questions) "
  2345.         "\1w[%s]\r\n",user->mbtype[0] ? user->mbtype : "Unanswered");
  2346.     if(fexist("PURITY.QUE") && purity_age<=getage(user->birth))
  2347.         bprintf("\1b[\1wP\1b] Purity test \1w(%u%% pure)\r\n"
  2348.             ,user->purity);
  2349.     bputs("\r\n\1bWhich or [\1wQ\1b]uit: \1w");
  2350.     i=getkeys("ABCDMPQ",total_ques);
  2351.     if(i&0x8000) {
  2352.         i&=~0x8000;
  2353.         i--;
  2354.         get_que(i,user);
  2355.         continue; }
  2356.  
  2357.     switch(i) {
  2358.         case 'A':
  2359.             get_your_det(user);
  2360.             break;
  2361.         case 'C':
  2362.             get_pref_det(user);
  2363.             break;
  2364.         case 'B':
  2365.             get_your_multi(user);
  2366.             break;
  2367.         case 'D':
  2368.             get_pref_multi(user);
  2369.             break;
  2370.         case 'M':
  2371.             get_mbtype(user);
  2372.             break;
  2373.         case 'P':
  2374.             get_purity(user);
  2375.             break;
  2376.         case 'Q':
  2377.             return(1); } }
  2378. }
  2379.  
  2380. void write_user()
  2381. {
  2382.     char str[256];
  2383.  
  2384. if(auto_update && time(NULL)-useron.updated>(long)auto_update*24L*60L*60L)
  2385.     useron.updated=time(NULL);
  2386. fseek(stream,useron_record*sizeof(user_t),SEEK_SET);
  2387. fwrite(&useron,sizeof(user_t),1,stream);
  2388. fflush(stream);
  2389.  
  2390. ixb.updated=useron.updated;
  2391. if(useron.misc&USER_DELETED)
  2392.     ixb.number=0;
  2393. else
  2394.     ixb.number=useron.number;
  2395. strcpy(str,useron.name);
  2396. strupr(str);
  2397. ixb.name=crc32(str);
  2398. ixb.system=system_crc;
  2399. fseek(index,useron_record*sizeof(ixb_t),SEEK_SET);
  2400. fwrite(&ixb,sizeof(ixb_t),1,index);
  2401. fflush(index);
  2402. if(!ixb.number) {
  2403.     sprintf(str,"%04u.MSG",useron.number);
  2404.     remove(str); }
  2405. }
  2406.  
  2407.  
  2408. void add_userinfo()
  2409. {
  2410.     static user_t user;
  2411.     char str[128];
  2412.     ushort tleft=timeleft;
  2413.     int i;
  2414.  
  2415. if(!cdt_warning(profile_cdt))
  2416.     return;
  2417. timeleft=0xffff;
  2418. user.number=user_number;
  2419. user.sex=user_sex;
  2420. strcpy(user.name,user_name);
  2421. strcpy(user.realname,user_name);
  2422. strcpy(user.system,system_name);
  2423. strcpy(user.birth,user_birth);
  2424. strcpy(user.zipcode,user_zipcode);
  2425. sprintf(user.min_zipcode,"%c0000",user_zipcode[0]);
  2426. sprintf(user.max_zipcode,"%c9999",user_zipcode[0]);
  2427. strcpy(user.location,user_location);
  2428. if(user.sex!='M' && user.sex!='F') {
  2429.     if(yesno("Are you of male gender"))
  2430.         user.sex='M';
  2431.     else
  2432.         user.sex='F'; }
  2433. if(!getage(user.birth))
  2434.     while(1) {
  2435.         checkline();
  2436.         cls();
  2437.         bputs("\1l\1y\1hYour birthdate (MM/DD/YY): ");
  2438.         if(!getstr(user.birth,8,K_UPPER|K_LINE))
  2439.             return;
  2440.         if(getage(user.birth))
  2441.             break; }
  2442.  
  2443. user.pref_sex=user.sex=='M' ? 'F' : 'M';
  2444. user.created=time(NULL);
  2445. if(!get_your_det(&user) || !get_your_multi(&user) || !get_pref_multi(&user)
  2446.     || !get_pref_det(&user)) {
  2447.     timeleft=tleft;
  2448.     return; }
  2449. for(i=0;i<total_ques;i++) {
  2450.     aborted=0;
  2451.     if(que[i]->req_age>getage(user.birth))
  2452.         continue;
  2453.     timeleft=0xffff;
  2454.     cls();
  2455.     bprintf("\1w\1h%s Questionnaire: \1y%u questions\r\n\r\n"
  2456.         "\1cAnswers will be viewable by other users.\r\n\r\n"
  2457.         ,que[i]->desc,que[i]->total_ques);
  2458.     if(yesno("Continue with questionnaire"))
  2459.         get_que(i,&user); }
  2460. timeleft=0xffff;
  2461. get_mbtype(&user);
  2462. timeleft=0xffff;
  2463. get_purity(&user);
  2464. if(!get_user_info(&user)) {
  2465.     timeleft=tleft;
  2466.     return; }
  2467. user.updated=time(NULL);
  2468. useron=user;
  2469. bputs("\1n\1h\r\nSaving...");
  2470. rewind(index);
  2471. while(!feof(index)) {
  2472.     if(!fread(&ixb,sizeof(ixb_t),1,index))
  2473.         break;
  2474.     if(!ixb.number) {      /* Deleted User */
  2475.         fseek(index,ftell(index)-sizeof(ixb_t),SEEK_SET);
  2476.         break; } }
  2477.  
  2478. useron_record=ftell(index)/sizeof(ixb_t);
  2479.  
  2480. write_user();
  2481. adjust_cdt(profile_cdt);
  2482.  
  2483. if(notify_user && notify_user!=user_number) {
  2484.     sprintf(str,"\1n\1hSMM: \1y%s \1madded %s profile to the Match Maker.\r\n"
  2485.         ,user_name,user_sex=='M' ? "his":"her");
  2486.     if(node_dir[0])
  2487.         putsmsg(notify_user,str);
  2488.     else
  2489.         puttgram(notify_user,str); }
  2490.  
  2491. timeleft=tleft;
  2492. }
  2493.  
  2494. void delphoto(user_t user)
  2495. {
  2496.     char fname[64],path[128];
  2497.     int i;
  2498.     struct ffblk ff;
  2499.  
  2500. if(!(user.misc&USER_PHOTO))
  2501.     return;
  2502. for(i=0;user.system[i];i++)
  2503.     if(isalnum(user.system[i]))
  2504.         break;
  2505. if(!user.system[i])
  2506.     fname[0]='~';
  2507. else
  2508.     fname[0]=user.system[i];
  2509. for(i=strlen(user.system)-1;i>0;i--)
  2510.     if(isalnum(user.system[i]))
  2511.         break;
  2512. if(i<=0)
  2513.     fname[1]='~';
  2514. else
  2515.     fname[1]=user.system[i];
  2516. fname[2]=0;
  2517. strupr(user.system);
  2518. strcat(fname,base41(crc16(user.system),tmp));
  2519. strcat(fname,base41(user.number,tmp));
  2520. strcat(fname,".*");
  2521. strupr(fname);
  2522. sprintf(path,"PHOTO\\%s",fname);
  2523. i=findfirst(path,&ff,0);
  2524. if(i)
  2525.     return;
  2526. sprintf(path,"PHOTO\\%s",ff.ff_name);
  2527. if(remove(path))
  2528.     bprintf("\1r\1h\7%s couldn't be removed!\1n\r\n",path);
  2529. else
  2530.     bprintf("\1r\1hPhoto removed.\r\n");
  2531. }
  2532.  
  2533.  
  2534. void smm_exit()
  2535. {
  2536.     char str[128];
  2537.     int i;
  2538.     FILE *in,*out;
  2539.  
  2540. if(io_int) {
  2541.     io_int=0;
  2542.     ivhctl(0); }
  2543. if(com_port) {
  2544.     for(i=0;i<5;i++)
  2545.         if(!rioctl(TXBC))        /* wait for rest of output */
  2546.             break;
  2547.         else
  2548.             mswait(1000);
  2549.     rioini(0,0); }
  2550. if(useron.number) {
  2551.     useron.lastin=time(NULL);
  2552.     write_user(); }
  2553. if(stream)
  2554.     fclose(stream);
  2555. if(cdt_adjustment) {
  2556.     if(node_dir[0]) {
  2557.         sprintf(str,"%sMODUSER.DAT",node_dir);
  2558.         if((out=fopen(str,"wt"))==NULL) {
  2559.             bprintf("Error opening %s for write\r\n",str);
  2560.             return; }
  2561.         fprintf(out,"%ld",cdt_adjustment);
  2562.         fclose(out); }
  2563.     else {                            /* Write back credits to DOOR.SYS */
  2564.         strcpy(str,door_sys);
  2565.         str[strlen(str)-1]='_';
  2566.         remove(str);
  2567.         rename(door_sys,str);
  2568.         if((in=fopen(str,"rb"))==NULL) {
  2569.             bprintf("Error opening %s for read\r\n",str);
  2570.             return; }
  2571.         if((out=fopen(door_sys,"wb"))==NULL) {
  2572.             bprintf("Error opening %s for write\r\n",door_sys);
  2573.             return; }
  2574.         for(i=0;!feof(in);i++) {
  2575.             if(!fgets(tmp,128,in))
  2576.                 break;
  2577.             if(i+1==30)
  2578.                 fprintf(out,"%ld\r\n",-(cdt_adjustment/1024L));
  2579.             else if(i+1==31)
  2580.                 fprintf(out,"%ld\r\n",(user_cdt+cdt_adjustment)/1024L);
  2581.             else
  2582.                 fprintf(out,"%s",tmp); }
  2583.         fclose(in);
  2584.         fclose(out);
  2585.         remove(str);
  2586.         } }
  2587. }
  2588.  
  2589. time_t checktime()
  2590. {
  2591.     struct tm tm;
  2592.  
  2593. memset(&tm,0,sizeof(tm));
  2594. tm.tm_year=94;
  2595. tm.tm_mday=1;
  2596. return(mktime(&tm)^0x2D24BD00L);
  2597. }
  2598.  
  2599. void statusline(void)
  2600. {
  2601.     int col,row;
  2602.  
  2603. col=lclwx();
  2604. row=lclwy();
  2605. lclxy(1,node_scrnlen);
  2606. lclatr(CYAN|HIGH|(BLUE<<4));
  2607. lputs("  ");
  2608. lprintf("%-25.25s %02d %-25.25s  %02d %c %s"
  2609.     ,user_name,user_level,user_realname[0] ? user_realname : user_location
  2610.     ,getage(user_birth)
  2611.     ,user_sex ? user_sex : SP
  2612.     ,user_phone);
  2613. lputc(CLREOL);
  2614. lclatr(LIGHTGRAY);
  2615. lclxy(col,row);
  2616. }
  2617.  
  2618.  
  2619. int minor_protection(user_t user)
  2620. {
  2621. if(!user_number || !age_split || SYSOP)
  2622.     return(0);
  2623. if(getage(user_birth)<age_split && getage(user.birth)>=age_split)
  2624.     return(1);
  2625. if(getage(user_birth)>=age_split && getage(user.birth)<age_split)
  2626.     return(1);
  2627. return(0);
  2628. }
  2629.  
  2630. void main(int argc, char **argv)
  2631. {
  2632.     char    str[512],name[128],desc[128],gotoname[128],*p,ext,ch;
  2633.     int     i,j,k,file,match,found;
  2634.     uint    base=0xffff;
  2635.     ushort    tleft;
  2636.     long    l,offset;
  2637.     ulong    name_crc,sys_crc,*crc_lst,ul;
  2638.     FILE    *fp,*que_lst;
  2639.     user_t    user;
  2640.     wall_t    wall;
  2641.     struct    ffblk ff;
  2642.  
  2643. nodefile=-1;
  2644. node_misc=NM_LOWPRIO;
  2645. com_port=-1;
  2646. com_base=0;
  2647. com_irq=com_rate=0;
  2648. node_dir[0]=exec_dir[0]=temp_dir[0]=ctrl_dir[0]=door_sys[0]=system_name[0]=0;
  2649. sys_name[0]=0;
  2650.  
  2651. p=getenv("SBBSNODE");
  2652. if(p) {
  2653.     strcpy(node_dir,p);
  2654.     if(node_dir[strlen(node_dir)-1]!='\\')
  2655.         strcat(node_dir,"\\");
  2656.     initdata(); }
  2657.  
  2658. gotoname[0]=0;
  2659. for(i=1;i<argc;i++) {
  2660.     if(argv[i][0]=='/') {
  2661.         switch(toupper(argv[i][1])) {
  2662.             case 'P':
  2663.                 com_port=atoi(argv[i]+2);
  2664.                 break;
  2665.             case 'I':
  2666.                 com_irq=atoi(argv[i]+2);
  2667.                 break;
  2668.             case 'C':
  2669.                 com_base=ahtoul(argv[i]+2);
  2670.                 break;
  2671.             case 'R':
  2672.                 com_rate=atol(argv[i]+2);
  2673.                 break;
  2674.             case 'T':
  2675.                 mswtyp=atoi(argv[i]+2);
  2676.                 break;
  2677.             case 'N':
  2678.                 node_dir[0]=0;
  2679.                 break;
  2680.             default:
  2681.                 printf("\nusage: SMM [DOOR.SYS] [/option] [/option] [...] [user name]\n");
  2682.                 printf("\n");
  2683.                 printf("where:\n");
  2684.                 printf("       DOOR.SYS is the path and filename of DOOR.SYS\n");
  2685.                 printf("\n");
  2686.                 printf("       /p# sets com port\n");
  2687.                 printf("       /i# sets com irq\n");
  2688.                 printf("       /c# sets com I/O address (or DIGI or FOSSIL)\n");
  2689.                 printf("       /r# sets com rate\n");
  2690.                 printf("       /t# sets time-slice API support\n");
  2691.                 printf("\n");
  2692.                 printf("       user name (if specified) is user to look-up\n");
  2693.                 exit(1); }
  2694.         continue; }
  2695.     if(!node_dir[0] && !door_sys[0]) {
  2696.         strcpy(door_sys,argv[i]);
  2697.         continue; }
  2698.     if(gotoname[0])
  2699.         strcat(gotoname," ");
  2700.     strcat(gotoname,argv[i]); }
  2701.  
  2702. if(!node_dir[0] && !door_sys[0]) {
  2703.     printf("\n\7SBBSNODE environment variable not set and DOOR.SYS not "
  2704.         "specified.\n");
  2705.     exit(1); }
  2706.  
  2707. if(door_sys[0]) {
  2708.     #ifdef __TURBOC__
  2709.         ctrlbrk(cbreakh);
  2710.     #endif
  2711.  
  2712.     #ifdef __WATCOMC__
  2713.         putenv("TZ=UCT0");
  2714.         setvbuf(stdout,NULL,_IONBF,0);
  2715.         setvbuf(stderr,NULL,_IONBF,0);
  2716.     #endif
  2717.  
  2718.     if(setmode(fileno(stderr),O_BINARY)==-1) {     /* eliminate LF expansion */
  2719.         printf("\n\7Can't set stderr to BINARY\n");
  2720.         exit(1); }
  2721.  
  2722.     starttime=time(NULL);            /* initialize start time stamp */
  2723.     wordwrap[0]=0;                    /* set wordwrap to null */
  2724.     attr(LIGHTGRAY);                /* initialize color and curatr to plain */
  2725.     mnehigh=LIGHTGRAY|HIGH;         /* mnemonics highlight color */
  2726.     mnelow=GREEN;                    /* mnemonics normal text color */
  2727.     sec_warn=180;                    /* seconds till inactivity warning */
  2728.     sec_timeout=300;                /* seconds till inactivity timeout */
  2729.     tos=lncntr=0;                    /* init topofscreen and linecounter to 0 */
  2730.     lastnodemsg=0;                    /* Last node to send message to */
  2731.     aborted=0;                        /* Ctrl-C hit flag */
  2732.  
  2733.     fp=fopen(door_sys,"rb");
  2734.     if(!fp) {
  2735.         printf("\n\7ERROR opening %s\n",door_sys);
  2736.         exit(2); }
  2737.     user_misc=user_flags2[0]=user_flags3[0]=user_flags4[0]=0;
  2738.     user_rest[0]=user_exempt[0]=0;
  2739.     user_sex=user_address[0]=user_zipcode[0]=user_realname[0]=0;
  2740.     str[0]=0;
  2741.     fgets(str,81,fp);                // 01: COM port - if local
  2742.     if(com_port==-1)
  2743.         com_port=atoi(str+3);
  2744.     str[0]=0;
  2745.     fgets(str,81,fp);                // 02: DCE Rate
  2746.     user_dce=atoi(str);
  2747.     fgets(str,81,fp);                // 03: Data bits
  2748.     str[0]=0;
  2749.     fgets(str,81,fp);                // 04: Node num
  2750.     node_num=atoi(str);
  2751.     str[0]=0;
  2752.     fgets(str,81,fp);                // 05: DTE rate
  2753.     if(!com_rate)
  2754.         com_rate=atol(str);
  2755.     fgets(str,81,fp);                // 06: Screen display
  2756.     fgets(str,81,fp);                // 07: Printer toggle
  2757.     fgets(str,81,fp);                // 08: Page bell
  2758.     fgets(str,81,fp);                // 09: Caller alarm
  2759.     str[0]=0;
  2760.     fgets(str,81,fp);                // 10: User name
  2761.     sprintf(user_name,"%.25s",str);
  2762.     truncsp(user_name);
  2763.     str[0]=0;
  2764.     fgets(str,81,fp);                // 11: User location
  2765.     sprintf(user_location,"%.30s",str);
  2766.     truncsp(user_location);
  2767.     str[0]=0;
  2768.     fgets(str,81,fp);                // 12: Home phone
  2769.     sprintf(user_phone,"%.12s",str);
  2770.     truncsp(user_phone);
  2771.     fgets(str,81,fp);                // 13: Work phone
  2772.     fgets(str,81,fp);                // 14: Password
  2773.     str[0]=0;
  2774.     fgets(str,81,fp);                // 15: Security Level
  2775.     user_level=atoi(str);
  2776.     fgets(str,81,fp);                // 16: Total logons
  2777.     fgets(str,81,fp);                // 17: Last on date
  2778.     str[0]=0;
  2779.     fgets(str,81,fp);                // 18: Time left in seconds
  2780.     timeleft=atoi(str);
  2781.     fgets(str,81,fp);                // 19: Time left in minutes
  2782.     str[0]=0;
  2783.     fgets(str,81,fp);                // 20: Graphics
  2784.     if(!strnicmp(str,"GR",2))
  2785.         user_misc|=(COLOR|ANSI);
  2786.     str[0]=0;
  2787.     fgets(str,81,fp);                // 21: Screen length
  2788.     user_rows=atoi(str);
  2789.     if(user_rows<10)
  2790.         user_rows=24;
  2791.     fgets(str,81,fp);                // 22: Expert?
  2792.     str[0]=0;
  2793.     fgets(str,81,fp);                // 23: Registered conferences
  2794.     sprintf(user_flags1,"%.26s",str);
  2795.     truncsp(user_flags1);
  2796.     fgets(str,81,fp);                // 24: Conference came from
  2797.     str[0]=0;
  2798.     fgets(str,81,fp);                // 25: User's expiration date
  2799.     user_expire=dstrtounix(str);
  2800.     str[0]=0;
  2801.     fgets(str,81,fp);                // 26: User's number
  2802.     user_number=atoi(str);
  2803.     fgets(str,81,fp);                // 27: Default protocol
  2804.     fgets(str,81,fp);                // 28: Total uploads
  2805.     fgets(str,81,fp);                // 29: Total downloads
  2806.     fgets(str,81,fp);                // 30: Kbytes downloaded today
  2807.     str[0]=0;
  2808.     fgets(str,81,fp);                // 31: Max Kbytes to download today
  2809.     user_cdt=atol(str)*1024UL;
  2810.     str[0]=0;
  2811.     fgets(str,81,fp);                // 32: Birthday
  2812.     truncsp(str);
  2813.     sprintf(user_birth,"%.8s",str);
  2814.     fgets(str,81,fp);                // 33: Path to MAIN
  2815.     fgets(str,81,fp);                // 34: Path to GEN
  2816.     str[0]=0;
  2817.     fgets(str,81,fp);                 // 35: Sysop's name
  2818.     sprintf(sys_op,"%.40s",str);
  2819.     truncsp(sys_op);
  2820.     fclose(fp);
  2821.     con_fp=stderr;
  2822.     if(setmode(fileno(con_fp),O_BINARY)==-1) {     /* eliminate LF expansion */
  2823.         printf("Can't set console output to BINARY\n");
  2824.         exit(1); }
  2825.     }
  2826.  
  2827. if(!user_number) {
  2828.     printf("\7\nERROR: Invalid user number (%u)\n",user_number);
  2829.     exit(5); }
  2830.  
  2831. if(*(&riobp-1)!=23) {
  2832.     printf("Wrong rciol.obj\n");
  2833.     exit(1); }
  2834.  
  2835. node_scrnlen=lclini(0xd<<8);      /* Tab expansion, no CRLF expansion */
  2836. lclini(node_scrnlen-1);
  2837.  
  2838. if(com_port) {
  2839.     lprintf("\r\nInitializing COM port %u: ",com_port);
  2840.     switch(com_base) {
  2841.         case 0xb:
  2842.             lputs("PC BIOS");
  2843.             rioctl(I14PC);
  2844.             if(!com_irq) com_irq=com_port-1;
  2845.             break;
  2846.         case 0xffff:
  2847.         case 0xd:
  2848.             lputs("DigiBoard");
  2849.             rioctl(I14DB);
  2850.             if(!com_irq) com_irq=com_port-1;
  2851.             break;
  2852.         case 0xe:
  2853.             lputs("PS/2 BIOS");
  2854.             rioctl(I14PS);
  2855.             if(!com_irq) com_irq=com_port-1;
  2856.             break;
  2857.         case 0xf:
  2858.             lputs("FOSSIL");
  2859.             rioctl(I14FO);
  2860.             if(!com_irq) com_irq=com_port-1;
  2861.             break;
  2862.         case 0:
  2863.             base=com_port;
  2864.             lputs("UART I/O (BIOS), ");
  2865.             if(com_irq)
  2866.                 lprintf("IRQ %d",com_irq);
  2867.             else lputs("default IRQ");
  2868.             break;
  2869.         default:
  2870.             base=com_base;
  2871.             lprintf("UART I/O %Xh, ",com_base);
  2872.             if(com_irq)
  2873.                 lprintf("IRQ %d",com_irq);
  2874.             else lputs("default IRQ");
  2875.             break; }
  2876.  
  2877.     if(base==0xffff)
  2878.         lprintf(" channel %u",com_irq);
  2879.     i=rioini(base,com_irq);
  2880.     if(i) {
  2881.         lprintf(" - Failed! (%d)\r\n",i);
  2882.         exit(1); }
  2883.     if(mdm_misc&MDM_FLOWCTRL)
  2884.         rioctl(IOSM|CTSCK|RTSCK); /* set rts/cts chk */
  2885.     if(com_rate)
  2886.         setbaud((uint)(com_rate&0xffffL));
  2887.     msr=&riobp-1; }
  2888.  
  2889. /* STATUS LINE */
  2890. statusline();
  2891.  
  2892. rioctl(TSTYPE|mswtyp);     /* set time-slice API type */
  2893.  
  2894. rioctl(CPTON);            /* ctrl-p translation */
  2895.  
  2896. i=INT29L;
  2897. if(com_port)
  2898.     i|=(INT29R|INT16);
  2899. ivhctl(i);
  2900. io_int=1;
  2901.  
  2902. atexit(smm_exit);
  2903.  
  2904. printf("\r\nSynchronet Match Maker  v%s  Developed 1995-1997 Rob Swindell\n\n"
  2905.     ,SMM_VER);
  2906.  
  2907. if(checktime()) {
  2908.     printf("Time problem!\n");
  2909.     return; }
  2910.  
  2911. if((file=nopen("SMM.CFG",O_RDONLY))==-1) {
  2912.     bprintf("\r\n\7Error opening/creating SMM.DAB\r\n");
  2913.     exit(1); }
  2914. if((stream=fdopen(file,"w+b"))==NULL) {
  2915.     bprintf("\r\n\7Error converting SMM.DAB file handle to stream\r\n");
  2916.     exit(1); }
  2917. str[0]=0;
  2918. fgets(str,128,stream);
  2919. purity_age=atoi(str);
  2920. str[0]=0;
  2921. fgets(str,128,stream);
  2922. min_age=atoi(str);
  2923. str[0]=0;
  2924. fgets(str,128,stream);
  2925. min_level=atoi(str);
  2926.  
  2927. req_flags1[0]=0;
  2928. fgets(req_flags1,128,stream);
  2929. req_flags1[27]=0;
  2930. truncsp(req_flags1);
  2931.  
  2932. req_flags2[0]=0;
  2933. fgets(req_flags2,128,stream);
  2934. req_flags2[27]=0;
  2935. truncsp(req_flags2);
  2936.  
  2937. req_flags3[0]=0;
  2938. fgets(req_flags3,128,stream);
  2939. req_flags3[27]=0;
  2940. truncsp(req_flags3);
  2941.  
  2942. req_flags4[0]=0;
  2943. fgets(req_flags4,128,stream);
  2944. req_flags4[27]=0;
  2945. truncsp(req_flags4);
  2946.  
  2947. str[0]=0;
  2948. fgets(str,128,stream);
  2949. profile_cdt=atol(str);
  2950. str[0]=0;
  2951. fgets(str,128,stream);
  2952. telegram_cdt=atol(str);
  2953. str[0]=0;
  2954. fgets(str,128,stream);
  2955. auto_update=atoi(str);
  2956. str[0]=0;
  2957. fgets(str,128,stream);
  2958. notify_user=atoi(str);
  2959.  
  2960. fgets(str,128,stream);        // regnum
  2961.  
  2962. str[0]=0;
  2963. fgets(str,128,stream);
  2964. telegram_level=atoi(str);
  2965.  
  2966. str[0]=0;
  2967. fgets(str,128,stream);
  2968. que_level=atoi(str);
  2969.  
  2970. str[0]=0;
  2971. fgets(str,128,stream);
  2972. wall_level=atoi(str);
  2973.  
  2974. str[0]=0;
  2975. fgets(str,128,stream);
  2976. wall_cdt=atol(str);
  2977.  
  2978. str[0]=0;
  2979. fgets(str,128,stream);
  2980. que_cdt=atol(str);
  2981.  
  2982. fgets(zmodem_send,128,stream);
  2983. if(!zmodem_send[0])
  2984.     strcpy(zmodem_send,DEFAULT_ZMODEM_SEND);
  2985. truncsp(zmodem_send);
  2986.  
  2987. str[0]=0;
  2988. fgets(str,128,stream);
  2989. smm_misc=atol(str);
  2990.  
  2991. fgets(str,128,stream);
  2992. sprintf(system_name,"%.40s",str);
  2993. truncsp(system_name);
  2994.  
  2995. fgets(local_view,128,stream);
  2996. truncsp(local_view);
  2997.  
  2998. str[0]=0;
  2999. fgets(str,128,stream);
  3000. sysop_level=atoi(str);
  3001. if(!sysop_level)
  3002.     sysop_level=90;
  3003.  
  3004. str[0]=0;
  3005. fgets(str,128,stream);
  3006. wall_age=atoi(str);
  3007.  
  3008. str[0]=0;
  3009. fgets(str,128,stream);
  3010. age_split=atoi(str);
  3011.  
  3012. fclose(stream);
  3013.  
  3014. if(!system_name[0] && sys_name[0])
  3015.     strcpy(system_name,sys_name);
  3016. if(!system_name[0]) {
  3017.     printf("\7\nERROR: System name not specified\n");
  3018.     exit(3) ; }
  3019.  
  3020. sprintf(str,"%.25s",system_name);
  3021. strupr(str);
  3022. system_crc=crc32(str);
  3023.  
  3024. if((file=open("SMM.DAB",O_RDWR|O_BINARY|SH_DENYNO|O_CREAT
  3025.     ,S_IWRITE|S_IREAD))==-1) {
  3026.     bprintf("\r\n\7Error opening/creating SMM.DAB\r\n");
  3027.     exit(1); }
  3028. if((stream=fdopen(file,"w+b"))==NULL) {
  3029.     bprintf("\r\n\7Error converting SMM.DAB file handle to stream\r\n");
  3030.     exit(1); }
  3031. setvbuf(stream,0L,_IOFBF,4096);
  3032.  
  3033. if((file=open("SMM.IXB",O_RDWR|O_BINARY|SH_DENYNO|O_CREAT
  3034.     ,S_IWRITE|S_IREAD))==-1) {
  3035.     bprintf("\r\n\7Error opening/creating SMM.IXB\r\n");
  3036.     exit(1); }
  3037. if((index=fdopen(file,"w+b"))==NULL) {
  3038.     bprintf("\r\n\7Error converting SMM.IXB file handle to stream\r\n");
  3039.     exit(1); }
  3040. setvbuf(stream,0L,_IOFBF,1024);
  3041.  
  3042. trashfile=NULL;
  3043. if((file=open("SMM.CAN",O_RDONLY|SH_DENYNO))!=-1) {
  3044.     trashfile=fdopen(file,"rb");
  3045.     setvbuf(trashfile,NULL,_IOFBF,4096); }
  3046.  
  3047. total_ques=0;
  3048. i=nopen("QUE.LST",O_RDONLY);
  3049. if(i!=-1)
  3050.     que_lst=fdopen(i,"rb");
  3051. else
  3052.     que_lst=NULL;
  3053. i=0;
  3054. while(que_lst && !feof(que_lst) && i<5) {
  3055.     if(!fgets(name,81,que_lst))
  3056.         break;
  3057.     truncsp(name);
  3058.     strupr(name);
  3059.     sprintf(str,"%s.QUE",name);
  3060.     if(!fgets(desc,81,que_lst))
  3061.         break;
  3062.     truncsp(desc);
  3063.     if(!fgets(tmp,81,que_lst))
  3064.         break;
  3065.     truncsp(tmp);
  3066.     if((file=nopen(str,O_RDONLY))!=-1) {
  3067.         fp=fdopen(file,"rb");
  3068.         total_ques++;
  3069.         if((que[i]=(questionnaire_t *)MALLOC(sizeof(questionnaire_t)))==NULL) {
  3070.             bprintf("Can't malloc questionnaires!\r\n");
  3071.             exit(1); }
  3072.         sprintf(que[i]->name,"%.8s",name);
  3073.         sprintf(que[i]->desc,"%.25s",desc);
  3074.         que[i]->req_age=atoi(tmp);
  3075.         fgets(str,128,fp);
  3076.         que[i]->total_ques=atoi(str);
  3077.         if(que[i]->total_ques<1 || que[i]->total_ques>20) {
  3078.             bprintf("Invalid number of questions (%d) in questionnaire #%d\r\n"
  3079.                 ,que[i]->total_ques,i+1);
  3080.             exit(1); }
  3081.         for(j=0;j<que[i]->total_ques;j++) {
  3082.             if(!fgets(str,128,fp))
  3083.                 break;
  3084.             truncsp(str);
  3085.             if(!str[0])
  3086.                 break;
  3087.             str[80]=0;
  3088.             strcpy(que[i]->que[j].txt,str);
  3089.             fgets(str,128,fp);
  3090.             que[i]->que[j].answers=atoi(str);
  3091.             if(que[i]->que[j].answers<1 || que[i]->que[j].answers>16) {
  3092.                 bprintf("Invalid number of answers (%d) in question #%d "
  3093.                     "of questionnaire #%d\r\n"
  3094.                     ,que[i]->que[j].answers,j+1,i+1);
  3095.                 exit(1); }
  3096.             fgets(str,128,fp);
  3097.             que[i]->que[j].allowed=atoi(str);
  3098.             for(k=0;k<que[i]->que[j].answers;k++) {
  3099.                 if(!fgets(str,128,fp))
  3100.                     break;
  3101.                 truncsp(str);
  3102.                 if(!str[0])
  3103.                     break;
  3104.                 str[60]=0;
  3105.                 strcpy(que[i]->que[j].ans[k],str); }
  3106.             que[i]->que[j].answers=k; }
  3107.  
  3108.         que[i]->total_ques=j; }
  3109.     fclose(fp);
  3110.     i++; }
  3111. fclose(que_lst);
  3112.  
  3113. lncntr=0;
  3114. getsmsg(user_number);
  3115. if(lncntr)
  3116.     pause();
  3117.  
  3118. memset(&useron,0,sizeof(user_t));
  3119.  
  3120. atexit(smm_exit);
  3121.  
  3122. bputs("\1n\1hSearching for your profile...");
  3123. rewind(index);
  3124. while(!feof(index)) {
  3125.     if(!fread(&ixb,sizeof(ixb_t),1,index))
  3126.         break;
  3127.     if(ixb.system==system_crc && ixb.number==user_number) {
  3128.         useron_record=(ftell(index)-sizeof(ixb_t))/sizeof(ixb_t);
  3129.         fseek(stream,useron_record*sizeof(user_t),SEEK_SET);
  3130.         fread(&user,sizeof(user_t),1,stream);
  3131.         if(stricmp(user.realname,user_name)) {    /* new name, so delete it */
  3132.             user.misc|=USER_DELETED;
  3133.             fseek(stream,ftell(stream)-sizeof(user_t),SEEK_SET);
  3134.             fwrite(&user,sizeof(user_t),1,stream);
  3135.             fseek(stream,0,SEEK_CUR);
  3136.             fseek(index,ftell(index)-sizeof(ixb_t),SEEK_SET);
  3137.             ixb.number=0;
  3138.             fwrite(&ixb,sizeof(ixb_t),1,index);
  3139.             sprintf(str,"%04u.MSG",user_number);
  3140.             remove(str);
  3141.             continue; }
  3142.         useron=user;        /* name matches, same user */
  3143.         break; } }
  3144. fflush(stream);
  3145. fflush(index);
  3146. CRLF;
  3147.  
  3148. if(useron.number && useron.sex!='M' && useron.sex!='F') {
  3149.     if(yesno("Are you of male gender"))
  3150.         useron.sex='M';
  3151.     else
  3152.         useron.sex='F';
  3153.     write_user();
  3154.     user_sex=useron.sex; }
  3155.  
  3156. if(!useron.number && user_sex!='M' && user_sex!='F' && can_add()) {
  3157.     if(yesno("Are you of male gender"))
  3158.         user_sex='M';
  3159.     else
  3160.         user_sex='F'; }
  3161.  
  3162. if(!useron.number && can_add()) {
  3163.     sprintf(str,"%04u.MSG",user_number);
  3164.     remove(str);
  3165.     printfile("SMM_LOGO.ASC");
  3166.     if(yesno("\r\nYour profile doesn't exist. Create it now"))
  3167.         add_userinfo(); }
  3168.  
  3169. if(gotoname[0]) {
  3170.     strupr(gotoname);
  3171.     name_crc=crc32(gotoname);
  3172.     rewind(index);
  3173.     i=0;
  3174.     while(!feof(index)) {
  3175.         if(!fread(&ixb,sizeof(ixb_t),1,index))
  3176.             break;
  3177.         if(!ixb.number)    /* DELETED */
  3178.             continue;
  3179.         if(ixb.name!=name_crc)
  3180.             continue;
  3181.         fseek(stream
  3182.             ,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
  3183.             *sizeof(user_t),SEEK_SET);
  3184.         if(!fread(&user,sizeof(user_t),1,stream))
  3185.             continue;
  3186.         if(minor_protection(user))
  3187.             continue;
  3188.         i=1;
  3189.         if(!long_user_info(user))
  3190.             break; }
  3191.     if(!i) {
  3192.         bprintf("\r\n\1n\1h%s \1rnot found.\r\n",gotoname);
  3193.         pause(); }
  3194.     return; }
  3195.  
  3196. /*********************************************/
  3197. /* ALL User Messages (from Digital Dynamics) */
  3198. /*********************************************/
  3199. for(i=findfirst("ALL*.MSG",&ff,0);!i;i=findnext(&ff)) {
  3200.     if((j=nopen(ff.ff_name,O_RDONLY))==-1) {
  3201.         bprintf("\1n\1r\1hCan't open \1w%s\r\n",ff.ff_name);
  3202.         pause();
  3203.         continue; }
  3204.     if((fp=fdopen(j,"rb"))==NULL) {
  3205.         bprintf("\1n\1r\1hCan't fdopen \1w%s\r\n",ff.ff_name);
  3206.         pause();
  3207.         continue; }
  3208.     str[0]=0;
  3209.     fgets(str,128,fp);
  3210.     truncsp(str);
  3211.     ul=ahtoul(str);    /* Expiration date */
  3212.     ul^=0x305F6C81UL;
  3213.     attr(LIGHTGRAY);
  3214.     cls();
  3215.     while(!feof(fp)) {
  3216.         if(!fgets(str,128,fp))
  3217.             break;
  3218.         bputs(str); }
  3219.     fclose(fp);
  3220.     CRLF;
  3221.     if(ul<=time(NULL))
  3222.         remove(ff.ff_name); }
  3223.  
  3224. /**************************************************/
  3225. /* One-time User Messages (from Digital Dynamics) */
  3226. /**************************************************/
  3227. for(i=findfirst("ONE*.MSG",&ff,0);!i;i=findnext(&ff)) {
  3228.     if(fdate_dir(ff.ff_name)<useron.lastin)
  3229.         continue;
  3230.     if((j=nopen(ff.ff_name,O_RDONLY))==-1) {
  3231.         bprintf("\1n\1r\1hCan't open \1w%s\r\n",ff.ff_name);
  3232.         pause();
  3233.         continue; }
  3234.     if((fp=fdopen(j,"rb"))==NULL) {
  3235.         bprintf("\1n\1r\1hCan't fdopen \1w%s\r\n",ff.ff_name);
  3236.         pause();
  3237.         continue; }
  3238.     str[0]=0;
  3239.     fgets(str,128,fp);
  3240.     truncsp(str);
  3241.     ul=ahtoul(str);    /* Expiration date */
  3242.     ul^=0x305F6C81UL;
  3243.     attr(LIGHTGRAY);
  3244.     cls();
  3245.     while(!feof(fp)) {
  3246.         if(!fgets(str,128,fp))
  3247.             break;
  3248.         bputs(str); }
  3249.     fclose(fp);
  3250.     CRLF;
  3251.     if(ul<=time(NULL))
  3252.         remove(ff.ff_name); }
  3253.  
  3254. /******************************************/
  3255. /* Sysop Messages (from Digital Dynamics) */
  3256. /******************************************/
  3257. for(i=findfirst("SYS*.MSG",&ff,0);SYSOP && !i;i=findnext(&ff)) {
  3258.     if((j=nopen(ff.ff_name,O_RDONLY))==-1) {
  3259.         bprintf("\1n\1r\1hCan't open \1w%s\r\n",ff.ff_name);
  3260.         pause();
  3261.         continue; }
  3262.     if((fp=fdopen(j,"rb"))==NULL) {
  3263.         bprintf("\1n\1r\1hCan't fdopen \1w%s\r\n",ff.ff_name);
  3264.         pause();
  3265.         continue; }
  3266.     str[0]=0;
  3267.     fgets(str,128,fp);
  3268.     truncsp(str);
  3269.     ul=ahtoul(str);    /* Expiration date */
  3270.     ul^=0x305F6C81UL;
  3271.     attr(LIGHTGRAY);
  3272.     cls();
  3273.     while(!feof(fp)) {
  3274.         if(!fgets(str,128,fp))
  3275.             break;
  3276.         bputs(str); }
  3277.     fclose(fp);
  3278.     CRLF;
  3279.     if(ul<=time(NULL) || !noyes("Delete message"))
  3280.         remove(ff.ff_name); }
  3281.  
  3282. statusline();
  3283. while(1) {
  3284.     checkline();
  3285.     aborted=0;
  3286.     attr(LIGHTGRAY);
  3287.     cls();
  3288.  
  3289.     bprintf("\1n  \1b\1hSynchronet \1cMatch Maker  \1bv%s (XSDK v%s)  "
  3290.         "Developed 1995-1997 Rob Swindell\1n\r\n\r\n",SMM_VER,xsdk_ver);
  3291.     printfile("SMM_LOGO.ASC");
  3292.     CRLF;
  3293.  
  3294.     l=filelength(fileno(stream));
  3295.     if(l<0) l=0;
  3296.     sprintf(str,"\1n\1cThere are \1h%lu\1n\1c entries in the user profile "
  3297.         "database.\r\n",l/(long)sizeof(user_t));
  3298.     center(str);
  3299.  
  3300.     sprintf(str,"%04u.MSG",user_number);
  3301.     if(fexist(str))
  3302.         center("\1h\1mYou have awaiting telegrams!\r\n");
  3303.  
  3304.     if(flength("WALL.DAB")>0)
  3305.         center("\1h\1cThere is writing on the Wall.\r\n");
  3306.  
  3307.     if(!useron.number)
  3308.         center("\1h\1rYou have not yet created a profile!\r\n");
  3309.  
  3310.     printfile("SMM_MAIN.ASC");
  3311.  
  3312.     nodesync();             /* Display any waiting messages */
  3313.  
  3314.     bprintf("\r\n%32s\1b\1hWhich or [\1wQ\1b]uit: \1h\1w",nulstr);
  3315.     ch=getkey(K_UPPER);
  3316. //      bprintf("%c\r\n",ch);
  3317.     bputs("\r\1>");
  3318.     switch(ch) {
  3319.         case '?':
  3320.             break;
  3321.         case '*':
  3322.             if(!SYSOP)
  3323.                 break;
  3324.             bputs("\1n\1hSearching...");
  3325.             rewind(stream);
  3326.             while(!feof(stream) && !aborted) {
  3327.                 if(!fread(&user,sizeof(user_t),1,stream))
  3328.                     break;
  3329.                 if(user.misc&USER_DELETED) {
  3330.                     sprintf(str,"\r\nUndelete \1c%s \1b(\1c%s@%s\1b)"
  3331.                         ,user.name,user.realname,user.system);
  3332.                     if(!yesno(str))
  3333.                         continue;
  3334.                     fseek(stream,ftell(stream)-sizeof(user_t),SEEK_SET);
  3335.                     user.misc&=~USER_DELETED;
  3336.                     fwrite(&user,sizeof(user_t),1,stream);
  3337.                     fseek(stream,0,SEEK_CUR);
  3338.                     fseek(index
  3339.                         ,((ftell(stream)-sizeof(user_t))/sizeof(user_t))
  3340.                         *sizeof(ixb_t),SEEK_SET);
  3341.                     strcpy(str,user.name);
  3342.                     strupr(str);
  3343.                     ixb.name=crc32(str);
  3344.                     sprintf(str,"%.25s",user.system);
  3345.                     strupr(str);
  3346.                     ixb.system=crc32(str);
  3347.                     ixb.updated=user.updated;
  3348.                     ixb.number=user.number;
  3349.                     fwrite(&ixb,sizeof(ixb_t),1,index);
  3350.                     } }
  3351.             fflush(stream);
  3352.             fflush(index);
  3353.             break;
  3354.         case '!':
  3355.             if(!SYSOP)
  3356.                 break;
  3357.             cls();
  3358.             bputs("\1n\1hSystems Participating in Your Database:\r\n\r\n\1m");
  3359.             crc_lst=NULL;
  3360.             j=0;
  3361.             rewind(stream);
  3362.             while(!feof(stream) && !aborted) {
  3363.                 if(!fread(&user,sizeof(user_t),1,stream))
  3364.                     break;
  3365.                 if(user.misc&USER_DELETED || !(user.misc&USER_FROMSMB))
  3366.                     continue;
  3367.                 if(!smm_pause)
  3368.                     lncntr=0;
  3369.                 sprintf(str,"%.25s",user.system);
  3370.                 strupr(str);
  3371.                 sys_crc=crc32(str);
  3372.                 for(i=0;i<j;i++)
  3373.                     if(sys_crc==crc_lst[i])
  3374.                         break;
  3375.                 if(i==j) {
  3376.                     crc_lst=REALLOC(crc_lst,(j+1)*sizeof(ulong));
  3377.                     if(crc_lst==NULL) {
  3378.                         printf("REALLOC error!\n");
  3379.                         pause();
  3380.                         break; }
  3381.                     crc_lst[j++]=sys_crc;
  3382.                     bprintf("%s\r\n",user.system); } }
  3383.             if(crc_lst)
  3384.                 FREE(crc_lst);
  3385.             if(j)
  3386.                 bprintf("\1n\r\n\1h%u systems listed.\r\n",j);
  3387.             pause();
  3388.             break;
  3389.         case '\\':
  3390.             if(!SYSOP)
  3391.                 break;
  3392.             bprintf("Rebuilding Index...");
  3393.             rewind(stream);
  3394.             rewind(index);
  3395.             while(!feof(stream)) {
  3396.                 if(!fread(&user,sizeof(user_t),1,stream))
  3397.                     break;
  3398.                 if(user.misc&USER_DELETED)
  3399.                     ixb.number=0;
  3400.                 else
  3401.                     ixb.number=user.number;
  3402.                 strupr(user.name);
  3403.                 ixb.name=crc32(user.name);
  3404.                 strupr(user.system);
  3405.                 user.system[25]=0;
  3406.                 ixb.system=crc32(user.system);
  3407.                 ixb.updated=user.updated;
  3408.                 fwrite(&ixb,sizeof(ixb_t),1,index); }
  3409.             break;
  3410.         case 'R':
  3411.             if(useron.number) {
  3412.                 bputs("\1y\1hMinimum match percentage: \1w");
  3413.                 sprintf(str,"%u",useron.min_match);
  3414.                 if(!getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL) || aborted)
  3415.                     break;
  3416.                 useron.min_match=atoi(str);
  3417.                 if(useron.min_match>100)
  3418.                     useron.min_match=100; }
  3419.             rewind(stream);
  3420.             bprintf("\1n\1l\1hSearching...");
  3421.             while(!feof(stream) && !aborted) {
  3422.                 if(!fread(&user,sizeof(user_t),1,stream))
  3423.                     break;
  3424.                 if(user.misc&USER_DELETED)
  3425.                     continue;
  3426.                 if(minor_protection(user))
  3427.                     continue;
  3428.                 if(useron.min_match && useron.number) {
  3429.                     match=total_match(useron,user);
  3430.                     if(match<useron.min_match)
  3431.                         continue; }
  3432.                 if(!long_user_info(user))
  3433.                     break;
  3434.                 if(!smm_pause)
  3435.                     lncntr=0;
  3436.                 bprintf("\1n\1l\1hSearching..."); }
  3437.             break;
  3438.         case 'F':
  3439.             bputs("\1y\1hText to search for: ");
  3440.             if(!getstr(str,25,K_UPPER|K_LINE))
  3441.                 break;
  3442.             ext=yesno("\r\nDisplay extended profiles");
  3443.             cls();
  3444.             if(!smm_pause && !ext)
  3445.                 printfile("LIST_HDR.ASC");
  3446.             rewind(stream);
  3447.             i=0;
  3448.             while(!aborted) {
  3449.                 bprintf("\1n\1l\1hSearching...");
  3450.                 while(!feof(stream) && !aborted) {
  3451.                     if(!fread(&user,sizeof(user_t),1,stream))
  3452.                         break;
  3453.                     if(user.misc&USER_DELETED)
  3454.                         continue;
  3455.                     if(minor_protection(user))
  3456.                         continue;
  3457.                     tmpuser=user;
  3458.                     sprintf(tmp,"%lu",user.number);
  3459.                     strupr(user.name);
  3460.                     strupr(user.realname);
  3461.                     strupr(user.system);
  3462.                     strupr(user.location);
  3463.                     strupr(user.note[0]);
  3464.                     strupr(user.note[1]);
  3465.                     strupr(user.note[2]);
  3466.                     strupr(user.note[3]);
  3467.                     strupr(user.note[4]);
  3468.                     if(strstr(user.name,str)
  3469.                         || strstr(user.location,str)
  3470.                         || strstr(user.mbtype,str)
  3471.                         || strstr(user.note[0],str)
  3472.                         || strstr(user.note[1],str)
  3473.                         || strstr(user.note[2],str)
  3474.                         || strstr(user.note[3],str)
  3475.                         || strstr(user.note[4],str)
  3476.                         || (SYSOP && strstr(user.realname,str))
  3477.                         || (SYSOP && strstr(user.system,str))
  3478.                         || (SYSOP && !strcmp(tmp,str))
  3479.                         ) {
  3480.                         i=1;
  3481.                         if(ext && !long_user_info(tmpuser))
  3482.                             break;
  3483.                         if(!ext && short_user_info(tmpuser)==0)
  3484.                             break;
  3485.                         if(!smm_pause)
  3486.                             lncntr=0; } }
  3487.                 if(aborted || ext || !lncntr)
  3488.                     break;
  3489.                 user.number=0;
  3490.                 if(short_user_info(user)>=0)
  3491.                     break; }
  3492.             if(!i)
  3493.                 bprintf("\r\n\1n\1h%s \1rnot found.\r\n",str);
  3494.             break;
  3495.         case 'G':
  3496.             bputs("\1y\1hUser name: ");
  3497.             if(!getstr(str,25,K_UPPER|K_LINE))
  3498.                 break;
  3499.             truncsp(str);
  3500.             name_crc=crc32(str);
  3501.             rewind(index);
  3502.             i=0;
  3503.             while(!feof(index)) {
  3504.                 if(!fread(&ixb,sizeof(ixb_t),1,index))
  3505.                     break;
  3506.                 if(!ixb.number)    /* DELETED */
  3507.                     continue;
  3508.                 if(ixb.name!=name_crc)
  3509.                     continue;
  3510.                 fseek(stream
  3511.                     ,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
  3512.                     *sizeof(user_t),SEEK_SET);
  3513.                 if(!fread(&user,sizeof(user_t),1,stream))
  3514.                     continue;
  3515.                 if(minor_protection(user))
  3516.                     continue;
  3517.                 i=1;
  3518.                 if(!long_user_info(user))
  3519.                     break; }
  3520.             if(!i)
  3521.                 bprintf("\r\n\1n\1h%s \1rnot found.\r\n",str);
  3522.             break;
  3523.         case 'L':
  3524.             if(useron.number) {
  3525.                 bputs("\1y\1hMinimum match percentage: \1w");
  3526.                 sprintf(str,"%u",useron.min_match);
  3527.                 if(!getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL) || aborted)
  3528.                     break;
  3529.                 useron.min_match=atoi(str);
  3530.                 if(useron.min_match>100)
  3531.                     useron.min_match=100; }
  3532.             cls();
  3533.             if(!smm_pause)
  3534.                 printfile("LIST_HDR.ASC");
  3535.             rewind(stream);
  3536.             while(!aborted) {
  3537.                 while(!feof(stream) && !aborted) {
  3538.                     if(!fread(&user,sizeof(user_t),1,stream))
  3539.                         break;
  3540.                     if(user.misc&USER_DELETED)
  3541.                         continue;
  3542.                     if(minor_protection(user))
  3543.                         continue;
  3544.                     if(useron.min_match && useron.number) {
  3545.                         match=total_match(useron,user);
  3546.                         if(match<useron.min_match)
  3547.                             continue; }
  3548.                     if(!short_user_info(user))
  3549.                         break;
  3550.                     if(!smm_pause)
  3551.                         lncntr=0; }
  3552.                 if(aborted || !lncntr)
  3553.                     break;
  3554.                 user.number=0;
  3555.                 if(short_user_info(user)>=0)
  3556.                     break; }
  3557.             break;
  3558.  
  3559.         case 'N':
  3560.             while(1) {
  3561.                 checkline();
  3562.                 bputs("\1y\1hLast update (MM/DD/YY): ");
  3563.                 if(useron.number)
  3564.                     unixtodstr(useron.lastin,str);
  3565.                 else
  3566.                     str[0]=0;
  3567.                 if(!getstr(str,8,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
  3568.                     break;
  3569.                 if(isdigit(str[0]) && isdigit(str[1]) && str[2]=='/'
  3570.                     && isdigit(str[3]) && isdigit(str[4]) && str[5]=='/'
  3571.                     && isdigit(str[6]) && isdigit(str[7]))
  3572.                     break;
  3573.                 bputs("\r\n\1h\1rInvalid date!\r\n\r\n"); }
  3574.             if(!str[0] || aborted)
  3575.                 break;
  3576.             l=dstrtounix(str);
  3577.             if(useron.number) {
  3578.                 bputs("\1y\1h\r\nMinimum match percentage: \1w");
  3579.                 sprintf(str,"%u",useron.min_match);
  3580.                 if(!getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL) || aborted)
  3581.                     break;
  3582.                 useron.min_match=atoi(str);
  3583.                 if(useron.min_match>100)
  3584.                     useron.min_match=100; }
  3585.             ext=!noyes("\r\nDisplay extended profiles");
  3586.             if(aborted)
  3587.                 break;
  3588.             cls();
  3589.             if(!ext && !smm_pause)
  3590.                 printfile("LIST_HDR.ASC");
  3591.             rewind(index);
  3592.             while(!aborted) {
  3593.                 while(!feof(index) && !aborted) {
  3594.                     if(!smm_pause)
  3595.                         lncntr=0;
  3596.                     if(!fread(&ixb,sizeof(ixb_t),1,index))
  3597.                         break;
  3598.                     if(!ixb.number)     /* DELETED */
  3599.                         continue;
  3600.                     if(ixb.updated>=l) {
  3601.                         fseek(stream
  3602.                             ,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
  3603.                             *sizeof(user_t),SEEK_SET);
  3604.                         if(!fread(&user,sizeof(user_t),1,stream))
  3605.                             continue;
  3606.                         if(minor_protection(user))
  3607.                             continue;
  3608.                         if(useron.min_match && useron.number) {
  3609.                             match=total_match(useron,user);
  3610.                             if(match<useron.min_match)
  3611.                                 continue; }
  3612.                         if(ext && !long_user_info(user))
  3613.                             break;
  3614.                         if(!ext && short_user_info(user)==0)
  3615.                             break;
  3616.                         continue; } }
  3617.                 if(aborted || ext || !lncntr)
  3618.                     break;
  3619.                 user.number=0;
  3620.                 if(short_user_info(user)>=0)
  3621.                     break; }
  3622.             break;
  3623.  
  3624.         case 'U':
  3625.         case 'W':       /* Create/Edit Profile */
  3626.             if(!can_add()) {
  3627.                 bprintf("\1h\1rYou have insufficient access to create a "
  3628.                     "profile.\r\n\r\n");
  3629.                 break; }
  3630.  
  3631.             if(!useron.number) {
  3632.                 add_userinfo();
  3633.                 break; }
  3634.  
  3635.             user=useron;
  3636.             tleft=timeleft;
  3637.             if(!get_user_info(&user)) {
  3638.                 timeleft=tleft;
  3639.                 break; }
  3640.  
  3641.             if(!memcmp(&user,&useron,sizeof(user_t))) {
  3642.                 timeleft=tleft;
  3643.                 break; }
  3644.  
  3645.             if(!yesno("Save changes")) {
  3646.                 timeleft=tleft;
  3647.                 break; }
  3648.             timeleft=tleft;
  3649.             user.updated=time(NULL);
  3650.             useron=user;
  3651.             write_user();
  3652.             break;
  3653.  
  3654.         case 'D':
  3655.             if(SYSOP) {
  3656.                 bputs("Name to Delete: ");
  3657.                 if(useron.number) {
  3658.                     strcpy(str,useron.name);
  3659.                     strupr(str); }
  3660.                 else
  3661.                     str[0]=0;
  3662.                 getstr(str,25,K_UPPER|K_LINE|K_EDIT|K_AUTODEL);
  3663.                 rewind(stream);
  3664.                 while(!feof(stream)) {
  3665.                     if(!fread(&user,sizeof(user_t),1,stream))
  3666.                         break;
  3667.                     strcpy(tmp,user.name);
  3668.                     strupr(tmp);
  3669.                     if(!(user.misc&USER_DELETED) && strstr(tmp,str)) {
  3670.                         sprintf(tmp,"Delete %s (%s@%s)"
  3671.                             ,user.name,user.realname,user.system);
  3672.                         i=noyes(tmp);
  3673.                         if(aborted)
  3674.                             break;
  3675.                         if(i)
  3676.                             continue;
  3677.                         fseek(stream,ftell(stream)-sizeof(user_t),SEEK_SET);
  3678.                         fseek(index
  3679.                             ,((ftell(stream)-sizeof(user_t))/sizeof(user_t))
  3680.                             *sizeof(ixb_t),SEEK_SET);
  3681.                         user.misc|=USER_DELETED;
  3682.                         fwrite(&user,sizeof(user_t),1,stream);
  3683.                         fseek(stream,0,SEEK_CUR);
  3684.                         memset(&ixb,0,sizeof(ixb_t));
  3685.                         fwrite(&ixb,sizeof(ixb_t),1,index);
  3686.                         fflush(stream);
  3687.                         fflush(index);
  3688.                         delphoto(user);
  3689.                         if(user.number==user_number
  3690.                             && !stricmp(user.system,system_name))
  3691.                             useron.number=0;
  3692.                         break; } }
  3693.                 if(aborted)
  3694.                     break;
  3695.                 break; }
  3696.             if(!useron.number) {
  3697.                 bputs("\1h\1rYour profile doesn't exist.\r\n\r\n");
  3698.                 break; }
  3699.             if(noyes("Are you sure you want to delete your profile"))
  3700.                 break;
  3701.             if(!cdt_warning(-profile_cdt))
  3702.                 break;
  3703.             sprintf(str,"%04u.MSG",user_number);
  3704.             remove(str);
  3705.             fseek(stream,useron_record*sizeof(user_t),SEEK_SET);
  3706.             useron.misc|=USER_DELETED;
  3707.             fwrite(&useron,sizeof(user_t),1,stream);
  3708.             fflush(stream);
  3709.             memset(&ixb,0,sizeof(ixb_t));
  3710.             fseek(index,useron_record*sizeof(ixb_t),SEEK_SET);
  3711.             fwrite(&ixb,sizeof(ixb_t),1,index);
  3712.             fflush(index);
  3713.             delphoto(user);
  3714.             useron.number=0;
  3715.             aborted=0;
  3716.             bputs("\r\n\1h\1r\1iProfile deleted.\r\n");
  3717.             adjust_cdt(-profile_cdt);
  3718.             break;
  3719.         case 'P':
  3720.             smm_pause=!smm_pause;
  3721.             bprintf("\1r\1hScreen pause is now \1w%s\r\n\r\n"
  3722.                 ,smm_pause ? "ON":"OFF");
  3723.             break;
  3724.         case 'M':
  3725.             mbtype_desc(useron.mbtype);
  3726.             break;
  3727.         case 'H':
  3728.             cls();
  3729.             printfile("SMM_HELP.ASC");
  3730.             break;
  3731.         case 'O':
  3732.             if(noyes("Hang-up now"))
  3733.                 break;
  3734.             dtr(5);
  3735.             if(node_dir) {
  3736.                 sprintf(str,"%sHANGUP.NOW",node_dir);
  3737.                 fopen(str,"wb");
  3738.                 nodesync(); }
  3739.             return;
  3740.         case 'S':
  3741.             bputs("\1y\1hUser name: ");
  3742.             if(!getstr(str,25,K_UPPER|K_LINE))
  3743.                 break;
  3744.             truncsp(str);
  3745.             name_crc=crc32(str);
  3746.             rewind(index);
  3747.             i=0;
  3748.             while(!feof(index)) {
  3749.                 if(!fread(&ixb,sizeof(ixb_t),1,index))
  3750.                     break;
  3751.                 if(!ixb.number)    /* DELETED */
  3752.                     continue;
  3753.                 if(ixb.name!=name_crc)
  3754.                     continue;
  3755.                 fseek(stream
  3756.                     ,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
  3757.                     *sizeof(user_t),SEEK_SET);
  3758.                 if(!fread(&user,sizeof(user_t),1,stream))
  3759.                     continue;
  3760.                 if(minor_protection(user))
  3761.                     continue;
  3762.                 i=1;
  3763.                 if(send_telegram(user))
  3764.                     break; }
  3765.             if(!i)
  3766.                 bprintf("\r\n\1n\1h%s \1rnot found.\r\n",str);
  3767.             break;
  3768.         case 'T':
  3769.             sprintf(str,"%04u.MSG",user_number);
  3770.             if(!fexist(str)) {
  3771.                 bputs("\1r\1hYou have no telegrams waiting.\r\n\r\n");
  3772.                 break; }
  3773.             cls();
  3774.             printfile(str);
  3775.             if(noyes("\r\nDelete all telegrams waiting for you"))
  3776.                 break;
  3777.             remove(str);
  3778.             break;
  3779.         case 'V':   /* Visit the wall */
  3780.             if(getage(user_birth)<wall_age && !SYSOP) {
  3781.                 bputs("\1r\1hSorry, you're too young to view the wall.\r\n");
  3782.                 pause();
  3783.                 break; }
  3784.             while(1) {
  3785.                 checkline();
  3786.                 bputs("\1y\1hView writing since (MM/DD/YY): ");
  3787.                 if(useron.number)
  3788.                     unixtodstr(useron.lastin,str);
  3789.                 else
  3790.                     str[0]=0;
  3791.                 if(!getstr(str,8,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
  3792.                     break;
  3793.                 if(isdigit(str[0]) && isdigit(str[1]) && str[2]=='/'
  3794.                     && isdigit(str[3]) && isdigit(str[4]) && str[5]=='/'
  3795.                     && isdigit(str[6]) && isdigit(str[7]))
  3796.                     break;
  3797.                 bputs("\r\n\1h\1rInvalid date!\r\n\r\n"); }
  3798.             if(aborted)
  3799.                 break;
  3800.             l=dstrtounix(str);
  3801.             ext=yesno("\r\nDisplay extended information when available");
  3802.             if(aborted)
  3803.                 break;
  3804.             strcpy(str,"WALL.DAB");
  3805.             if((file=sopen(str,O_RDWR|O_BINARY|O_CREAT,SH_DENYNO
  3806.                 ,S_IREAD|S_IWRITE))==-1) {
  3807.                 bprintf("\r\nError opening %s\r\n",str);
  3808.                 break; }
  3809.             cls();
  3810.             offset=0L;
  3811.             while(!eof(file) && !aborted) {
  3812.                 if(read(file,&wall,sizeof(wall_t))!=sizeof(wall_t))
  3813.                     break;
  3814.                 if(wall.imported<l)
  3815.                     continue;
  3816.                 strcpy(str,wall.name);
  3817.                 strupr(str);
  3818.                 name_crc=crc32(str);
  3819.                 sprintf(str,"%.25s",wall.system);
  3820.                 strupr(str);
  3821.                 sys_crc=crc32(str);
  3822.                 rewind(index);
  3823.                 i=0;
  3824.                 user.sex=0;
  3825.                 while(ext && !feof(index) && !aborted) {
  3826.                     if(!fread(&ixb,sizeof(ixb_t),1,index))
  3827.                         break;
  3828.                     if(!ixb.number)    /* DELETED */
  3829.                         continue;
  3830.                     if(ixb.name!=name_crc || ixb.system!=sys_crc)
  3831.                         continue;
  3832.                     fseek(stream
  3833.                         ,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
  3834.                         *sizeof(user_t),SEEK_SET);
  3835.                     if(!fread(&user,sizeof(user_t),1,stream))
  3836.                         continue;
  3837.                     if(minor_protection(user))
  3838.                         break;
  3839.                     main_user_info(user);
  3840.                     if(useron.number) {
  3841.                         CRLF;
  3842.                         bprintf("\1h\1mThis user meets your profile "
  3843.                             "preferences:\1w%3u%%            "
  3844.                             ,basic_match(useron,user));
  3845.                         bprintf("\1n\1gCreated: \1h%s\r\n"
  3846.                             ,unixtodstr(user.created,str));
  3847.                         bprintf("\1h\1mYou meet this user's profile "
  3848.                             "preferences:\1w%3u%%            "
  3849.                             ,basic_match(user,useron));
  3850.                         bprintf("\1n\1gUpdated: \1h%s\r\n"
  3851.                             ,unixtodstr(user.updated,str)); }
  3852.  
  3853.                     i=1;
  3854.                     CRLF;
  3855.                     break; }
  3856.                 if(!i) {
  3857.                     if(ext)
  3858.                         cls();
  3859.                     bprintf("\1n\1h%s ",wall.name); }
  3860.                 bprintf("\1n\1h\1cWrote on %s:\r\n"
  3861.                     ,timestr(&wall.written));
  3862.                 for(j=0;j<5;j++) {
  3863.                     if(!wall.text[j][0])
  3864.                         break;
  3865.                     bprintf("\1n\1%c%5s%s\r\n"
  3866.                         ,user.sex=='F'?'m':'g',"",wall.text[j]); }
  3867.                 if(aborted)
  3868.                     break;
  3869.                 if(ext) {
  3870.                     nodesync();
  3871.                     if(i) {
  3872.                         bputs(PrevReadSendQuitOrMore);
  3873.                         ch=getkey(K_UPPER);
  3874.                         if(ch=='R')
  3875.                             long_user_info(user);
  3876.                         if(ch=='S')
  3877.                             send_telegram(user);
  3878.                         if(ch=='R' || ch=='S')  /* Don't move forward */
  3879.                             lseek(file,tell(file)-sizeof(wall_t),SEEK_SET); }
  3880.                     else {
  3881.                         bputs("\r\n\1n\1hProfile not found.\r\n\r\n");
  3882.                         bputs("\1b[\1cP\1b]revious, [\1cQ\1b]uit, "
  3883.                             "or [\1cM\1b]ore: \1c");
  3884.                         ch=getkey(K_UPPER); }
  3885.                     if(ch=='P') {
  3886.                         lseek(file,offset,SEEK_SET);
  3887.                         if(tell(file))
  3888.                             lseek(file,tell(file)-sizeof(wall_t),SEEK_SET);
  3889.                         offset=tell(file);
  3890.                         continue; }
  3891.                     if(ch=='Q') {
  3892.                         cls();
  3893.                         break; }
  3894.                     offset=tell(file); }
  3895.                 else if(lncntr+7>=user_rows || eof(file)) {
  3896.                     lncntr=0;
  3897.                     bputs(PrevReadSendQuitOrMore);
  3898.                     ch=getkey(K_UPPER);
  3899.                     if(ch=='Q')
  3900.                         break;
  3901.                     else if(ch=='S' || ch=='R') {
  3902.                         bprintf("\1n\r\1>\1y\1hUser name: ");
  3903.                         if(getstr(name,25,K_UPPER|K_LINE|K_NOCRLF)) {
  3904.                             truncsp(name);
  3905.                             name_crc=crc32(name);
  3906.                             rewind(index);
  3907.                             i=0;
  3908.                             while(!feof(index)) {
  3909.                                 if(!fread(&ixb,sizeof(ixb_t),1,index))
  3910.                                     break;
  3911.                                 if(!ixb.number)    /* DELETED */
  3912.                                     continue;
  3913.                                 if(ixb.name!=name_crc)
  3914.                                     continue;
  3915.                                 fseek(stream
  3916.                                     ,((ftell(index)
  3917.                                         -sizeof(ixb_t))/sizeof(ixb_t))
  3918.                                     *sizeof(user_t),SEEK_SET);
  3919.                                 if(!fread(&user,sizeof(user_t),1,stream))
  3920.                                     continue;
  3921.                                 if(minor_protection(user))
  3922.                                     continue;
  3923.                                 i=1;
  3924.                                 if(ch=='S' && send_telegram(user))
  3925.                                     break;
  3926.                                 if(ch=='R' && !long_user_info(user))
  3927.                                     break;    }
  3928.                             if(!i)
  3929.                                 bprintf("\r\n\1n\1h%s \1rnot found.\r\n",name);
  3930.                                 }
  3931.                         lseek(file,offset,SEEK_SET); }
  3932.                     else if(ch=='P') {
  3933.                         lseek(file,offset,SEEK_SET);
  3934.                         for(i=0;i<4;i++)
  3935.                             if(tell(file))
  3936.                                 lseek(file,tell(file)-sizeof(wall_t),SEEK_SET);
  3937.                         }
  3938.                     cls();
  3939.                     offset=tell(file); } }
  3940.             cls();
  3941.             if(user_level<wall_level) {
  3942.                 close(file);
  3943.                 bputs("\r\n\1h\1rYou have insufficient access to write on the "
  3944.                     "wall.\r\n");
  3945.                 pause();
  3946.                 break; }
  3947.             if(aborted || noyes("Write on the Wall")) {
  3948.                 close(file);
  3949.                 break; }
  3950.             if(!useron.number) {
  3951.                 bputs("\r\n\1h\1rYou must create a profile first.\r\n");
  3952.                 close(file);
  3953.                 break; }
  3954.             if(!cdt_warning(wall_cdt)) {
  3955.                 close(file);
  3956.                 break; }
  3957.             memset(&wall,0,sizeof(wall_t));
  3958.             strcpy(wall.name,useron.name);
  3959.             strcpy(wall.system,system_name);
  3960.             wall.written=wall.imported=time(NULL);
  3961.             bputs("\1l\1n\1hWriting on the Wall:\r\n\r\n");
  3962.             for(i=0;i<5 && !aborted;i++) {
  3963.                 bprintf("\1n\1h\1%c%u of 5: \1n\1%c"
  3964.                     ,useron.sex=='F'?'m':'g',i+1,useron.sex=='F'?'m':'g');
  3965.                 if(!getstr(wall.text[i],70,i==4 ? K_MSG:K_MSG|K_WRAP))
  3966.                     break;
  3967.                 if(trash(wall.text[i])) {
  3968.                     bprintf("\r\n\1r\1hSorry, you can't use that text."
  3969.                         "\r\n\r\n");
  3970.                     i--;
  3971.                     continue; } }
  3972.             if(!i || aborted || !yesno("\r\nSave")) {
  3973.                 close(file);
  3974.                 break; }
  3975.             lseek(file,0L,SEEK_END);
  3976.             write(file,&wall,sizeof(wall_t));
  3977.             close(file);
  3978.             adjust_cdt(wall_cdt);
  3979.             if(notify_user && notify_user!=user_number) {
  3980.                 sprintf(str,"\1n\1hSMM: \1y%s\1m wrote on the Match Maker "
  3981.                     "Wall\r\n",user_name);
  3982.                 if(node_dir[0])
  3983.                     putsmsg(notify_user,str);
  3984.                 else
  3985.                     puttgram(notify_user,str); }
  3986.             break;
  3987.         case 'Q':
  3988.             return; } }
  3989. }
  3990.  
  3991. /* End of SMM.C */
  3992.