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

📄 scprot.c

📁 VoiFax is a program that manage voice/data/fax modem in the same manner of vgetty and mgetty.VoiFax
💻 C
字号:
/*  voifax scripting protocol interface library *  Copyright (C) 2004  Simone Freddio & Andrea Emanuelli * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <signal.h>#include <sys/types.h>#include "scriptcntl.h"#include "common.h"#include "scprot.h"#include "libevent.h"#include "util.h"/* Local function prototypes */static int search_device(char *dev);void sigpipe_handler(int par);static int handler_device						(int argc, char **argv);static int handler_goodbye					(int argc, char **argv);static int handler_hello						(int argc, char **argv);static int handler_beep							(int argc, char **argv);static int handler_enable_events		(int argc, char **argv);static int handler_disable_events		(int argc, char **argv);static int handler_dial							(int argc, char **argv);static int handler_play							(int argc, char **argv);static int handler_get_tty					(int argc, char **argv);static int handler_get_modem				(int argc, char **argv);static int handler_autostop					(int argc, char **argv);static int handler_record						(int argc, char **argv);static int handler_wait							(int argc, char **argv);static int handler_stop							(int argc, char **argv);static int handler_dtmf							(int argc, char **argv);static int handler_quote						(int argc, char **argv);static int handler_getfax						(int argc, char **argv);static int handler_sendfax					(int argc, char **argv);static t_sp sp;static int events_enabled = false;/* Local data */static t_sp_devdesc sp_devices[SP_DEVICES] =	{ { SD_NODEVICE,													"NO_DEVICE" },		{ SD_DIALUPLINE,												"DIALUP_LINE" },		{ SD_INTERNAL_MICROPHONE,								"INTERNAL_MICROPHONE" },		{	EXTERNAL_MICROPHONE,									"EXTERNAL_MICROPHONE" },		{	INTERNAL_SPEAKER,											"INTERNAL_SPEAKER" },		{	LOCAL_HANDSET,												"LOCAL_HANDSET" },		{	EXTERNAL_SPEAKER,											"EXTERNAL_SPEAKER" },		{	DIALUP_WITH_INT_SPEAKER,							"DIALUP_WITH_INT_SPEAKER" },		{	DIALUP_WITH_EXT_SPEAKER,							"DIALUP_WITH_EXT_SPEAKER" },		{	DIALUP_WITH_INTERNAL_MIC_AND_SPEAKER,	"DIALUP_WITH_INTERNAL_MIC_AND_SPEAKER" },		{	DIALUP_WITH_EXTERNAL_MIC_AND_SPEAKER, "DIALUP_WITH_EXTERNAL_MIC_AND_SPEAKER" },		{	DIALUP_WITH_LOCAL_HANDSET,						"DIALUP_WITH_LOCAL_HANDSET" } };/* Local functions *//***********************//*** SCRIPT HANDLERS ***/static int handler_device(int argc, char **argv){	char module[] = "handler_device";	char trc[200];	int dev;		if (argc != 2)	{		TRC(TRC_ERR, module, "Handler device: Wrong number of parameters");		return false;	}		sprintf(trc, "Device = '%s'", argv[1]);	TRC(TRC_INFO, module, trc);		dev = search_device(argv[1]);	if (dev == -1)	{		TRC(TRC_WARN, module, argv[1]);		TRC(TRC_WARN, module, "Unkown device");		return sc_send(&sp.sc, "DEVICE_NOT_AVAILABLE");	}	sprintf(trc, "Setting device = '%s', '%d'", argv[1], dev);	TRC(TRC_INFO, module, trc);		strcpy(argv[0], SP_EVENT_DEVICE);	sprintf(argv[1], "%d", dev);	return libevent_call_handler(argc, argv);}static int handler_goodbye(int argc, char **argv){	char module[] = "handler_goodbye";	argv = argv;	if (argc != 1)	{		TRC(TRC_ERR, module, "Wrong number of arguments");		return false;	}	TRC(TRC_INFO, module, "Received goodbye, closing connection");	sp.handshake = HANDSHAKE_CLOSED;	return sc_send(&sp.sc, "GOODBYE SHELL");}static int handler_hello(int argc, char **argv){	char module[] = "handler_hello";	argv = argv;	if (argc != 3)	{		TRC(TRC_ERR, module, "Wrong number of arguments");		return false;	}	TRC(TRC_INFO, module, "Initial handshake from script");	sp.handshake = HANDSHAKE_DONE;	return sp_send_ready();}static int handler_beep(int argc, char **argv){	char module[] = "handler_beep";	if (argc > 3)	{		TRC(TRC_ERR, module, "Wrong number of arguments");		return false;	}	TRC(TRC_INFO, module, "Got beep");	strcpy(argv[0], SP_EVENT_BEEP);	return libevent_call_handler(argc, argv);}static int handler_enable_events(int argc, char **argv){	char module[] = "handler_enable_events";	argc = argc; argv = argv;	TRC(TRC_INFO, module, "Enabling events...");		events_enabled = true;	return sp_send_ready();}static int handler_disable_events(int argc, char **argv){	char module[] = "handler_disable_events";	argc = argc; argv = argv;	TRC(TRC_INFO, module, "Disabling events...");	events_enabled = true;		return sp_send_ready();}static int handler_dial(int argc, char **argv){	char module[] = "handler_dial";	char trc[200];	if (argc != 2)	{		TRC(TRC_ERR, module, "Wrong number of arguments");		return false;	}		sprintf(trc, "Dialing '%s'...", argv[1]);	TRC(TRC_INFO, module, trc);	strcpy(argv[0], SP_EVENT_DIAL);	return libevent_call_handler(argc, argv);}static int handler_play(int argc, char **argv){	char module[] = "handler_play";	char trc[200];	switch (argc)	{		case 2:			sprintf(trc, "Playing '%s'...", argv[1]);			TRC(TRC_INFO, module, trc);			break;		case 3:			sprintf(trc, "Playing '%s' '%s'...", argv[1], argv[2]);			TRC(TRC_INFO, module, trc);			break;		default:			TRC(TRC_ERR, module, "Wrong number of arguments");			return false;	}		strcpy(argv[0], SP_EVENT_PLAY);	return libevent_call_handler(argc, argv);}static int handler_get_tty(int argc, char **argv){	char module[] = "handler_get_tty";	TRC(TRC_INFO, module, "Returning dev...");	strcpy(argv[0], SP_EVENT_GET_TTY);	return libevent_call_handler(argc, argv);}static int handler_get_modem(int argc, char **argv){	char module[] = "handler_get_modem";	TRC(TRC_INFO, module, "Returning modem...");	strcpy(argv[0], SP_EVENT_GET_MODEM);	return libevent_call_handler(argc, argv);}static int handler_autostop(int argc, char **argv){	char module[] = "handler_autostop";	char trc[200];	int val = false;	if (argc != 2)	{		TRC(TRC_ERR, module, "Wrong number of arguments");		return false;	}	sprintf(trc, "Received '%s' '%s'.", argv[0], argv[1]);	TRC(TRC_INFO, module, trc);	if (strcmp(argv[1], "ON") == 0)	{		val = true;	}	else if (strcmp(argv[1], "OFF") == 0)	{		val = false;	}	else	{		TRC(TRC_WARN, module, "Bad parameter");		return false;	}	strcpy(argv[0], SP_EVENT_AUTOSTOP);	sprintf(argv[1], "%d", val);	return libevent_call_handler(argc, argv);}static int handler_record(int argc, char **argv){	char module[] = "handler_record";	char trc[200];	if (argc != 2)	{		TRC(TRC_ERR, module, "Wrong number of arguments");		return false;	}		sprintf(trc, "Recording '%s'...", argv[1]);	TRC(TRC_INFO, module, trc);	strcpy(argv[0], SP_EVENT_RECORD);	return libevent_call_handler(argc, argv);}static int handler_wait(int argc, char **argv){	char module[] = "handler_wait";	char trc[200];	if (argc != 2)	{		TRC(TRC_ERR, module, "Wrong number of arguments");		return false;	}	sprintf(trc, "Waiting for '%d'", atoi(argv[1]));	TRC(TRC_INFO, module, trc);		strcpy(argv[0], SP_EVENT_WAIT);	return libevent_call_handler(argc, argv);}static int handler_stop(int argc, char **argv){	char module[] = "handler_stop";	if (argc != 1)	{		TRC(TRC_ERR, module, "Wrong number of arguments");		return false;	}		TRC(TRC_INFO, module, "Stop received");	strcpy(argv[0], SP_EVENT_STOP);	return libevent_call_handler(argc, argv);}static int handler_dtmf(int argc, char **argv){	char module[] = "handler_dtmf";	char trc[200];	if (argc != 2)	{		TRC(TRC_ERR, module, "Wrong number of arguments");		return false;	}	sprintf(trc, "Sending dtmf for '%d'", atoi(argv[1]));	TRC(TRC_INFO, module, trc);		strcpy(argv[0], SP_EVENT_DTMF);	return libevent_call_handler(argc, argv);}static int handler_quote(int argc, char **argv){	char module[] = "handler_quote";	char trc[200];	if (argc != 2)	{		TRC(TRC_ERR, module, "Wrong number of arguments");		return false;	}	sprintf(trc, "Sending raw command '%s'", argv[1]);	TRC(TRC_INFO, module, trc);		strcpy(argv[0], SP_EVENT_QUOTE);	return libevent_call_handler(argc, argv);}static int handler_getfax(int argc, char **argv){	char module[] = "handler_getfax";	char trc[200];	if (argc != 1)	{		TRC(TRC_ERR, module, "Wrong number of arguments");		return false;	}	sprintf(trc, "Receiving fax...");	TRC(TRC_INFO, module, trc);		strcpy(argv[0], SP_EVENT_GETFAX);	return libevent_call_handler(argc, argv);}static int handler_sendfax(int argc, char **argv){	char module[] = "handler_sendfax";	char trc[200];	sprintf(trc, "Sending fax...");	TRC(TRC_INFO, module, trc);		strcpy(argv[0], SP_EVENT_SENDFAX);	return libevent_call_handler(argc, argv);}/*************************/static int search_device(char *dev){	char module[] = "search_device";	int a = 0;	char trc[200];	for (a = 0; a < SP_DEVICES; a++)	{		if (strcmp(dev, sp_devices[a].devname) == 0)		{			return sp_devices[a].devno;		}	}	sprintf(trc, "Device not found: '%s'", dev);	TRC(TRC_WARN, module, trc);	return -1;}/* Exported functions */int sp_init(char *cmd){	char module[] = "sp_init";	int r = true;	if (!sc_launch(&sp.sc, cmd))	{		TRC(TRC_ERR, module, "Unable to launch script");		return false;	}	sp.handshake = HANDSHAKE_CONNECTING;	if (!sc_send(&sp.sc, "HELLO SHELL"))	{		TRC(TRC_ERR, module, "Unable to send data to script");		return false;	}	r = r && libevent_add_handler(handler_hello,					"SC_HELLO VOICE PROGRAM");	r = r && libevent_add_handler(handler_beep,						"SC_BEEP");	r = r && libevent_add_handler(handler_device,					"SC_DEVICE");		r = r && libevent_add_handler(handler_goodbye,				"SC_GOODBYE"	);		r = r && libevent_add_handler(handler_enable_events,	"SC_ENABLE EVENTS");	r = r && libevent_add_handler(handler_disable_events,	"SC_DISABLE EVENTS");	r = r && libevent_add_handler(handler_dial,						"SC_DIAL");	r = r && libevent_add_handler(handler_play,						"SC_PLAY");	r = r && libevent_add_handler(handler_get_tty,				"SC_GET TTY");	r = r && libevent_add_handler(handler_get_modem,			"SC_GET MODEM");	r = r && libevent_add_handler(handler_autostop,				"SC_AUTOSTOP");	r = r && libevent_add_handler(handler_record,					"SC_RECORD");	r = r && libevent_add_handler(handler_wait,						"SC_WAIT");	r = r && libevent_add_handler(handler_stop,						"SC_STOP");	r = r && libevent_add_handler(handler_dtmf,						"SC_DTMF");	r = r && libevent_add_handler(handler_quote,					"SC_QUOTE");	r = r && libevent_add_handler(handler_getfax,					"SC_GETFAX");	r = r && libevent_add_handler(handler_sendfax,				"SC_SENDFAX");	if (!r)	{		TRC(TRC_ERR, module, "Error initializing script handlers");	}	/* Solo per compatiblita' con vgetty che necessitava		 di una kill -PIPE $PID da parte del processo figlio		 per capirequando erano disponibili i dati sulla pipe. */	signal(SIGPIPE, sigpipe_handler);	return r;}void sigpipe_handler(int par){	par = par;	TRC(TRC_INFO, "sigpipe_handler","lettura messaggi dall script");	sp_handle_messages();}int sp_getstatus(){		switch (sp.handshake) {			case HANDSHAKE_CLOSED:				return SP_HM_CLOSED;				break;			case HANDSHAKE_WAITING:				return SP_HM_OK;				break;			default:				return SP_HM_NONE;		}	return SP_HM_NONE;}int sp_handle_messages(){	char module[] = "sp_handle_messages";	char buf[200];	char evt[200];	char trc[300];	if (sp.handshake == HANDSHAKE_CLOSED)		return SP_HM_CLOSED;		if (sp.handshake != HANDSHAKE_WAITING && sc_receiveready(&sp.sc))	{		sc_receive(&sp.sc, buf, sizeof(buf));		remove_special_chars(buf);				sprintf(trc, "Received from script: %s", buf);		TRC(TRC_INFO, module, trc);		sprintf(evt, "SC_%s", buf);		if (!libevent_process_event(evt))		{			TRC(TRC_ERR, module, "Handler error");			kill(sp.sc.script_pid, SIGTERM);			return SP_HM_ERROR;		}				if (sp.handshake == HANDSHAKE_WAITING)		{			sp.handshake = HANDSHAKE_CLOSED;			return SP_HM_CLOSED;		}		return SP_HM_OK;	}	return SP_HM_NONE;}/* Node abstraction functions (to avoid direct access to scripting protocol) */#define DEFINE_ABS_FUN(name, evt)		int sp_send_##name (void) \																		{ \																			return sc_send(&sp.sc, evt); \																		}#define DEFINE_ABS_EVENT_FUN(name, evt)		int sp_send_##name (void) \																					{ \																						if (events_enabled) \																							return sc_send(&sp.sc, evt); \																						else \																							return true;\																					}DEFINE_ABS_FUN(ready,									"READY")DEFINE_ABS_FUN(device_not_available,	"DEVICE_NOT_AVAILABLE")DEFINE_ABS_FUN(error,									"ERROR")DEFINE_ABS_FUN(beeping,								"BEEPING")DEFINE_ABS_FUN(dialing,								"DIALING")DEFINE_ABS_FUN(playing,								"PLAYING")DEFINE_ABS_FUN(recording,							"RECORDING")DEFINE_ABS_FUN(waiting,								"WAITING")DEFINE_ABS_FUN(dtmfing,								"DTMFING")DEFINE_ABS_FUN(receiving,							"RECEIVING")int sp_send_tty(char *dev){	return	sc_send(&sp.sc, dev) && 					sp_send_ready();}int sp_send_modem(char *modem){	return	sc_send(&sp.sc, modem) && 					sp_send_ready();}int sp_send_dtmf(char dtmf){	char msg[5];	sprintf(msg, "%c", dtmf);	return sc_send(&sp.sc, "RECEIVE_DTMF") && sc_send(&sp.sc, msg);}DEFINE_ABS_EVENT_FUN(bong_tone,           	"BONG_TONE")DEFINE_ABS_EVENT_FUN(busy_tone,           	"BUSY_TONE")DEFINE_ABS_EVENT_FUN(loop_break,          	"LOOP_BREAK")DEFINE_ABS_EVENT_FUN(call_waiting,        	"CALL_WAITING")DEFINE_ABS_EVENT_FUN(dial_tone,           	"DIAL_TONE")DEFINE_ABS_EVENT_FUN(data_calling_tone,   	"DATA_CALLING_TONE")DEFINE_ABS_EVENT_FUN(data_or_fax_detected,	"DATA_OR_FAX_DETECTED")DEFINE_ABS_EVENT_FUN(fax_calling_tone,    	"FAX_CALLING_TONE")DEFINE_ABS_EVENT_FUN(handset_on_hook,     	"HANDSET_ON_HOOK")DEFINE_ABS_EVENT_FUN(handset_off_hook,    	"HANDSET_OFF_HOOK")DEFINE_ABS_EVENT_FUN(loop_polarity_change,	"LOOP_POLARITY_CHANGE")DEFINE_ABS_EVENT_FUN(no_answer,           	"NO_ANSWER")DEFINE_ABS_EVENT_FUN(no_carrier,          	"NO_CARRIER")DEFINE_ABS_EVENT_FUN(no_dial_tone,        	"NO_DIAL_TONE")DEFINE_ABS_EVENT_FUN(no_voice_energy,    		"NO_VOICE_ENERGY")DEFINE_ABS_EVENT_FUN(ring_detected,       	"RING_DETECTED")DEFINE_ABS_EVENT_FUN(ringback_detected,   	"RINGBACK_DETECTED")DEFINE_ABS_EVENT_FUN(silence_detected,    	"SILENCE_DETECTED")DEFINE_ABS_EVENT_FUN(sit_tone,            	"SIT_TONE")DEFINE_ABS_EVENT_FUN(tdd_detected,        	"TDD_DETECTED")DEFINE_ABS_EVENT_FUN(voice_detected,      	"VOICE_DETECTED")DEFINE_ABS_EVENT_FUN(unknown_event,       	"UNKNOWN_EVENT")

⌨️ 快捷键说明

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