Hello, I have a Conexant HSF PCI modem that I used to make phone calls with Microsoft Outlook. (The modem has a handset connected to it).
I am trying to set up KAddressBook to do the same but it expects an external application to dial the number. What application would it be?
Thats a good question, and having never had to do it, I had to do some quick googling.
Anyway, I found a possible application (available in oss repositories) called ant-phone. Download and install, then configure kaddressbook with
ant-phone -e %N
Edit: Another canidate may be the dtmf-dial application
ant-phone works with ISDN and dtmf-dial generates sound, whereas I basically need to send ATD^number to /dev/modem, where number depends on the number to dial and the time of day.
I think the following script should work for me:
#!/bin/sh
phone="${1}"
hour="$(date ‘+%H’)"
if “${hour}” >= ‘8’ && “${hour}” < ‘20’ ]]
then prefix=‘01044’
else prefix=‘01033’
fi
“$1” = ‘+’* ]] && phone=‘0104400’"${1:1}"
“${1}” = ‘+48’* ]] && phone="$prefix${1:3}"
“${1}” = ‘+48’{5,6,7,8}* ]] && phone=‘01044’"${1:3}"
“${1}” = ‘+4880’* ]] && phone=‘01033’"${1:3}"
echo ‘Wywołuję ‘"${phone}"’…’
‘/usr/sbin/chat’>’/dev/modem’<’/dev/modem’ ‘’ ‘ATD^’"${phone}"’@’ ‘CONNECT’
It logs the number I dial; I do not care.
Thanks for sharing you solution
Hmm, it doesn’t hurt anything, but you are too zealous with quoting on this line:
‘/usr/sbin/chat’>’/dev/modem’<’/dev/modem’ ‘’ ‘ATD^’"${phone}"’@’ ‘CONNECT’
The command name and the device name don’t need to be quoted since they are fixed strings without any whitespace inside. At least you didn’t try to quote the < which would have not worked.
Also you could have reduced the number of quotes simply by using double quotes around this whole thing.
“ATD^${phone}@ CONNECT”
I imagine quoted text is parsed faster than unquoted
And failing because of lax quoting is a common pattern in scripts, so I prefer to be on the safe side.
(And, of course, s/>=/-ge/ and s/</-lt/).
Besides, it comes out that setgid scripts are disabled in SuSE, so the script will work only for dialout users.
I have also noticed that the hsfmodem driver puts my call on the loudspeakers, something I never managed to have under Windows. I am curious whether a microphone would work as well.
Surely you are joking. Even if that were true, it would only be minuscule amount for the loss of readability.
The problem is that SuSE does not honor setgid in scripts so a compiled program is required, maybe along these lines:
#include <cstdlib>
#include <fstream>
#include <string>
#include <iostream>
#include <cstring>
#include <cerrno>
#include <sstream>
#include <stdexcept>
#include <cassert>#include <sys/fcntl.h>
#define REQUIRES(P_C) typedef char const requirement_fulfilled_12 +(P_C)];
static char const sc_device_name] = “/dev/modem”,
sc_cmd ] = "AT
", sc_exp ] = "OK
",
sc_daytime_pfx] = “01044”, sc_nightly_pfx] = “01033”;enum DialoguePart { DLG_QUESTION, DLG_ANSWER, DLG_COUNT };
enum Measures
{
HOUR_PER_DAY = 014, HOUR_PER_NIGHT = 014,
MIN_PER_HOUR = 074, SEC_PER_MIN = 074 };
enum LocalSettings { DAY_BEGIN_HOUR = 010, DAY_END_HOUR = 024 };static std:: string phone_expand (char const p_phone ])
{
register time_t a_time ((+time (NULL)));
register struct tm const a_tm
(*localtime
(+a_time == -01?
&(a_time = +DAY_BEGIN_HOUR * +MIN_PER_HOUR * +SEC_PER_MIN): &a_time));
register char const
(*const a_pfx)
(+a_tm. tm_hour >= +DAY_BEGIN_HOUR && +a_tm. tm_hour < +DAY_END_HOUR?
sc_daytime_pfx: sc_nightly_pfx);
register std:: ostringstream a_phone;
static char const sc_format ] = "ATDT^\0@;H
";
enum FormatPos { POS_NUMBER = 06 };
REQUIRES (POS_NUMBER * sizeof *sc_format < sizeof sc_format);
REQUIRES (POS_NUMBER >= 0);
register std:: ostringstream:: pos_type const
a_beg (((a_phone << sc_format). tellp()));
static char const sc_local_pfx ] = “+4880”, sc_foreign_pfx ] = “00”;
assert (!sc_format +POS_NUMBER - 01]);
a_phone << p_phone;
if (+p_phone [01] == ‘+’)
a_phone. seekp (a_beg) << sc_daytime_pfx << sc_foreign_pfx << p_phone + 01;
if (!std:: string:: traits_type:: compare (p_phone, sc_local_pfx, 03))
a_phone. seekp (a_beg)
<< (p_phone [03] >= ‘5’ && p_phone [03] <= ‘8’?
std:: string:: traits_type:: compare (p_phone + 03, sc_local_pfx + 03, 02)?
sc_daytime_pfx: sc_nightly_pfx: a_pfx)
<< p_phone + 03; a_phone << sc_format + POS_NUMBER;
if (!a_phone) throw std:: runtime_error (“no phone”);
return a_phone. str(); }static int nblk_talk (char const ]);
extern “C” int main (int p_argc, char const *const p_argv ])
{
for (int an_ix ((01)); +an_ix < +p_argc; ++an_ix)
{ register std:: string const a_cmd ((phone_expand (p_argv +an_ix])));
if (std:: cout && !(std:: cout << a_cmd << ’
'))
std:: perror (“write”);
if (nblk_talk (a_cmd. c_str()) != +EXIT_SUCCESS) return +EXIT_FAILURE; }
return std:: cout? +EXIT_SUCCESS: +EXIT_FAILURE; }static int nblk_talk (char const p_cmd])
{
register FILE (*const a_modem) ((std:: fopen (sc_device_name, “r+”)));
if (a_modem)
{ register int a_code;
register int const a_fno ((+fileno (a_modem)));
if (+a_fno < 0) { perror (“file”); a_code = +EXIT_FAILURE; }
else
{ register int a_fl (+fcntl (+a_fno, +F_GETFL));
if (+a_fl < 0 || +fcntl (+a_fno, +F_SETFL, +a_fl & ~+O_NONBLOCK) == -01)
{ std:: perror (“flags”); a_code = +EXIT_FAILURE; }
else for (register std:: size_t an_ix (0); +an_ix < 01; ++an_ix)
if
(+std:: fputs (p_cmd, a_modem) == +EOF)
{ std:: perror (“write”); a_code = +EXIT_FAILURE; }
else
{ register int a_line ((0));
do
{
if
(+fcntl
(+a_fno, +F_SETFL, +a_line? +a_fl | +O_NONBLOCK: +a_fl & ~+O_NONBLOCK)
== -01)
{ std:: perror (“flags”); a_code = +EXIT_FAILURE; break; } ++a_line;
auto char a_buf +BUFSIZ];
auto char const (*const a_res) ((std:: fgets (a_buf, +BUFSIZ, a_modem)));
if (a_res) {
if (+std:: fputs (a_res, stdout) == +EOF)
{ std:: perror (“write”); a_code = +EXIT_FAILURE; }
else a_code = +EXIT_SUCCESS; }
else { std:: perror (“read”); a_code = +EXIT_FAILURE; }}
while (+a_code == +EXIT_SUCCESS); }}
if (+std:: fclose (a_modem)) { perror (“close”); return +EXIT_FAILURE; }
else return +a_code; } else { perror (“open”); return +EXIT_FAILURE; }}
Works for me. Note that I was had to use an stdio for nblk_talk because of a bug in fstream and because I need fileno.
Several corrections and enhancements:
#include <cstdlib>
#include <fstream>
#include <string>
#include <iostream>
#include <cstring>
#include <cerrno>
#include <sstream>
#include <stdexcept>
#include <cassert>
#include <sys/fcntl.h>
#define REQUIRED(P_C) typedef char const requirement_fulfilled_12 +(P_C)];
static char const sc_device_name] = "/dev/modem",
sc_cmd ] = "AT
", sc_exp ] = "OK
",
sc_daytime_pfx] = "1044", sc_nightly_pfx] = "1033",
sc_tel_scheme ] = "tel:";
enum Measures
{
HOUR_PER_DAY = 014, HOUR_PER_NIGHT = 014,
MIN_PER_HOUR = 074, SEC_PER_MIN = 074 };
enum LocalSettings { DAY_BEGIN_HOUR = 010, DAY_END_HOUR = 022 };
static std:: string phone_expand (char const *p_phone)
/*
Expands a phone number to a form that can be dialed.
Strips initial "tel:" if present.
*/
{
register time_t a_time ((+time (NULL)));
register struct tm const a_tm
(*localtime
(+a_time == -01?
&(a_time = +DAY_BEGIN_HOUR * +MIN_PER_HOUR * +SEC_PER_MIN): &a_time));
register char const
(*const a_pfx)
(+a_tm. tm_hour >= +DAY_BEGIN_HOUR && +a_tm. tm_hour < +DAY_END_HOUR?
sc_daytime_pfx: sc_nightly_pfx);
register std:: ostringstream a_phone;
static char const sc_format ] = "ATDT^\0,@;H
";
enum FormatPos { POS_NUMBER = 06 };
register
std:: ostringstream:: pos_type const a_beg
(((a_phone << sc_format). tellp()));
static char const sc_local_pfx ] = "+4880", sc_foreign_pfx ] = "00";
REQUIRED (POS_NUMBER * sizeof *sc_format < sizeof sc_format);
REQUIRED (POS_NUMBER > 0);
std:: clog << a_tm. tm_hour << ' ' << a_pfx << '
';
if (!std:: char_traits <char >:: compare (p_phone, sc_tel_scheme, 04))
p_phone += 04;
assert (!sc_format +POS_NUMBER - 01]);
a_phone << p_phone;
if (std:: string:: traits_type:: eq (*p_phone, '+'))
a_phone. seekp (a_beg) << sc_daytime_pfx << sc_foreign_pfx << p_phone + 01;
if (!std:: string:: traits_type:: compare (p_phone, sc_local_pfx, 03))
a_phone. seekp (a_beg)
<< (p_phone [03] >= '5' && p_phone [03] <= '8'?
std:: string:: traits_type:: compare (p_phone + 03, sc_local_pfx + 03, 02)?
sc_daytime_pfx: sc_nightly_pfx: a_pfx)
<< p_phone + 03; a_phone << sc_format + POS_NUMBER << '\0';
if (!a_phone) throw std:: runtime_error ("no phone");
return a_phone. str(); }
static int nblk_talk (char const ]);
extern "C" int main (int p_argc, char const *const p_argv ])
{
for (int an_ix ((01)); +an_ix < +p_argc; ++an_ix)
{ register std:: string const a_cmd ((phone_expand (p_argv +an_ix])));
if (std:: cout && !(std:: cout << a_cmd << '
'))
std:: perror ("write");
if (nblk_talk (a_cmd. c_str()) != +EXIT_SUCCESS) return +EXIT_FAILURE; }
return std:: cout? +EXIT_SUCCESS: +EXIT_FAILURE; }
static int nblk_talk (char const p_cmd])
{
register FILE (*const a_modem) ((std:: fopen (sc_device_name, "r+")));
if (a_modem) /* ?MODEM_IS_OPEN Y */
{ register int a_code;
register int const a_fno ((+fileno (a_modem)));
if (+a_fno < 0) /* ?MODEM_NO_FILENO Y */
{ perror ("file"); a_code = +EXIT_FAILURE; }
else /* ?MODEM_NO_FILENO N */
{ register int a_fl (+fcntl (+a_fno, +F_GETFL));
if (+a_fl < 0 || +fcntl (+a_fno, +F_SETFL, +a_fl & ~+O_NONBLOCK) == -01)
/* ?MODEM_NO_BLOCK Y */
{ perror ("flags"); a_code = +EXIT_FAILURE; }
else /* ?MODEM_NO_BLOCK N */
for (register std:: size_t an_ix (0); +an_ix < 01; ++an_ix) /* @ONCE */
if
(+std:: fputs (p_cmd, a_modem) == +EOF) /* ?MODEM_NO_COMMAND Y */
{ perror ("write"); a_code = +EXIT_FAILURE; }
else /* ?MODEM_NO_COMMAND N */
{ register int a_line ((0));
do /* @ANSWERS */
/*
The code waits for the first answer line
and reads all available remaining lines */
if
(+fcntl
(+a_fno, +F_SETFL, +a_line? +a_fl | +O_NONBLOCK: +a_fl & ~+O_NONBLOCK)
== -01) /* ?MODEM_BLOCK_NO_TOGGLE Y */
{ perror ("flags"); a_code = +EXIT_FAILURE; }
else /* ?MODEM_BLOCK_NO_TOGGLE N */ { ++a_line;
auto char a_buf +BUFSIZ];
auto char const (*const a_res) ((std:: fgets (a_buf, +BUFSIZ, a_modem)));
if (a_res) /* ?MODEM_ANSWER Y */
if (std:: clog << a_res) a_code = +EXIT_SUCCESS;
else { perror ("write"); a_code = +EXIT_FAILURE; }
/* ?MODEM_BLOCK_NO_TOGGLE */
else /* ?MODEM_ANSWER N */ { perror ("read"); a_code = +EXIT_FAILURE; }
/* ?MODEM_ANSWER */ } /* ?MODEM_BLOCK_NO_TOGGLE */
while (+a_code == +EXIT_SUCCESS); /* @ANSWERS */ }
/* ?MODEM_NO_COMMAND */ /* @ONCE X */ /* ?MODEM_NO_BLOCK */ }
/* ?MODEM_NO_FILENO */
if (+std:: fclose (a_modem)) { perror ("close"); return +EXIT_FAILURE; }
else return +a_code; }
else /* ?MODEM_IS_OPEN N */ { perror ("open"); return +EXIT_FAILURE; }
/* ?MODEM_IS_OPEN */ } /* !nblk_talk X */