📄 yaps.c
字号:
if (cnt >= siz) { siz += 4; if (! (mg = (message *) Realloc (mg, (siz + 1) * sizeof (message)))) { OOM; return NULL; } } mg[cnt].nr = cnt; sav = ptr; ptr = skipch (ptr, ','); if (*sav == '/') { ++sav; isalias = False; } else if (*sav == ':') { ++sav; isalias = True; } else if (! isdigit (*sav)) { rmv = cfg_get (cfg, NULL, CFG_RMPID, NULL); if (rmv && *sav && strchr (rmv, *sav)) isalias = False; else isalias = True; } else isalias = False; if (isalias) { if (! (mg[cnt].alias = strdup (sav))) { OOM; return NULL; } if (! (tstr = cfg_block_get (cfg, SEC_ALIAS, sav, NULL))) { fprintf (stderr, "No alias %s found\n", sav); return NULL; } else sav = tstr; } else mg[cnt].alias = NULL; mg[cnt].pid = strdup (sav); sav = recv[n + 1]; if (*sav == '+') { if (! (mg[cnt].msg = readfile (sav + 1))) { fprintf (stderr, "Unable to read %s, aborted\n", sav + 1); return NULL; } } else if ((*sav == '-') && (! *(sav + 1))) { if (! fstdin) if (! (fstdin = read_stdin ())) { fprintf (stderr, "Unable to read from stdin, aborted\n"); return NULL; } mg[cnt].msg = snew (fstdin -> str, fstdin -> len); } else if ((*sav == '.') && (! *(sav + 1))) mg[cnt].msg = snew (NULL, 0); else { if (*sav == '\\') ++sav; mg[cnt].msg = snewc (sav); } if (! (mg[cnt].pid && mg[cnt].msg)) { OOM; return NULL; } mg[cnt].callid = NULL; mg[cnt].service = NULL; mg[cnt].prot = Unknown; mg[cnt].s = NULL; memset (& mg[cnt].st, 0, sizeof (mg[cnt].st)); rmv = cfg_get (cfg, mg[cnt].service, CFG_RMPID, NULL); for (srun = sbase; srun; srun = srun -> next) if ((! service) || (! strcmp (srun -> name, service))) { if (rmv) remove_invalids (mg[cnt].pid, rmv); if (v_alidate (srun -> pchk, mg[cnt].pid, & start, & end)) break; } if (! srun) { fprintf (stderr, "No service for pager id %s found\n", mg[cnt].pid); return NULL; } if (! (mg[cnt].service = strdup (srun -> name))) { OOM; return NULL; } if (rplc = cfg_get (cfg, mg[cnt].service, CFG_CHPID, NULL)) { if (! strcmp (rplc, "-")) rplc = ""; else if (*rplc == '\\') ++rplc; if (! (mg[cnt].pid = do_replace (mg[cnt].pid, start, end - start, rplc, strlen (rplc)))) { OOM; return NULL; } } mg[cnt].s = srun; V (4, ("Found service %s for %s\n", mg[cnt].service, mg[cnt].pid)); ++cnt; } free (str); } free (recv); if (fstdin) sfree (fstdin); if (cnt > 1) qsort (mg, cnt, sizeof (message), mcompare); for (n = 0; n < cnt; ++n) { sr = mg[n].service; if ((mg[n].prot = getproto (cfg_get (cfg, sr, CFG_PROTOCOL, NULL))) == Unknown) { fprintf (stderr, "Unknown protocol for service %s\n", sr); return NULL; } if (! callid) ptr = cfg_get (cfg, sr, CFG_CALLID, NULL); else ptr = callid; if (ptr) if (! (mg[n].callid = strdup (ptr))) { OOM; return NULL; } else if (rmv = cfg_get (cfg, sr, CFG_RMCID, NULL)) remove_invalids (mg[n].callid, rmv); if (cfg_bget (cfg, sr, CFG_USECID, DEF_USECID)) { if (! mg[n].callid) { fprintf (stderr, "Need caller id for service %s\n", sr); return NULL; } } else if (mg[n].callid) { free (mg[n].callid); mg[n].callid = NULL; } if (mg[n].callid) { if (mg[n].s && mg[n].s -> cchk) if (! v_alidate (mg[n].s -> cchk, mg[n].callid, & start, & end)) { fprintf (stderr, "Call ID %s is invalid for service %s\n", mg[n].callid, mg[n].service); return NULL; } if (rplc = cfg_get (cfg, mg[n].service, CFG_CHCID, NULL)) { if (! strcmp (rplc, "-")) rplc = ""; else if (*rplc == '\\') ++rplc; if (! (mg[n].callid = do_replace (mg[n].callid, start, end - start, rplc, strlen (rplc)))) { OOM; return NULL; } } if (check (mg[n].callid, cfg_get (cfg, sr, CFG_CHKCID, NULL)) < 0) { fprintf (stderr, "Invalid caller id %s for service %s\n", mg[n].callid, sr); return NULL; } } if (check (mg[n].pid, cfg_get (cfg, sr, CFG_CHKPID, NULL)) < 0) { fprintf (stderr, "Invalid pager id %s for service %s\n", mg[n].pid, sr); return NULL; } if (force) lforce = force; else lforce = cfg_bget (cfg, sr, CFG_FORCE, False); if (delay && (! cfg_bget (cfg, sr, CFG_CANDELAY, False)) && (! lforce)) { fprintf (stderr, "Service %s is unable to delay a message\n", sr); return NULL; } if (expire && (! cfg_bget (cfg, sr, CFG_CANEXP, False)) && (! lforce)) { fprintf (stderr, "Service %s is unable to set expiration\n", sr); return NULL; } if (! rds) rds = cfg_bget (cfg, sr, CFG_DORDS, False); if (rds && (! cfg_bget (cfg, sr, CFG_CANRDS, False)) && (! lforce)) { fprintf (stderr, "Service %s is unable to report delivery status\n", sr); return NULL; } if (! sig) tsig = cfg_get (cfg, sr, CFG_SIG, NULL); else tsig = sig; if (tsig && (! cfg_bget (cfg, sr, CFG_USESIG, False))) tsig = NULL; if (tsig && *tsig) if (! (scatc (mg[n].msg, " ") && scatc (mg[n].msg, tsig))) { OOM; return NULL; } mg[n].s = NULL; } for (n = 0; n < cnt; ++n) { sr = mg[n].service; if (! trunc) ttrunc = cfg_bget (cfg, sr, CFG_TRUNCATE, False); else ttrunc = trunc; msize = cfg_iget (cfg, sr, CFG_MAXSIZE, 0); msplit = cfg_bget (cfg, sr, CFG_MAYSPLIT, False); if ((msize > 0) && (mg[n].msg -> len > msize)) if (trunc) mg[n].msg -> len = msize; else if (! msplit) { fprintf (stderr, "Unable to split message for service %s\n", sr); return NULL; } else { doins = (msize > 40) ? True : False; if (cnt >= siz) { siz += 4; if (! (mg = (message *) Realloc (mg, (siz + 1) * sizeof (message)))) { OOM; return NULL; } } for (m = cnt; m > n + 1; --m) mg[m] = mg[m - 1]; mg[n + 1].nr = mg[n].nr; mg[n + 1].callid = mg[n].callid ? strdup (mg[n].callid) : NULL; mg[n + 1].alias = mg[n].alias ? strdup (mg[n].alias) : NULL; mg[n + 1].pid = strdup (mg[n].pid); mg[n + 1].service = strdup (mg[n].service); mg[n + 1].prot = mg[n].prot; if (doins) rsize = msize - (sizeof (SPLIT_INIT) - 1); else rsize = msize; for (m = 1; (m < 15) && (m < rsize); ++m) if (sisspace (mg[n].msg, rsize - m)) { rsize -= m; sdel (mg[n].msg, rsize, 1); break; } if (doins) { if (mg[n + 1].msg = snewc (SPLIT_INIT)) if (tmp = scut (mg[n].msg, rsize, mg[n].msg -> len - rsize)) { if (! scat (mg[n + 1].msg, tmp)) mg[n + 1].msg = sfree (mg[n + 1].msg); else { mg[n].msg -> len = rsize; if (! scatc (mg[n].msg, SPLIT_TERM)) mg[n].msg = sfree (mg[n].msg); } sfree (tmp); } else mg[n + 1].msg = sfree (mg[n + 1].msg); } else { mg[n + 1].msg = scut (mg[n].msg, rsize, mg[n].msg -> len - rsize); mg[n].msg -> len = rsize; } mg[n + 1].s = NULL; memset (& mg[n + 1].st, 0, sizeof (mg[n + 1].st)); srelease (mg[n].msg); if (! (mg[n + 1].pid && mg[n + 1].msg && mg[n + 1].service && mg[n].msg)) { OOM; return NULL; } ++cnt; } }# ifndef NDEBUG if (verbose >= 4) { (*verbout) ("Sending following message%s:\n", (cnt == 1 ? "" : "s")); for (n = 0; n < cnt; ++n) if (mg[n].pid && mg[n].msg) (*verbout) ("%-12s (%s, %s): %s\n", (mg[n].alias ? mg[n].alias : mg[n].pid), mg[n].service, mg[n].pid, schar (mg[n].msg)); }# endif /* NDEBUG */ *mcnt = cnt; return mg;}/*}}}*//*{{{ calculate costs */# define WDAY(cc1,cc2) ((((unsigned char) (cc1)) << 8) | ((unsigned char) (cc2)))# define DAY (60 * 24)typedef struct _ttable { int wday; int start, end; double elen; struct _ttable *next;} ttable;static char *vtab[] = { "fixed", "entity-length", "max-entities", "dial-overhead", "cost", "unit", "timetable", "remainder", NULL};static inttonum (char ch){ switch (ch) { default: case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; }}static ttable *parse_timetable (char *str){ ttable *base, *prev, *tmp; char *ptr, *sav, *cptr; int n; base = NULL; prev = NULL; for (ptr = str; *ptr; ) { sav = ptr; ptr = skipch (ptr, ';'); cptr = skipch (sav, '='); if (tmp = (ttable *) malloc (sizeof (ttable))) { tmp -> wday = 0; tmp -> start = 0; tmp -> end = DAY - 1; tmp -> elen = atof (cptr); tmp -> next = NULL; while (*sav) if (isalpha (*sav) && isalpha (*(sav + 1))) { *sav = tolower (*sav); *(sav + 1) = tolower (*(sav + 1)); switch (WDAY (*sav, *(sav + 1))) { case WDAY ('s', 'o'): tmp -> wday |= (1 << 0); break; case WDAY ('m', 'o'): tmp -> wday |= (1 << 1); break; case WDAY ('t', 'u'): tmp -> wday |= (1 << 2); break; case WDAY ('w', 'e'): tmp -> wday |= (1 << 3); break; case WDAY ('t', 'h'): tmp -> wday |= (1 << 4); break; case WDAY ('f', 'r'): tmp -> wday |= (1 << 5); break; case WDAY ('s', 'a'): tmp -> wday |= (1 << 6); break; case WDAY ('w', 'k'): tmp -> wday |= (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5); break; case WDAY ('s', 's'): tmp -> wday |= (1 << 0) | (1 << 6); break; case WDAY ('a', 'l'): tmp -> wday |= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6); break; } sav += 2; } else break; while (*sav && (! isdigit (*sav))) if (*sav == '-') break; if (isdigit (*sav)) { n = 0; while (isdigit (*sav)) { n *= 10; n += tonum (*sav++); } tmp -> start = (n / 100) * 60 + n % 100; } while (*sav && (! isdigit (*sav))) ++sav; if (isdigit (*sav)) { n = 0; while (isdigit (*sav)) { n *= 10; n += tonum (*sav++); } tmp -> end = (n / 100) * 60 + n % 100; } if (prev) prev -> next = tmp; else base = tmp; prev = tmp; } } return base;}static inline Booltimetable_valid (ttable *t, int wday, int tim){ if (t -> wday & (1 << wday)) if (t -> end > t -> start) { if ((tim >= t -> start) && (tim <= t -> end)) return True; } else if ((tim <= t -> end) || (tim >= t -> start)) return True; return False;}static char *calc_cost (void *cfg, char *service, time_t start, int dur){ char *ret; char *tstr; char *ptr, *var, *val; int n; Bool fixed; double elen; int ment; int dover; double cost; char *unit; char *ttab; int remainder; ttable *tbase, *trun; struct tm *tt; double fdur; int cur, wday; double sec; int ents; double fcost; if ((! (tstr = cfg_get (cfg, service, CFG_COST, NULL))) || (! (tstr = strdup (tstr)))) return NULL; ret = NULL; fixed = False; elen = 0.0; ment = -1; dover = 0; cost = 0.0; unit = NULL; ttab = NULL; remainder = 2; for (ptr = tstr; *ptr; ) { var = ptr; ptr = skipch (ptr, ','); val = skipch (var, '='); for (n = 0; vtab[n]; ++n) if (! strcmp (vtab[n], var)) break; switch (n) { case 0: /* fixed */ fixed = True; break; case 1: /* entity-length */ elen = atof (val); break; case 2: /* max-entities */ ment = atoi (val); break; case 3: /* dial-overhead */ dover = atoi (val); break; case 4: /* cost */ cost = atof (val); break; case 5: /* unit */ unit = val; break; case 6: /* timetable */ ttab = val; break; case 7: /* remainder */ remainder = atoi (val); break; } } if (dover > 0) { start += dover; dur -= dover; if (dur < 1) dur = 1; } if (ttab && (tbase = parse_timetable (ttab))) { if (tt = localtime (& start)) { cur = tt -> tm_hour * 60 + tt -> tm_min; sec = (double) tt -> tm_sec; wday = tt -> tm_wday; ents = 0; fdur = 0; trun = NULL; while (fdur <= (double) dur) { if ((! trun) || (! timetable_valid (trun, wday, cur))) { for (trun = tbase; trun; trun = trun -> next) if (timetable_valid (trun, wday, cur)) break; if (! trun) trun = tbase; } if (fixed) { cost = trun -> elen; break; } if (trun -> elen < 0.1) break; ++ents; fdur += trun -> elen; sec += trun -> elen; while (sec >= 60.0) { sec -= 60.0; ++cur; while (cur >= DAY) { cur -= DAY; wday++; if (wday > 6) wday = 0; } } } } while (tbase) { trun = tbase; tbase = tbase -> next; free (trun); } } else ents = (int) ((double) dur / elen) + 1; if ((ment > 0) && (ents > ment)) ents = ment; if (fixed) fcost = cost; else fcost = cost * (double) ents; if (fcost > 0.01) { do_log (LG_COST, "Session costs aprox. %.*f %s", remainder, fcost, (unit ? unit : "")); if (ret = malloc (64 + (unit ? strlen (unit) : 0))) { sprintf (ret, "%.*f", remainder, fcost); if (unit) { for (ptr = ret; *ptr; ++ptr) ; *ptr++ = ' '; strcpy (ptr, unit); } } } free (tstr); return ret;}/*}}}*//*{{{ send pages */static intsendit (void *cfg, int cur, message *mg, int mcnt, int *rerr, date_t *delay, date_t *expire, Bool rds){ char *sr; Bool err; int sig; int n, m; char *ptr; int cnt; int mmsgs; Bool inspid; char *convtab; void *ctab; message *send; int count; void *sp; char *modem, *reset; int tout; int (*transmit) (void *, void *, string_t *, message *, int, void *, char *, date_t *, date_t *, Bool); time_t start, end; int diff; string_t *cid; sr = mg[cur].service; mmsgs = cfg_iget (cfg, sr, CFG_MAXMSGS, 0); inspid = cfg_bget (cfg, sr, CFG_INSPID, DEF_INSPID); for (n = cur, cnt = 0; n < mcnt; ++n, ++cnt) { if (n != cur) if (strcmp (mg[n].service, sr)) break; else if ((mmsgs > 0) && (cnt == mmsgs)) break; else if (inspid && strcmp (mg[cur].pid, mg[n].pid)) break; mg[n].st.success = False; mg[n].st.reason = NotTried; mg[n].st.rmsg = NULL; } ctab = NULL; if (ctab = cv_new ()) { if (convtab = cfg_get (cfg, sr, CFG_CONVTAB, DEF_CONVTAB)) cv_read_table (ctab, convtab); extend_convtable (ctab, cfg, sr); } send = mg + cur; count = cnt; do_log (LG_SSESSION, "Starting up for service %s", sr); time (& start); err = 0; if (sp = do_dial (cfg, sr, (inspid ? mg[0].pid : NULL), & modem)) { for (n = 0; n < cnt; ++n) mg[cur + n].st.reason = NotSend; if (! (sig = setjmp (env))) { dojump = True; switch (mg[cur].prot) { default: case Unknown: transmit = NULL; break; case Ascii: transmit = asc_send; break; case Script: transmit = scr_send; break; case Tap: transmit = tap_send; break; case Ucp: transmit = ucp_send; break; } if (transmit) { cid = mg[0].callid ? snewc (mg[0].callid) : NULL; err = (*transmit) (sp, ctab, cid, send, count, cfg, sr, delay, expire, rds); sfree (cid); } else err = 1; tty_drain (sp, 1); } else V (2, ("\n")); dojump = False; for (n = 0, m = -1; n < cnt; ++n) if (mg[n + cur].st.success == True)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -