home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2 / Openstep-4.2-Intel-User.iso / NextLibrary / PrivateFrameworks / Uucp.framework / Versions / A / Resources / contrib / dialHDB.c < prev    next >
C/C++ Source or Header  |  1994-01-30  |  5KB  |  188 lines

  1. /*
  2. # File:        dialHDB.c
  3. # Author:    Daniel Hagerty , hag@eddie.mit.edu
  4. #        Copyright (C) 1993
  5. # Date:        Fri Nov 26 19:22:31 1993
  6. # Description:    Program for using HDB dialers for dialing modems, exiting
  7.         with 0 on success, else failure.
  8. # Version:    1.0
  9. # Revision History:
  10. ######
  11. ### 11/26/93 Hag - File creation
  12. ######
  13. ### 1/5/94 Hag - Finally got around to finishing this damn thing.
  14. ######
  15. */
  16. /* Basic theory behind this program-
  17.    dialHDB forks into two processes, a monitor parent, and a child
  18.    that does the exec of the dialer. Child pretty much just execs the
  19.    dialer program, unless there's an exec problem, in which case the
  20.    child sends the parent a SIGUSR1 to indicate failed execution.
  21. */
  22.  
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <sys/types.h>
  26. #include <sys/wait.h>
  27. #include <signal.h>
  28.  
  29. #define kUsage    "Usage:\n\t%s dialerPath device number speed\n\
  30. %s dialer -h device speed\n"
  31.  
  32. #define kExitErrFlag    0x80    /* & in with exit code to determine error */
  33. #define kErrorMask    0x0f    /* Mask to determine error code */
  34.  
  35. /* Error code defines as lifted from an HDB dialer */
  36. #define    RCE_NULL    0    /* general purpose or unknown error code */
  37. #define    RCE_INUSE    1    /* line in use */
  38. #define    RCE_SIG        2    /* signal aborted dialer */
  39. #define    RCE_ARGS    3    /* invalid arguments */
  40. #define    RCE_PHNO    4    /* invalid phone number */
  41. #define    RCE_SPEED    5    /* invalid baud rate -or- bad connect baud */
  42. #define    RCE_OPEN    6    /* can't open line */
  43. #define    RCE_IOCTL    7    /* ioctl error */
  44. #define    RCE_TIMOUT    8    /* timeout */
  45. #define    RCE_NOTONE    9    /* no dial tone */
  46. #define    RCE_BUSY    13    /* phone is busy */
  47. #define    RCE_NOCARR    14    /* no carrier */
  48. #define    RCE_ANSWER    15    /* no answer */
  49.  
  50. /* Structure definition to map error codes to strings */
  51. typedef struct
  52. {
  53.   int errNum;
  54.   char *errString;
  55. } errTable;
  56.  
  57. const errTable errors[]=
  58. {
  59.   { RCE_NULL,    "Unknown Error" },
  60.   { RCE_INUSE,    "Line is being used" },
  61.   { RCE_SIG,    "Recieved fatal signal" },
  62.   { RCE_ARGS,    "Bad arguments" },
  63.   { RCE_PHNO,    "Invalid phone number" },
  64.   { RCE_SPEED,    "Invalid baud rate or bad connection" },
  65.   { RCE_OPEN,    "Unable to open line" },
  66.   { RCE_IOCTL,    "ioctl error" },
  67.   { RCE_TIMOUT,    "Timed out" },
  68.   { RCE_NOTONE,    "No dialtone" },
  69.   { RCE_BUSY,    "Phone number is busy" },
  70.   { RCE_NOCARR,    "No carrier" },
  71.   { RCE_ANSWER,    "No answer" },
  72.   { 0,NULL}
  73. };
  74.  
  75. /* Function Prototypes */
  76. int figureStat(int stat);
  77. char *findInTable(int error);
  78. void badExec(void);
  79.  
  80. char *dialerName;        /* basename of our dialer program */
  81. char *dialerPath;        /* full path of dialer program */
  82.  
  83. main(int argc,char *argv[])
  84. {
  85.   int parent;            /* pid of parent process */
  86.   int child;            /* pid of child process */
  87.   int stat;            /* exit status of child process */
  88.   char *temp;            /* used to get basename of dialer */
  89.   
  90.   if(argc!=5)
  91.   {
  92.     fprintf(stderr,kUsage,argv[0],argv[0]);
  93.     exit(1);
  94.   }
  95.  
  96.   dialerPath=argv[1];
  97.   dialerName= (temp=strrchr(argv[1],'/'))!=NULL ? temp+1 : argv[1];
  98.   
  99.   parent=getpid();
  100.   
  101.   signal(SIGUSR1,badExec);    /* set up for possible failed exec */
  102.  
  103.   if((child=fork())<0)
  104.   {
  105.     perror("fork");
  106.     exit(2);
  107.   }
  108.   if(child>0)            /* We're parent, wait for child to exit */
  109.   {
  110.     /* Set up to ignore signals so we can report them on stderror */
  111.     signal(SIGHUP,SIG_IGN);
  112.     signal(SIGINT,SIG_IGN);
  113.     signal(SIGTERM,SIG_IGN);
  114.     
  115.     wait(&stat);        /* wait for child to exit */
  116.     exit(figureStat(stat));    /* figure out our exit code and die */
  117.   }
  118.   else                /* child process */
  119.   {
  120.     close(0);            /* close of modem file desc, since HDB */
  121.     close(1);            /* doesn't use them */
  122.     dup2(2,1);            /* and remap stdout to stderr, just in case */
  123.     if(execvp(argv[1],argv+1)<0) /* exec program with argv shifted by 1 */
  124.     {                /* if exec fails, send SIGUSR1 to parent */
  125.       kill(parent,SIGUSR1);
  126.       exit(0);
  127.     }
  128.   }  
  129.   exit(0);
  130. }
  131.  
  132. /* Figure out whether or not dialer ran succesfully, and return
  133. with 0 if it worked, otherwise error */
  134. int figureStat(int stat)
  135. {
  136.   int exit;
  137.   int errFlag;
  138.   int error;
  139.   
  140.   if(WIFSIGNALED(stat))        /* determine if exit was from signal or what */
  141.   {
  142.     fprintf(stderr,"Error: Dialer %s recieved signal %d.\n",dialerName,
  143.         WTERMSIG(stat));
  144.     return(1);
  145.   }
  146.   if(WIFSTOPPED(stat))
  147.   {
  148.     fprintf(stderr,"Error: Dialer %s recieved signal %d.\n",dialerName,
  149.         WSTOPSIG(stat));
  150.     return(1);
  151.   }
  152.   exit=WEXITSTATUS(stat);
  153.  
  154.   errFlag=exit&kExitErrFlag;    /* Is the error flag set? */
  155.   if(errFlag)
  156.   {
  157.     char *errString;
  158.  
  159.     error=exit&kErrorMask;
  160.     errString=findInTable(error); /* find it's string, print it on stderr */
  161.     fprintf(stderr,"Error: %s - %s.\n",dialerName,errString); /* and return */
  162.     return(1);
  163.   }
  164.   return(0);
  165. }
  166.  
  167. /* Support routine, look up exit code in error table, and return pointer
  168. to proper string */
  169. char *findInTable(int error)
  170. {
  171.   int i=0;
  172.  
  173.   for(i=0;errors[i].errString!=NULL;i++)
  174.   {
  175.     if(errors[i].errNum==error)
  176.       return(errors[i].errString);
  177.   }
  178.   /* Still here, return the top entry, for unknown error */
  179.   return(errors[0].errString);
  180. }
  181.  
  182. /* Called by signal if we recieve SIGUSR 1 */
  183. void badExec(void)
  184. {
  185.   fprintf(stderr,"Error: %s - Execution problem.\n",dialerPath);
  186.   exit(1);
  187. }
  188.