home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_03_04 / 3n04027a < prev    next >
Text File  |  1991-12-27  |  11KB  |  406 lines

  1. /*
  2.  *    EASYFAX.C:  A simple FaxBios demonstration program to
  3.  *                send plain ASCII files as faxes.
  4.  *
  5.  *    Designed to work in both Large AND Small models in MSC 6.00A
  6.  *
  7.  *    cl -W3 -AS -Zp -F 2000 easyfax.c /link /NOE >errs
  8.  */
  9.  
  10.  
  11. /* Standard C and DOS header files */
  12. #include <stdio.h>
  13. #include <dos.h>
  14. #include <process.h>
  15. #include <string.h>
  16. #include <io.h>
  17. #include <ctype.h>
  18. #include <time.h>
  19. #include <conio.h>
  20. #include <fcntl.h>
  21. #include <malloc.h>
  22.  
  23. /* These definitions are required for FaxBios Developer's Kit */
  24. typedef unsigned int       WORD;
  25. typedef unsigned char      BYTE;
  26. typedef long               DWORD;
  27. typedef void far *         POINTER;
  28.  
  29. /* FaxBios Development Kit expects hardcoded path names */
  30. #include "\fax\api\enum\fbenum.h"
  31. #include "\fax\api\struct\fbstruct.h"
  32.  
  33. #include "easyfax.h"  /* My function protos & etc. */
  34. FaxTheFile(char *filename, char *dest_name, FB_STATE *fb_state);
  35.  
  36. main(int argc, char **argv)
  37. {
  38.    BYTE mux;
  39.    WORD err;
  40.    struct PC_LOGIN_REC pc;
  41.    FB_STATE fb_state;
  42.  
  43.    if (argc != 3) {
  44.       printf("Usage:   EASYFAX filename \"destination\"  \n");
  45.       return -1;
  46.       }
  47.  
  48.    if ( (mux = FAXB_Find() ) == 0) {
  49.       printf("Error:   FaxBios not loaded\n");
  50.       return -2;
  51.       }
  52.    printf("Using FaxBios at Multiplex address 0x%2X\n",mux);
  53.  
  54.    if ((err=FAXB_SysLogin(&pc, mux)) != SUCCESS)
  55.       return err;
  56.  
  57.    fb_state.mux_num = mux;
  58.    fb_state.client_id = pc.login.client_id;
  59.    fb_state.retry = INF_RETRY;
  60.  
  61.    printf("Logged into %s FaxBios V%d.%02d\n",pc.login.mfg_id,
  62.       pc.login.api_ver_major, pc.login.api_ver_minor);
  63.  
  64.    /* make sure SEND is possible */
  65.    if (pc.login.FaxBios_cap & ACM_XMIT_BIT)
  66.       FaxTheFile(argv[1], argv[2], &fb_state);
  67.    else
  68.       printf("FaxBios does not allow sending files.\n");
  69.  
  70.    FAXB_SysLogout(&fb_state);
  71.    printf("Logged out of FaxBios\n");
  72.    return SUCCESS;
  73. }
  74.  
  75.  
  76. FaxTheFile(char *filename, char *dest_name, FB_STATE *fb_state)
  77. {
  78.    int err;
  79.    int found = 0;
  80.    struct PDIR_PERSON_REC person;
  81.    struct SYS_FAXAPP_INFO_REC app_info;
  82.    WORD cur_person = 0;
  83.    WORD envelope_id;
  84.    WORD file_support_cap;
  85.    WORD file_type;
  86.    WORD num_persons;
  87.    WORD pdir_handle;
  88.    WORD sched_handle;
  89.  
  90.    if ((err=FAXB_SysGetFaxAppInfo(&app_info, fb_state)) != SUCCESS)
  91.       return err;
  92.  
  93.    if ((err=FAXB_SchedOpen(&sched_handle, fb_state)) != SUCCESS)
  94.       return err;
  95.  
  96.    if ((err=FAXB_GraphGetFileType(filename, &file_type,
  97.          &file_support_cap, fb_state)) != SUCCESS)
  98.       return err;
  99.  
  100.    if (! (file_support_cap & 0x03) ) {
  101.       printf("FaxBios cannot send or convert this file\n");
  102.       return -1;
  103.       }
  104.  
  105.    if ((err=FAXB_SchedAddFile(sched_handle, filename, file_type,
  106.         app_info.def_usrfont_tok, fb_state)) != SUCCESS)
  107.       return err;
  108.  
  109.    if ((err=FAXB_PdirOpen(&pdir_handle, app_info.def_pdir_tok,
  110.         0, &num_persons, fb_state)) != SUCCESS)
  111.       return err;
  112.  
  113.    while ( (!found) && (cur_person < num_persons) ) {
  114.       person.retrieve_by_ndx = 1;
  115.       person.personid_or_ndx = cur_person++;
  116.       FAXB_PdirReadPerson(pdir_handle, &person, fb_state);
  117.       if (stricmp(dest_name, (char *)&person.record.name) == 0) {
  118.          found = 1;
  119.          }
  120.       }
  121.  
  122.    if ((err=FAXB_PdirClose(pdir_handle, fb_state)) != SUCCESS)
  123.       return err;
  124.  
  125.    if (found)
  126.       FAXB_SchedAddDest(sched_handle, &person.record, fb_state);
  127.    else
  128.       {
  129.       printf("Error:  person <%s> not found in phone directory.\n",
  130.          dest_name);
  131.       return -3;
  132.       }
  133.  
  134.    if ((err=FAXB_SchedSetParam(sched_handle, fb_state)) !=
  135.         SUCCESS)
  136.       return err;
  137.  
  138.    if ((err=FAXB_SchedClose(sched_handle, &envelope_id,
  139.          fb_state)) != SUCCESS)
  140.       return err;
  141.  
  142.    return SUCCESS;
  143. }
  144.  
  145. /*
  146.  * This function returns the FaxBios multiplex number.  The code
  147.  * was adapted from a similar function in SENDFAX.C in the FaxBios
  148.  * Developer's Kit.
  149. */
  150.  
  151. BYTE  FAXB_Find()
  152. {
  153. static char far FB_Signature[]="FaxBiosjpc";
  154. BYTE mux_num = 0x80;
  155. char far *FaxBios_ID;
  156. union REGS regs;
  157.  
  158.    do {
  159.       /* Looking for FaxBios Multiplex */
  160.        memset((char *)®s, 0, sizeof(regs));
  161.        regs.h.ah = mux_num;
  162.        int86(MULTIPLEX, ®s, ®s);
  163.  
  164.        /* Check [DX:DI] for signature */
  165.        if ( regs.h.al == 0xFF ) {
  166.            /* needs to be far pointer */
  167.            FaxBios_ID = (char far *)(((long)regs.x.dx << 16) +
  168.               regs.x.di);
  169.  
  170.            if (far_strncmp(FaxBios_ID, FB_Signature,
  171.                   sizeof(FB_Signature)-1) == 0 )
  172.                /* FaxBios was found! */
  173.                return mux_num;
  174.                }
  175.  
  176.        /* FaxBios not found, keep trying */
  177.    } while ( mux_num++ < 0xFF );
  178.  
  179.   return 0;   /* FaxBios was not found */
  180. }
  181.  
  182.  
  183. WORD FAXB_GraphGetFileType(char *filename, WORD *file_type,
  184.     WORD *file_support_cap, FB_STATE *fb_state)
  185. {
  186.    struct GRAPH_FILE_TYPE_REC gr_file_type;
  187.    int err;
  188.  
  189.    strcpy(gr_file_type.fname, filename);
  190.    err = FAXB_Func(GRAPH_GET_FILE_TYPE, &gr_file_type,
  191.       sizeof(struct GRAPH_FILE_TYPE_REC), fb_state);
  192.  
  193.    *file_type = gr_file_type.file_type;
  194.    *file_support_cap = gr_file_type.file_support_cap;
  195.    return err;
  196. }
  197.  
  198.  
  199. WORD FAXB_SysLogin(struct PC_LOGIN_REC *login_info, BYTE mux_num)
  200. {
  201.    FB_STATE fb_state = {mux_num, 0, INF_RETRY};
  202.    return FAXB_Func(SYS_LOGIN, login_info,
  203.      sizeof(struct PC_LOGIN_REC), &fb_state);
  204. }
  205.  
  206. WORD FAXB_SysLogout(FB_STATE *fb_state)
  207. {
  208.    struct SYS_LOGOUT_REC logout_info;
  209.  
  210.    return FAXB_Func(SYS_LOGOUT, &logout_info,
  211.      sizeof(struct SYS_LOGOUT_REC), fb_state);
  212. }
  213.  
  214. WORD FAXB_SysGetFaxAppInfo(struct SYS_FAXAPP_INFO_REC *info,
  215.    FB_STATE *fb_state)
  216. {
  217.    return FAXB_Func(SYS_GET_FAXAPP_INFO, info,
  218.      sizeof(struct SYS_FAXAPP_INFO_REC), fb_state);
  219. }
  220.  
  221.  
  222. WORD FAXB_SchedOpen(WORD *sched_handle, FB_STATE *fb_state)
  223. {
  224.    struct SCHED_OPEN_REC sched_open;
  225.    int err;
  226.  
  227.    err = FAXB_Func(SCHED_OPEN, &sched_open,
  228.       sizeof(struct SCHED_OPEN_REC), fb_state);
  229.    *sched_handle = sched_open.sched_handle;
  230.    return err;
  231. }
  232.  
  233.  
  234. WORD FAXB_SchedClose(WORD sched_handle, WORD *envelope_id,
  235.     FB_STATE *fb_state)
  236. {
  237.    struct SCHED_CLOSE_REC sched_close;
  238.    int err;
  239.  
  240.    sched_close.sched_handle = sched_handle;
  241.    err = FAXB_Func(SCHED_CLOSE, &sched_close,
  242.       sizeof(struct SCHED_CLOSE_REC), fb_state);
  243.    *envelope_id = sched_close.envelope_id;
  244.    return err;
  245. }
  246.  
  247.  
  248. WORD FAXB_SchedSetParam(WORD sched_handle, FB_STATE *fb_state)
  249. {
  250.    struct SCHED_SET_PARAMS_REC sched_param;
  251.  
  252.    memset((char *) &sched_param, 0, sizeof(sched_param));
  253.    sched_param.sched_handle = sched_handle;
  254.    /* time(&sched_param.params.sched_time); */
  255.    return FAXB_Func(SCHED_SET_PARAMS, &sched_param,
  256.      sizeof(struct SCHED_SET_PARAMS_REC), fb_state);
  257. }
  258.  
  259. WORD FAXB_SchedAddFile(WORD sched_handle, char *filename,
  260.     WORD file_type, char* use_font, FB_STATE *fb_state)
  261. {
  262.    struct SCHED_ADD_FILE_REC add;
  263.    int err;
  264.  
  265.    memset((char *) &add, 0, sizeof(add));
  266.    add.sched_handle = sched_handle;
  267.    add.file_info.file_type = file_type;
  268.    if (add.file_info.file_type == TYPE_UNIDENTIFIED)
  269.        add.file_info.file_type = TYPE_ASCII;
  270.  
  271.    strcpy(add.file_info.fname, filename);
  272.    strcpy(add.file_info.conv_params.font_tok, use_font);
  273.    add.file_info.conv_params.resolution = STD_RESOLUTION;
  274.    add.file_info.conv_params.page_length = LEN_US_LETTER;
  275.    add.file_info.conv_params.page_width = WIDTH_A4;
  276.  
  277.    err = FAXB_Func(SCHED_ADD_FILE, &add,
  278.       sizeof(struct SCHED_ADD_FILE_REC), fb_state);
  279.    return err;
  280. }
  281.  
  282.  
  283. WORD FAXB_SchedAddDest(WORD sched_handle,
  284.     struct PDIR_CANONICAL_REC *can_person, FB_STATE *fb_state)
  285. {
  286.    struct DEST_INFO_REC dest_info;
  287.    int err;
  288.  
  289.    memset((char *) &dest_info, 0, sizeof(dest_info));
  290.    dest_info.sched_handle = sched_handle;
  291.    dest_info.pdir = *can_person;
  292.  
  293.    err = FAXB_Func(SCHED_ADD_DEST, &dest_info,
  294.       sizeof(struct DEST_INFO_REC), fb_state);
  295.    return err;
  296. }
  297.  
  298.  
  299. WORD FAXB_PdirOpen(WORD *pdir_handle, char *dir_filename,
  300.     WORD rw_mode, WORD *num_persons, FB_STATE *fb_state)
  301. {
  302.    struct PDIR_OPEN_REC pdir_open;
  303.    int err;
  304.  
  305.    pdir_open.mode = rw_mode;
  306.    pdir_open.sort_tok[0] = '\0';
  307.    strcpy(pdir_open.pdir_tok, dir_filename);
  308.  
  309.    err = FAXB_Func(PDIR_OPEN, &pdir_open,
  310.       sizeof(struct PDIR_OPEN_REC), fb_state);
  311.    *pdir_handle = pdir_open.pdir_handle;
  312.    *num_persons = pdir_open.num_persons;
  313.    return err;
  314. }
  315.  
  316. WORD FAXB_PdirReadPerson(WORD pdir_handle,
  317.    struct PDIR_PERSON_REC *person, FB_STATE *fb_state)
  318. {
  319.    person->pdir_handle = pdir_handle;
  320.    return FAXB_Func(PDIR_READ_PERSON, person,
  321.       sizeof(struct PDIR_PERSON_REC), fb_state);
  322. }
  323.  
  324. WORD FAXB_PdirClose(WORD pdir_handle, FB_STATE *fb_state)
  325. {
  326.    struct PDIR_CLOSE_REC pdir_close;
  327.  
  328.    pdir_close.pdir_handle = pdir_handle;
  329.    return FAXB_Func(PDIR_CLOSE, &pdir_close,
  330.      sizeof(struct PDIR_CLOSE_REC), fb_state);
  331. }
  332.  
  333.  
  334. /*  Retry values for BUSY status:
  335.    -1 == Infinite retry, 0 == No retry, N == Retry "N" times */
  336.  
  337. unsigned int FAXB_Func( int function, void far *rec, int size,
  338.     FB_STATE *fb_state)
  339. {
  340.    union REGS regs;
  341.    int status;
  342.    BYTE mux_num = fb_state->mux_num;
  343.    int my_client_id = fb_state->client_id;
  344.    int retry = fb_state->retry;
  345.  
  346.    /* store rec size twice for overrun testing */
  347.    *((int far *)rec) = size;
  348.    *((int far *)((char far *)rec + size - 2)) = size;
  349.  
  350.     /* All structs, except SYS_LOGIN, need the client_id */
  351.    if ( function != SYS_LOGIN )
  352.        ((struct SYS_LOGOUT_REC far *)rec)->client_id = my_client_id;
  353.  
  354.     /* put the Function number in, always at the same offset */
  355.    ((struct PC_LOGIN_REC far *)rec)->function_num = function;
  356.  
  357.    while (retry) {
  358.       regs.h.ah = mux_num;
  359.       regs.h.al = 0xFB;
  360.       regs.x.bx = function;
  361.       regs.x.dx = FP_SEG(rec);
  362.       regs.x.di = FP_OFF(rec);
  363.       int86(MULTIPLEX, ®s, ®s);
  364.  
  365.       if (*((int far *)rec) ==
  366.           *((int far *)((char far *)rec + size - 2)) ==
  367.               size ) {
  368.           printf("FaxBios has overrun data struct.\n");
  369.           return -4;
  370.           }
  371.  
  372.       if (regs.h.al != 0xFF) {
  373.           printf("FaxBios no longer present.\n");
  374.           return -5;
  375.           }
  376.  
  377.       status = (int) regs.x.cx;
  378.       if ( (function != SYS_LOGOUT) &&
  379.            ( (status == BUSY) || (status == LOCKED) ) ){
  380.          printf("FaxBios BUSY or LOCKED:  retrying\n");
  381.          if (retry > 0)
  382.             retry--;
  383.          }
  384.       else
  385.          retry = 0;     /* successful call */
  386.       }
  387.  
  388.    if (status >= NOT_IMPLEMENTED)
  389.       printf("FaxBios function %02XH failed with status %XH.\n",
  390.          function, status);
  391.    return status;
  392. }
  393.  
  394.  
  395.  
  396. /* Based on the Kernighan & Ritchie algorithm */
  397. int far_strncmp(char far *s, char far *t, int length)
  398. {
  399.    for (; *s == *t; s++, t++)
  400.       if ((*s == '\0') || !(--length))
  401.          return 0;
  402.  
  403.    return *s - *t;
  404. }
  405.  
  406.