📄 dial.c
字号:
/* * dial.c Functions to dial, retry etc. Als contains the dialing * directory code, _and_ the famous tu-di-di music. * * This file is part of the minicom communications package, * Copyright 1991-1995 Miquel van Smoorenburg. * * 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. */#include "port.h"#include "minicom.h"#if VC_MUSIC# if defined(__linux__)# include <sys/ioctl.h># include <sys/kd.h># include <sys/time.h># endif# if defined(_COH42) || defined(_SCO)# include <sys/vtkd.h># endif#endif/* We want the ANSI offsetof macro to do some dirty stuff. */#ifndef offsetof# define offsetof(type, member) ((int) &((type *)0)->member)#endif/* Values for the "flags". */#define FL_ECHO 0x01 /* Local echo on/off. */#define FL_DEL 0x02 /* Backspace or DEL */#define FL_WRAP 0x04 /* Use autowrap. */#define FL_ANSI 0x08 /* Type of term emulation */#define FL_TAG 0x80 /* This entry is tagged. */#define FL_SAVE 0x0f /* Which portions of flags to save. *//* Dialing directory. */struct v1_dialent { char name[32]; char number[16]; char script[16]; char username[32]; char password[32]; char term; char baud[8]; char parity[2]; char dialtype; char flags; /* Localecho in v0 */ char bits[2]; struct dialent *next;};struct dialent { char name[32]; char number[32]; char script[32]; char username[32]; char password[32]; char term; char baud[8]; char parity[2]; char dialtype; char flags; char bits[2]; struct dialent *next;};/* Version info. */#define DIALMAGIC 0x55AAstruct dver { short magic; short version; short size; short res1; short res2; short res3; short res4;};#define dialentno(di, no) ((struct dialent *)((char *)(di) + ((no) * sizeof(struct dialent)))) static struct dialent *dialents;static struct dialent *d_man;static int nrents = 1;static int newtype;/* Access to ".dialdir" denied? */static int dendd = 0;static char *tagged;/* * Functions to talk to the modem. */ /* * Send a string to the modem. * If how == 0, '~' sleeps 1 second. * If how == 1, "^~" sleeps 1 second. */void mputs(s, how)char *s;int how;{ char c; while(*s) { if (*s == '^' && (*(s + 1))) { s++; if (*s == '^') c = *s; else if (how == 1 && *s == '~') { sleep(1); s++; continue; } else c = (*s) & 31; } else c = *s; if (how == 0 && c == '~') sleep(1); else write(portfd, &c, 1); s++; }} /* * Initialize the modem. */ void modeminit(){ WIN *w; if (P_MINIT[0] == '\0') return; w = tell("Initializing Modem"); m_dtrtoggle(portfd); mputs(P_MINIT, 0); wclose(w, 1);}/* * Reset the modem. */void modemreset(){ WIN *w; if (P_MRESET[0] == '\0') return; w = tell("Resetting Modem"); mputs(P_MRESET, 0); sleep(1); wclose(w, 1);}/* * Hang the line up. */void hangup(){ WIN *w; w = tell("Hanging up"); if (P_MDROPDTR[0] == 'Y') { m_dtrtoggle(portfd); } else { mputs(P_MHANGUP, 0); sleep(1); } /* If we don't have DCD support fake DCD dropped */ bogus_dcd = 0; wclose(w, 1);}/* * This seemed to fit best in this file * Send a break signal. */void sendbreak(){ WIN *w; w = tell("Sending BREAK"); wcursor(w, CNONE); m_break(portfd); wclose(w, 1);} WIN *dialwin;int dialtime;#if VC_MUSIC/* * Play music until key is pressed. */void music(){ int x, i, k; int consolefd = 0; char *disp; /* If we're in X, we have to explicitly use the console */ if (strncmp(getenv("TERM"), "xterm", 5) == 0 && (disp = getenv("DISPLAY")) != NULL && (strcmp(disp, ":0.0") == 0 || (strcmp(disp, ":0") == 0))) { consolefd = open("/dev/console", O_WRONLY); if (consolefd < 0) consolefd = 0; } /* Tell keyboard handler what we want. */ keyboard(KSIGIO, 0); /* And loop forever :-) */ for(i = 0; i < 9; i++) { k = 2000 - 200 * (i % 3); (void) ioctl(consolefd, KIOCSOUND, k); /* Check keypress with timeout 160 ms */ x = check_io(-1, 0, 160, NULL, NULL); if (x & 2) break; } (void) ioctl(consolefd, KIOCSOUND, 0); if (consolefd) close(consolefd); /* Wait for keypress and absorb it */ while((x & 2) == 0) x = check_io(-1, 0, 10000, NULL, NULL); (void) keyboard(KGETKEY, 0);}#endif/* * The dial has failed. Tell user. * Count down until retrytime and return. */static int dialfailed(s, rtime)char *s;int rtime;{ int f, x; int ret = 0; wlocate(dialwin, 1, 5); wprintf(dialwin, " No connection: %s. \n", s); if (rtime < 0) { wprintf(dialwin, " Press any key to continue.. "); if (check_io(-1, 0, 10000, NULL, NULL) & 2) (void) keyboard(KGETKEY, 0); return(0); } wprintf(dialwin, " Retry in %2d seconds ", rtime); for(f = rtime - 1; f >= 0; f--) { x = check_io(-1, 0, 1000, NULL, NULL); if (x & 2) { /* Key pressed - absorb it. */ x = keyboard(KGETKEY, 0); if (x != ' ') ret = -1; break; } wlocate(dialwin, 14, 6); wprintf(dialwin, "%2d ", f); }#ifdef __linux__ /* MARK updated 02/17/94 - Min dial delay set to 0.35 sec instead of 1 sec */ if (f < 0) usleep(350000); /* Allow modem time to hangup if redial time == 0 */#else if (f < 0) sleep(1);#endif wlocate(dialwin, 1, 5); wprintf(dialwin, " \n"); wprintf(dialwin, " "); return(ret);}/* * Dial a number, and display the name. */int dial(d)struct dialent *d;{ char *s = 0, *t = 0; int f, x = 0, nb, retst = -1; int modidx, retries = 0; int maxretries = 1, rdelay = 45; char *reason = "Max retries"; time_t now, last; char buf[128]; char modbuf[128]; dialwin = wopen(18, 9, 62, 15, BSINGLE, stdattr, mfcolor, mbcolor, 0, 0, 1); wtitle(dialwin, TMID, "Autodial"); wcursor(dialwin, CNONE); wputs(dialwin, "\n"); wprintf(dialwin, " Dialing : %s\n", d->name); wprintf(dialwin, " At : %s\n", d->number); wredraw(dialwin, 1); /* Tell keyboard routines we need them. */ keyboard(KSIGIO, 0); maxretries = atoi(P_MRETRIES); if (maxretries <= 0) maxretries = 1; rdelay = atoi(P_MRDELAY); if (rdelay < 0) rdelay = 0; /* Main retry loop of dial() */MainLoop: while(++retries <= maxretries) { /* See if we need to try the next tagged entry. */ if (retries > 1 && (d->flags & FL_TAG)) { do { d = d->next; if (d == (struct dialent *)NULL) d = dialents; } while(!(d->flags & FL_TAG)); wlocate(dialwin, 0, 1); wprintf(dialwin, " Dialing : %s", d->name); wclreol(dialwin); wprintf(dialwin, "\n At : %s", d->number); wclreol(dialwin); } /* Calculate dial time */ dialtime = atoi(P_MDIALTIME); if (dialtime == 0) dialtime = 45; time(&now); last = now; /* Show used time */ wlocate(dialwin, 0, 3); wprintf(dialwin, " Time : %-3d", dialtime); if (maxretries > 1) wprintf(dialwin, " Attempt #%d", retries); wputs(dialwin, "\n\n\n Escape to cancel, space to retry."); /* Start the dial */ m_flush(portfd); switch(d->dialtype) { case 0: mputs(P_MDIALPRE, 0); mputs(d->number, 0); mputs(P_MDIALSUF, 0); break; case 1: mputs(P_MDIALPRE2, 0); mputs(d->number, 0); mputs(P_MDIALSUF2, 0); break; case 2: mputs(P_MDIALPRE3, 0); mputs(d->number, 0); mputs(P_MDIALSUF3, 0); break; } /* Wait 'till the modem says something */ modbuf[0] = 0; modidx = 0; s = buf; buf[0] = 0; while(dialtime > 0) { if (*s == 0) { x = check_io(portfd, 0, 1000, buf, NULL); s = buf; } if (x & 2) { f = keyboard(KGETKEY, 0); /* Cancel if escape was pressed. */ if (f == K_ESC) mputs(P_MDIALCAN, 0); /* On space retry. */ if (f == ' ') { mputs(P_MDIALCAN, 0); dialfailed("Cancelled", 4); m_flush(portfd); break; } (void) keyboard(KSTOP, 0); wclose(dialwin, 1); return(retst); } if (x & 1) { /* Data available from the modem. Put in buffer. */ if (*s == '\r' || *s == '\n') { /* We look for [\r\n]STRING[\r\n] */ modbuf[modidx] = 0; modidx = 0; } else if (modidx < 127) { /* Normal character. Add. */ modbuf[modidx++] = *s; modbuf[modidx] = 0; } /* Skip to next received char */ if (*s) s++; /* Only look when we got a whole line. */ if (modidx == 0 && !strncmp(modbuf, P_MCONNECT, strlen(P_MCONNECT))) { retst = 0; /* Try to do auto-bauding */ if (sscanf(modbuf + strlen(P_MCONNECT), "%d", &nb) == 1) retst = nb; /* Try to figure out if this system supports DCD */ f = m_getdcd(portfd); bogus_dcd = 1; wlocate(dialwin, 1, 6); if (d->script[0] == 0) { wputs(dialwin, "Connected. Press any key to continue");#if VC_MUSIC if (P_SOUND[0] == 'Y') music(); else { x = check_io(-1, 0, 0, NULL, NULL); if ((x & 2) == 2) (void) keyboard(KGETKEY, 0); }#else /* MARK updated 02/17/94 - If VC_MUSIC is not */ /* defined, then at least make some beeps! */ if (P_SOUND[0] == 'Y') wputs(dialwin,"\007\007\007");#endif x = check_io(-1, 0, 0, NULL, NULL); if ((x & 2) == 2) (void) keyboard(KGETKEY, 0); } keyboard(KSTOP, 0); wclose(dialwin, 1); /* Print out the connect strings. */ wprintf(us, "\r\n%s\r\n", modbuf); dialwin = NIL_WIN; /* Un-tag this entry. */ d->flags &= ~FL_TAG; return(retst); } for(f = 0; f < 3; f++) { if (f == 0) t = P_MNOCON1; if (f == 1) t = P_MNOCON2; if (f == 2) t = P_MNOCON3; if (f == 3) t = P_MNOCON4; if ((*t) && (!strncmp(modbuf, t, strlen(t)))) { if (retries < maxretries) { x = dialfailed(t, rdelay); if (x < 0) { keyboard(KSTOP, 0); wclose(dialwin, 1); return(retst); } } if (maxretries == 1) reason = t; goto MainLoop; } } } /* Do timer routines here. */ time(&now); if (last != now) { dialtime -= (now - last); if (dialtime < 0) dialtime = 0; wlocate(dialwin, 11, 3); wprintf(dialwin, "%-3d ", dialtime); if (dialtime <= 0) { mputs(P_MDIALCAN, 0); reason = "Timeout"; retst = -1; if (retries < maxretries) { x = dialfailed(reason, rdelay); if (x < 0) { keyboard(KSTOP, 0); wclose(dialwin, 1); return(retst); } } } } last = now; } } /* End of main while cq MainLoop */ dialfailed(reason, -1); keyboard(KSTOP, 0); wclose(dialwin, 1); return(retst);}/* * Create an empty entry. */static struct dialent *mkstdent(){ struct dialent *d; d = (struct dialent *)malloc(sizeof (struct dialent)); if (d == (struct dialent *)0) return(d); d->name[0] = 0; d->number[0] = 0; d->script[0] = 0; d->username[0] = 0; d->password[0] = 0; d->term = 1; d->dialtype = 0; d->flags = FL_DEL; strcpy(d->baud, "Curr"); strcpy(d->bits, "8"); strcpy(d->parity, "N"); d->next = (struct dialent *)0; return(d);}/* Read version 3 of the dialing directory. */void v3_read(fp, d)struct dialent *d;FILE *fp;{ (void) fread((char *)d, sizeof(struct dialent), (size_t)1, fp);}/* Read version 2 of the dialing directory. */void v2_read(fp, d)struct dialent *d;FILE *fp;{ (void) fread((char *)d, sizeof(struct dialent), (size_t)1, fp); if (d->flags & FL_ANSI) d->flags |= FL_WRAP;}/* Read version 1 of the dialing directory. */void v1_read(fp, d)FILE *fp;struct dialent *d;{ struct v1_dialent v1; fread((char *)&v1, sizeof(v1), (size_t)1, fp); memcpy(d->username, v1.username, sizeof(v1) - offsetof(struct v1_dialent, username)); strcpy(d->name, v1.name); strcpy(d->number, v1.number); strcpy(d->script, v1.script);}/* Read version 0 of the dialing directory. */void v0_read(fp, d)FILE *fp;struct dialent *d;{ v1_read(fp, d); d->dialtype = 0; d->flags = 0;}/* * Read in the dialing directory from $HOME/.dialdir */int readdialdir(){ long size; FILE *fp; char dfile[256]; static int didread = 0; int f; struct dialent *d = NULL, *prev = (struct dialent *)0; struct dver dial_ver; if (didread) return(0); didread = 1; nrents = 1; tagged = (char *)malloc(1); tagged[0] = 0; /* Make the manual dial entry. */ d_man = mkstdent(); strcpy(d_man->name, "Manually entered number"); /* Construct path */ sprintf(dfile, "%s/.dialdir", homedir); /* Try to open ~/.dialdir */ if ((fp = sfopen(dfile, "r")) == (FILE *)NULL) { if (errno == EPERM) { werror("Cannot open ~/.dialdir: permission denied"); dialents = mkstdent(); dendd = 1; return(0); } dialents = mkstdent(); return(0); } /* Get size of the file */ fseek(fp, 0L, SEEK_END); size = ftell(fp); if (size == 0) { dialents = mkstdent(); fclose(fp); return(0); } /* Get version of the dialing directory */ fseek(fp, 0L, SEEK_SET); fread(&dial_ver, sizeof(dial_ver), 1, fp); if (dial_ver.magic != DIALMAGIC) { /* First version without version info. */ dial_ver.version = 0; fseek(fp, 0L, SEEK_SET); } else size -= sizeof(dial_ver); /* See if the size of the file is allright. */ switch(dial_ver.version) { case 0: case 1: dial_ver.size = sizeof(struct v1_dialent); break; case 2: case 3: dial_ver.size = sizeof(struct dialent); break; default: werror("Unknown dialing directory version"); dendd = 1; dialents = mkstdent(); return(-1); } if (size % dial_ver.size != 0) { werror("Phonelist garbled (?)"); fclose(fp);#if 0 /* This should be less facistic now. */ unlink(dfile);#else dendd = 1;#endif dialents = mkstdent(); return(-1); } /* Read in the dialing entries */ nrents = size / dial_ver.size; if (nrents == 0) { dialents = mkstdent();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -