⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 phone.c

📁 话带数据中传真解调程序
💻 C
字号:
#if 0ifdef notdef** Phone ** Copyright 1997-1999 Pavel Machek, distribute under GPL** For doing voice transfers over ltmodem.** Based on minimal forum client.** You dont want to make this setuid, trust me.** Note that this slightly evil file is both Makefile and c source.*What you see here is program called phone. Together with ltmodem andlinmodem programs, it can act as telephone over lucentwinmodem. I.e. you sit down, put headphones and microphone on yourhead, and type ./phone. Then you hear dialing tone so you type "dialmartin". phone looks up martin in your telephone directory and dialsright number. Then you talk (and you can do commands like record/tmp/file.to.record.talk.in), then you quit and machine hangs up.It is not good telephone because theres some non-trivial latency inthere, but it is usable.endifphone:	phone.c	gcc phone.c -g -o phone -lreadline -I/opt/sound/include /usr/lib/libesd.soifndef notdefelse#endif#include "phone.h"char *stralloc( const char *s ){ char *t; strcpy( t = malloc( strlen( s )+1 ), s ); return t; }static voiderr(char *msg){  fprintf(stderr, "\n%s\n", msg);  exit(2);}/* A structure which contains information on the commands this program   can understand. */     typedef struct {  char *name;			/* User printable name of the function. */  Function *func;		/* Function to call to do the job. */  char *doc;			/* Documentation for this function.  */} COMMAND;     COMMAND commands[] = {  { "dial", com_dial, "Initiate call to given number" },  { "?", com_help, "Synonym for `help'" },  { "help", com_help, "Give some help" },  { "quit", com_quit, "Exit program" },  { "record", com_record, "Record conversation to file" },  { "play", com_playback, "Playback file to modem" },  { "stop", com_stop, "Stops playback" },  { (char *)NULL, (Function *)NULL, (char *)NULL }};     /* Forward declarations. */char *stripwhite ();COMMAND *find_command ();     /* Execute a command line. */intexecute_line (char *line){  register int i;  COMMAND *command;  char *word;  /* Isolate the command word. */  i = 0;  while (line[i] && whitespace (line[i]))    i++;  word = line + i;  while (line[i] && !whitespace (line[i]))    i++;  if (line[i])    line[i++] = '\0';  command = find_command (word);  if (!command) {      mprintf ("%s: No such command for phone.\n", word);      return (-1);    }       /* Get argument to command, if any. */  while (whitespace (line[i]))    i++;    word = line + i;       /* Call the function. */  return ((*(command->func)) (word));}     /* Look up NAME as the name of a command, and return a pointer to that        command.  Return a NULL pointer if NAME isn't a command name. */COMMAND *find_command (char *name){  register int i;       for (i = 0; commands[i].name; i++)    if (strcmp (name, commands[i].name) == 0)      return (&commands[i]);       return ((COMMAND *)NULL);}     /* Strip whitespace from the start and end of STRING.  Return a pointer        into STRING. */char *stripwhite (char *string){  register char *s, *t;       for (s = string; whitespace (*s); s++)    ;       if (*s == 0)    return (s);       t = s + strlen (s) - 1;  while (t > s && whitespace (*t))    t--;  *++t = '\0';       return s;}     /* **************************************************************** *//*                                                                  *//*                  Interface to Readline Completion                *//*                                                                  *//* **************************************************************** */     char *command_generator ();char *alias_generator ();char **phone_complete (char *, int, int);struct phonebook {  char *alias, *phone, *rest;  struct phonebook *next;};struct phonebook *book = NULL;     /* Attempt to complete on the contents of TEXT.  START and END bound the        region of rl_line_buffer that contains the word to complete.  TEXT is        the word to complete.  We can use the entire contents of rl_line_buffer        in case we want to do some simple parsing.  Return the array of matches,        or NULL if there aren't any. */char **phone_complete (char *text, int start, int end){  char **matches;       matches = (char **)NULL;       /* If this word is at the start of the line, then it is a command     to complete.  Otherwise it is the name of a file in the current     directory. */  if (start == 0)    return completion_matches (text, command_generator);  return completion_matches (text, alias_generator);}/* Generator function for command completion.  STATE lets us know whether        to start from scratch; without any state (i.e. STATE == 0), then we        start at the top of the list. */char *command_generator (char *text, int state){  static int list_index, len;  char *name;       /* If this is a new word to complete, initialize now.  This includes     saving the length of TEXT for efficiency, and initializing the index     variable to 0. */  if (!state) {    list_index = 0;    len = strlen (text);  }       /* Return the next name which partially matches from the command list. */  while (name = commands[list_index].name) {    list_index++;         if (strncmp (name, text, len) == 0)      return (stralloc(name));  }  /* If no names matched, then return NULL. */  return ((char *)NULL);}char *alias_generator (char *text, int state){  static int len;  static struct phonebook *book_cur = NULL;  char *name;       /* If this is a new word to complete, initialize now.  This includes     saving the length of TEXT for efficiency, and initializing the index     variable to 0. */  if (!state) {    len = strlen (text);    book_cur = book;  }       while (book_cur) {    struct phonebook *cur = book_cur;    book_cur = book_cur->next;    if (strncmp (cur->alias, text, len) == 0)      return (stralloc(cur->alias));  }          /* If no names matched, then return NULL. */  return ((char *)NULL);}     /* Print out help for ARG, or for all of the commands if ARG is        not present. */com_help (char *arg){  int i, printed = 0;       for (i = 0; commands[i].name; i++) {      if (!*arg || (strcmp (arg, commands[i].name) == 0)) {	  mprintf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);	  printed++;	}    }       if (!printed)    {      clear_line();      printf ("No commands match `%s'.  Possibilties are:\n", arg);           for (i = 0; commands[i].name; i++) {	  /* Print in six columns. */	  if (printed == 6) {	      printed = 0;	      printf ("\n");	    }     	  printf ("%s\t", commands[i].name);	  printed++;	}           if (printed)	printf ("\n");      rl_forced_update_display();    }  return (0);}/* Return non-zero if ARG is a valid argument for CALLER, else print   an error message and return zero. */intvalid_argument (char *caller, char *arg){  if (!arg || !*arg)    {      mprintf ("%s: Argument required.\n", caller);      return (0);    }  return (1);}static int soundin, soundout, ccout = -1, modemin, modemout, modemctrl, soundin_orig = -1, lm_out = -1;FILE *mctrl;static voidclear_line(void){  write(1, "\r\033[K", 4);}static voidhandle_sound_input(void){  char buf[512];  static int i = 0;  int num;  num = read(soundin, buf, BUFSIZE);#if 0  if (!(i++%100))    mprintf( "Got %d bytes from sound\n", num );#endif  if (!num) {    close(soundin), close(lm_out), lm_out = -1;    mprintf( "+ Done with dialing or playback\n" );    assert(soundin != soundin_orig);    soundin = soundin_orig;  }  if (write(modemout, buf, num) != num)    printf( "" );	/* Printf here does bad things. */}static voidhandle_modem_input(void){  char buf[512];  int num;  static int i=0;  num = read(modemin, buf, BUFSIZE);#if 0  if (!(i++%100))    mprintf( "Got %d bytes from modem at %d (%m)\n", num, modemin );#endif  if (lm_out != -1)    write(lm_out, buf, num);  write(soundout, buf, num);  if (ccout != -1)    write(ccout, buf, num);}static int	/* 1 .. exit program */process_user_input( unsigned char *line ){  char *s;  /* Remove leading and trailing whitespace from the line.     Then, if there is anything left, add it to the history list     and execute it. */  s = stripwhite (line);    if (*s) {    add_history (s);    execute_line (s);  }  return 0;}static fd_set my_fdset;static intline_mode_hook(void){  int r;  for(;;)    {      FD_ZERO(&my_fdset);      FD_SET(0, &my_fdset);      FD_SET(soundin, &my_fdset);      FD_SET(modemin, &my_fdset);      r = select(50, &my_fdset, NULL, NULL, NULL);      if (r < 0)	err("select() failed");      if (FD_ISSET(soundin, &my_fdset))	handle_sound_input();      if (FD_ISSET(modemin, &my_fdset))	handle_modem_input();      if (FD_ISSET(0, &my_fdset))	return 0;    }}static voidcomm_line_mode(void){  char *z;  rl_readline_name = "phone";  rl_event_hook = line_mode_hook;  for(;;)    {      clear_line();      z = readline("phone> ");      if (!z)	break;      if (*z)	add_history(z);      /*      write( 1, "\033[1A", 4 ); */      clear_line();      if (process_user_input(z))	break;      free(z);    }  putchar('\n');}voidopen_modem(void){  int fildesin[2];  int fildesout[2];  int fildesctrl[2];  int i;    pipe(fildesin);    pipe(fildesout);    pipe(fildesctrl);    printf( "Starting communication with ltmodem\n" );    fflush(stdout); fflush(stderr);    if (!fork()) {      close(0);      dup(fildesin[0]);      close(1);      dup(fildesout[1]);      close(3);      dup(fildesctrl[0]);      close(fildesin[0]);      close(fildesin[1]);      close(fildesout[0]);      close(fildesout[1]);      close(fildesctrl[0]);      close(fildesctrl[1]);      system( "tee /tmp/delme.xmit | ./ltmodem -c 2> /tmp/delme.ltmodem.log | tee /tmp/delme.rec\n" );      exit(0);    }    close(fildesin[0]);    close(fildesout[1]);    close(fildesctrl[0]);    modemout = fildesin[1];    modemin = fildesout[0];    modemctrl = fildesctrl[1];    mctrl = fdopen(modemctrl, "w");    if (!mctrl)      mprintf( "Could not open filedescriptor to file?!\n" );    setvbuf( mctrl, NULL, _IONBF, 0 );    fprintf( mctrl, "offhook\nduplex\n" );}voidopen_lm(char *number){  int fildesin[2];  int fildesout[2];  int i;    pipe(fildesin);    pipe(fildesout);    mprintf( "Starting communication with lm\n" );    fflush(stdout); fflush(stderr);    if (!fork()) {      char buf[10240];      close(fildesin[1]);      close(fildesout[0]);      sprintf(buf, "lm '-d%s' '-ccat > /proc/self/fd/%d | cat /proc/self/fd/%d'", number, fildesout[1], fildesin[0] );      system(buf);      exit(0);    }    close(fildesin[0]);    close(fildesout[1]);    lm_out = fildesin[1];    soundin = fildesout[0];}intcom_dial(char *arg){  struct phonebook *cur = book;  mprintf( "# I should call someone...\n" );  while (cur) {    if (!cur->alias)      continue;    if (!strcmp(arg, cur->alias)) {      if (!cur->phone)	continue;      arg = cur->phone;      mprintf( "Dialing %s (%s)\n", cur->alias, cur->phone );      break;    }    cur=cur->next;  }  open_lm(arg);  mprintf( "# Ok, what state are we in now?\n" );  return 0;}intcom_record(char *s){  ccout = open(s, O_WRONLY | O_CREAT, 0600);  if (ccout == -1) {    mprintf( "- Could not open record file: %m\n" );  } else    mprintf( "+ Ok, now recording to %s\n", s );  return 0;}intcom_playback(char *s){  if (soundin != soundin_orig) {    mprintf( "- You are currently dialing or playing other file, are you?\n" );    return 0;  }  soundin = open(s, O_RDONLY);  if (soundin == -1) {    mprintf( "- Could not open playback file: %m\n" );  } else    mprintf( "+ Ok, now playing back from %s\n", s );  return 0;}intcom_stop(char *s){  if (soundin == soundin_orig) {    mprintf( "- You are stopping when nothing is being played?\n" );    return 0;  }  close(soundin);  soundin = soundin_orig;}intcom_quit(char *arg){  fprintf(mctrl, "onhook\nquit\n");  exit(0);}voidparse_phonebook(void){  char *s, buf[10240];  FILE *phonebook;  phonebook = popen("cat ~/.phonebook | sed 's/\t\\+/:/g'", "r");  if (!phonebook) {    printf( "# ~/.phonebook not found, you can use only numbers\n" );    return;  }  while( fgets(buf, 10235, phonebook) ) {    struct phonebook *entry = malloc(sizeof(struct phonebook));    s = strdup(buf);    entry->alias = entry->phone = entry->rest = NULL;    entry->alias = s;    entry->phone = strchr(entry->alias, ':');    if (!entry->phone)      goto got_one;    *entry->phone++ = 0;    entry->rest = strchr(entry->phone, ':');    if (!entry->rest)      goto got_one;    *entry->rest++ = 0;  got_one:    //    printf( "Got one entry %s:%s:%s\n", entry->alias, entry->phone, entry->rest );    entry->next = book;    book = entry;  }}intmain(int argc, char **argv){  int i;  signal(SIGPIPE, SIG_IGN);  setvbuf( stdout, NULL, _IONBF, 0 );  if (!close(3))    printf( "Are you running me under gdb?!\n" );  if (3 != open("/dev/null", O_RDONLY))    printf( "Could not get fd #3\n" );  printf( "SWVERSION Phone " VERSION ", (c) 1999 Pavel Machek (GPL), type help for help\n" );  parse_phonebook();  rl_attempted_completion_function = (CPPFunction *)phone_complete;  for( i=1; i<argc; i++ ) {      if (*argv[i] != '-') { 	call_who = argv[i];       } else	{		  switch (argv[i][1]) {	  case 'd':	    sound_device=argv[i]+2;	    break;	  case 'h':	  default:	    printf( "\nUsage: %s [-d device] [-n nick] [user@site]\n"		    "       -h this help\n"		    , argv[0] );	    exit( 0 );	  }	}    }#if 1  open_modem();  printf( "Modem device opened at %d,%d\n", modemin, modemout );#else  modemin = modemout = 59;#endif  signal(SIGPIPE, SIG_IGN);  soundin_orig = soundin = esd_record_stream(ESD_BITS16 | ESD_MONO | ESD_RECORD | ESD_STREAM, 8000, NULL, NULL);  soundout = esd_play_stream(ESD_BITS16 | ESD_MONO | ESD_PLAY | ESD_STREAM, 8000, NULL, NULL);#if 0  {    //    FILE *pipe = popen("to_ulaw | ssh hobit 'cat | cat > /dev/audio'", "w");    FILE *pipe = popen("cat > /dev/null", "w");    soundout = pipe->_fileno;  }#endif  if (soundin == -1) {    fprintf(stderr, "- Could not open sound device: %m\n" );    exit(1);  }#if 0  i = AFMT_S16_LE;  if (ioctl(soundin, SNDCTL_DSP_SETFMT, &i)) {    fprintf(stderr, "- Could not set mode to 16bit: %m\n" );    exit(1);  }  i = 0;  if (ioctl(soundin, SNDCTL_DSP_STEREO, &i)) {    fprintf(stderr, "- Could not set mode to mono: %m\n" );    exit(1);  }  i = 4;  if (ioctl(soundin, SNDCTL_DSP_SETFRAGMENT, &i)) {    fprintf(stderr, "- Could not set fragment size: %m\n" );    exit(1);  }#endif  fcntl(modemout, F_SETFL, O_NONBLOCK);  printf( "Sound device opened at %d,%d\n", soundin, soundout );  comm_line_mode();  printf( "Phone exiting.\n" );  exit(0);}#if 0endif#endif 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -