version 1.6, 2003/05/05 11:04:10
|
version 1.7, 2003/08/14 23:52:38
|
Line 20
|
Line 20
|
#include <stdio.h> |
#include <stdio.h> |
#include "global.h" |
#include "global.h" |
|
|
|
#define D(x) /* x */ |
#define D(x) /* x */ |
|
|
|
#define MAX_ANOTATE (16 * 256) |
#define MAX_ANOTATE (16 * 256) |
|
|
Line 30 static int cmdf, outf, nextf;
|
Line 29 static int cmdf, outf, nextf;
|
|
|
static int combln, comlln; |
static int combln, comlln; |
static byte combuf[MAX_DATA_COMB]; |
static byte combuf[MAX_DATA_COMB]; |
|
static int pollc; |
|
|
static int dati, dato; |
static int dati, dato; |
static byte data[MAX_ANOTATE]; |
static byte data[MAX_ANOTATE]; |
|
|
static t_msec nextfdelay; |
static t_msec nextrdelay, nextfdelay; |
|
static off_t nextpackets; |
static int num_packets; |
|
static t_msec transmission_time; |
|
|
|
t_msec |
t_msec msec_now (void) |
msec_now (void) |
|
{ |
{ |
static int first_call = 1; |
|
static long long first_time; |
|
static long long now; |
|
|
|
struct timeval tv; |
|
|
|
gettimeofday (&tv, NULL); |
|
#if 0 |
|
#define MSEC_EXPONENT 21 |
#define MSEC_EXPONENT 21 |
static long last; |
static long last; |
static int local_delta; |
static int local_delta; |
if ((tv.tv_sec & (~((1L << MSEC_EXPONENT) - 1))) != last) |
struct timeval tv; |
{ |
gettimeofday (&tv,NULL); |
last = tv.tv_sec & (~((1L << MSEC_EXPONENT) - 1)); |
if ((tv.tv_sec & (~((1L << MSEC_EXPONENT) - 1))) != last) { |
local_delta += 1000 * (1L << MSEC_EXPONENT); |
last = tv.tv_sec & (~((1L << MSEC_EXPONENT) - 1)); |
} |
local_delta += 1000 * (1L << MSEC_EXPONENT); |
|
} |
return ((tv.tv_sec & ((1L << MSEC_EXPONENT) - 1)) * 1000 |
return ((tv.tv_sec & ((1L << MSEC_EXPONENT) - 1)) * 1000 |
+ tv.tv_usec / 1000 + local_delta); |
+ tv.tv_usec / 1000 + local_delta); |
#endif |
|
now = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); |
|
if (first_call) |
|
{ |
|
first_call = 0; |
|
first_time = now; |
|
} |
|
|
|
return (t_msec)(now - first_time); |
|
} |
} |
|
|
static void |
static void command_help (char *command, char *errmsg) |
command_help (char *command) |
|
{ |
{ |
fprintf (stderr, |
fprintf (stderr, "%s\nUsage:\t%s [OPTIONS...] [<file>]\n" |
"Usage:\t%s [<delay> <time> <file>]\n" |
" -d <delay>\ttime in msec after which the sending shall be repeated\n" |
"\tSend <file> repeated every <delay> msec evenly distributed within\n" |
" -t <time>\ttime in msec until the file shall be sent completely\n" |
"\t<time> msec, Feed a (delay,time,file) tuple to stdin to reset\n" |
" -i\t\taccept from stdin tripels: <delay> <time> <file>\n\n" |
"\tbehaviour, quit program with negative delay, don't repeat with delay=0.\n", |
"Send <file> repeated every <delay> msec evenly distributed within <time> msec.\n" |
command); |
"When omitted, <time> defaults to <delay>. When <delay> is omitted, the file is\n" |
|
"sent only once, and <time> must be given. When <file> is ommitted, only -i must\n" |
|
"be given, to allow commands be enter through stdin.\n", |
|
errmsg, command); |
} |
} |
|
|
static boolean |
static boolean line_complete (char **s1, |
line_complete (char **s1, char **s2, char **s3) |
char **s2, |
|
char **s3) |
{ |
{ |
int i; |
int i; |
boolean b = FALSE; |
boolean b; |
*s3 = NULL; |
*s3 = NULL; |
*s2 = NULL; |
*s2 = NULL; |
*s1 = NULL; |
*s1 = NULL; |
i = 0; |
i = 0; |
while (i < combln) |
while (i < combln) { |
{ |
if (combuf[i] == '\n') { |
if (combuf[i] == '\n') |
comlln = i; |
{ |
while (i >= 0) { |
comlln = i; |
if (combuf[i] <= ' ') { |
while (i >= 0) |
combuf[i] = 0; |
{ |
b = TRUE; |
if (combuf[i] <= ' ') |
} else { |
{ |
if (b) { |
combuf[i] = 0; |
*s3 = *s2; |
b = TRUE; |
*s2 = *s1; |
} |
b = FALSE; |
else |
} |
{ |
*s1 = &combuf[i]; |
if (b) |
|
{ |
|
*s3 = *s2; |
|
*s2 = *s1; |
|
b = FALSE; |
|
} |
|
*s1 = &combuf[i]; |
|
} |
|
i -= 1; |
|
} |
|
return (TRUE); |
|
} |
} |
i += 1; |
i -= 1; |
|
} |
|
return (TRUE); |
} |
} |
|
i += 1; |
|
} |
return (FALSE); |
return (FALSE); |
} |
} |
|
|
static boolean |
static boolean is_long (char *s, |
is_long (char *s, long *r) |
long *r) |
{ |
{ |
long i; |
long i; |
char *e; |
char *e; |
if (s == NULL) |
if (s == NULL) { |
{ |
return (FALSE); |
return (FALSE); |
} |
} |
|
errno = 0; |
errno = 0; |
i = strtol (s, &e, 0); |
i = strtol (s,&e,0); |
if ((errno != 0) || (*e != 0)) |
if ((errno != 0) |
{ |
|| (*e != 0)) { |
return (FALSE); |
return (FALSE); |
} |
} |
*r = i; |
*r = i; |
return (TRUE); |
return (TRUE); |
} |
} |
|
|
static boolean |
static boolean command_do (char *arg1, |
command_do (char *arg1, char *arg2, char *arg3) |
char *arg2, |
|
char *arg3) |
{ |
{ |
long l1, l2; |
long l1, l2; |
struct stat stat; |
struct stat stat; |
D (fprintf (stderr, "command_do(%s,%s,%s)\n", arg1, arg2, arg3)); |
D(fprintf(stderr,"command_do(%s,%s,%s)\n",arg1,arg2,arg3)); |
if (arg1 != NULL) |
if (arg1 != NULL) { |
{ |
if (is_long (arg1, &l1)) { |
if (is_long (arg1, &l1)) |
if (l1 < 0) { |
{ |
quit = TRUE; |
if (l1 < 0) |
return (TRUE); |
{ |
} |
quit = TRUE; |
if (arg2 != NULL) { |
return (TRUE); |
if (is_long (arg2, &l2)) { |
} |
if (l2 >= 0) { |
if (arg2 != NULL) |
if ((l1 >= l2) || (l1 == 0)) { |
{ |
if (arg3 != NULL) { |
if (is_long (arg2, &l2)) |
if (nextf >= 0) { |
{ |
close (nextf); |
if (l2 >= 0) |
} |
{ |
if ((nextf = open (arg3, O_RDONLY)) >= 0) { |
if ((l1 >= l2) || (l1 == 0)) |
if (fstat (nextf, &stat) == 0) { |
{ |
D(fprintf(stderr,"file %d, mode %07o, name %s, ino %ld, size %ld\n",nextf,stat.st_mode,arg3,stat.st_ino,stat.st_size)); |
if (arg3 != NULL) |
if (S_ISREG (stat.st_mode)) { |
{ |
if ((stat.st_size % TS_PACKET_SIZE) == 0) { |
if (nextf >= 0) |
nextrdelay = l2; |
{ |
nextpackets = stat.st_size / TS_PACKET_SIZE; |
close (nextf); |
nextfdelay = l1; |
} |
D(fprintf(stderr,"next opened(%d,%d,%d)\n",nextfdelay,nextrdelay,nextpackets)); |
if ((nextf = open (arg3, O_RDONLY)) >= 0) |
return (TRUE); |
{ |
} else { |
if (fstat (nextf, &stat) == 0) |
fprintf (stderr, "File size not multiple of 188\n"); |
{ |
} |
D (fprintf (stderr, "file %d, mode %07o, name %s, ino %ld, size %ld\n", |
} else { |
nextf, stat.st_mode, arg3, stat.st_ino, stat.st_size)); |
fprintf (stderr, "File not regular\n"); |
if (S_ISREG (stat.st_mode)) |
} |
{ |
} else { |
if ((stat.st_size % |
fprintf (stderr, "Cannot stat file\n"); |
TS_PACKET_SIZE) == 0) |
} |
{ |
close (nextf); |
num_packets = stat.st_size / |
nextf = -1; |
TS_PACKET_SIZE; |
} else { |
transmission_time = l2; |
fprintf (stderr, "Cannot open file\n"); |
nextfdelay = l1; |
} |
D (fprintf (stderr, "next opened(%d, %d, %d)\n", |
} else { |
nextfdelay, num_packets, transmission_time)); |
fprintf (stderr, "File name missing\n"); |
return (TRUE); |
} |
} |
} else { |
else |
fprintf (stderr, "0<delay<time not allowed\n"); |
{ |
} |
fprintf (stderr, |
} else { |
"File size not multiple of 188\n"); |
fprintf (stderr, "Time must not be negative\n"); |
} |
} |
} |
} else { |
else |
fprintf (stderr, "Time must be numeric\n"); |
{ |
|
fprintf (stderr, |
|
"File not regular\n"); |
|
} |
|
} |
|
else |
|
{ |
|
fprintf (stderr, "Cannot stat file\n"); |
|
} |
|
close (nextf); |
|
nextf = -1; |
|
} |
|
else |
|
{ |
|
fprintf (stderr, "Cannot open file\n"); |
|
} |
|
} |
|
else |
|
{ |
|
fprintf (stderr, "File name missing\n"); |
|
} |
|
} |
|
else |
|
{ |
|
fprintf (stderr, "0<delay<time not allowed\n"); |
|
} |
|
} |
|
else |
|
{ |
|
fprintf (stderr, "Time must not be negative\n"); |
|
} |
|
} |
|
else |
|
{ |
|
fprintf (stderr, "Time must be numeric\n"); |
|
} |
|
} |
|
else |
|
{ |
|
fprintf (stderr, "Time missing\n"); |
|
} |
|
} |
|
else |
|
{ |
|
fprintf (stderr, "Delay must be numeric\n"); |
|
} |
} |
|
} else { |
|
fprintf (stderr, "Time missing\n"); |
|
} |
|
} else { |
|
fprintf (stderr, "Delay must be numeric\n"); |
} |
} |
else |
} else { |
{ |
return (TRUE); |
return (TRUE); |
} |
} |
|
return (FALSE); |
return (FALSE); |
} |
} |
|
|
static boolean |
static boolean command_init (int cargc, |
command_init (int cargc, char **cargv) |
char **cargv) |
{ |
{ |
|
char *cdelay = NULL; |
|
char *ctime = NULL; |
|
char *cfile = NULL; |
|
int cc = 0; |
nextf = -1; |
nextf = -1; |
quit = FALSE; |
quit = FALSE; |
combln = 0; |
combln = 0; |
dati = dato = 0; |
dati = dato = 0; |
if (cargc > 1) |
pollc = -1; |
{ |
while (++cc < cargc) { |
if (!strcmp (cargv[1], "--help")) |
if (!strcmp (cargv[cc],"--help")) { |
{ |
command_help (cargv[0],""); |
command_help (cargv[0]); |
return (FALSE); |
return (FALSE); |
} else if (!strcmp (cargv[cc],"-i")) { |
} |
pollc = 0; |
else |
} else if (!strcmp (cargv[cc],"-d")) { |
if (!command_do |
if ((cdelay != NULL) || (++cc >= cargc)) { |
(cargv[1], cargc > 2 ? cargv[2] : NULL, |
command_help (cargv[0],"must not use -d twice.\n"); |
cargc > 3 ? cargv[3] : NULL)) |
return (FALSE); |
{ |
} |
command_help (cargv[0]); |
cdelay = cargv[cc]; |
return (FALSE); |
} else if (!strcmp (cargv[cc],"-t")) { |
} |
if ((ctime != NULL) || (++cc >= cargc)) { |
|
command_help (cargv[0],"must not use -t twice.\n"); |
|
return (FALSE); |
|
} |
|
ctime = cargv[cc]; |
|
} else { |
|
if (cfile != NULL) { |
|
command_help (cargv[0],"too many parameters.\n"); |
|
return (FALSE); |
|
} |
|
cfile = cargv[cc]; |
|
} |
|
} |
|
if (cfile != NULL) { |
|
if (!command_do (cdelay ? cdelay : "0", ctime ? ctime : cdelay, cfile)) { |
|
command_help (cargv[0],""); |
|
return (FALSE); |
} |
} |
|
} else if ((ctime != NULL) || (cdelay != NULL) || (pollc <= 0)) { |
|
command_help (cargv[0],"only -i must be given when started with no file.\n"); |
|
return (FALSE); |
|
} |
cmdf = STDIN_FILENO; |
cmdf = STDIN_FILENO; |
outf = STDOUT_FILENO; |
outf = STDOUT_FILENO; |
return ((cmdf >= 0) && (outf >= 0)); |
return ((cmdf >= 0) && (outf >= 0)); |
} |
} |
|
|
int |
int main (int argc, |
main (int argc, char *argv[]) |
char *argv[]) |
{ |
{ |
int polli, pollo, polls; |
int polli, pollo, polls; |
int toberead = 0; /* to make gcc happy */ |
int toberead; |
int currentf; |
int currentf; |
int packet_count = 0; |
|
|
|
boolean dotime; |
boolean dotime; |
t_msec rtime; |
t_msec rtime, ftime, rdelay, fdelay, now; |
t_msec rtime_base = 0; |
struct pollfd ufds [3]; |
t_msec ftime; |
off_t rpackets, rpartial, rpdone; |
t_msec fdelay = 0; /* to make gcc happy */ |
if (command_init (argc,&argv[0])) { |
t_msec now; |
currentf = -1; |
struct pollfd ufds[3]; |
rtime = ftime = msec_now (); |
if (command_init (argc, &argv[0])) |
while (!quit) { |
{ |
now = msec_now (); |
currentf = -1; |
D(fprintf(stderr,"now(%d)\n",now)); |
rtime = ftime = msec_now (); |
if (currentf < 0) { |
while (!quit) |
toberead = 0; |
{ |
if (nextpackets > 0) { |
|
rpackets = nextpackets; |
|
rdelay = nextrdelay / nextpackets; |
|
rpartial = nextrdelay % nextpackets; |
|
} else { |
|
rpackets = 1; |
|
rdelay = 0; |
|
rpartial = 0; |
|
} |
|
rpdone = 0; |
|
fdelay = nextfdelay; |
|
if ((ftime-now) < 0) { |
|
ftime = now; |
|
} |
|
rtime = ftime; |
|
currentf = nextf; |
|
nextf = -1; |
|
D(fprintf(stderr,"next current(%d,%d,%d)\n",currentf,fdelay,rdelay)); |
|
} |
|
if (currentf >= 0) { |
|
if ((rtime - now) <= 0) { |
|
if ((((dato-dati-1) & (MAX_ANOTATE-1)) - toberead) > TS_PACKET_SIZE) { |
|
toberead += TS_PACKET_SIZE; |
|
rtime += rdelay; |
|
rpdone += rpartial; |
|
if (rpdone >= rpackets) { |
|
rpdone -= rpackets; /* equaly distribute the rounded msecs by */ |
|
rtime += 1; /* counting them in an rpackets modulo-space */ |
|
} |
|
dotime = TRUE; |
|
D(fprintf(stderr,"timer a(%d,%d,%d)\n",toberead,rtime,rpdone)); |
|
} else { |
|
rtime = now; |
|
dotime = FALSE; |
|
D(fprintf(stderr,"timer b(%d,%d)\n",toberead,rtime)); |
|
} |
|
} else { |
|
dotime = TRUE; |
|
D(fprintf(stderr,"timer c(%d,%d)\n",toberead,rtime)); |
|
} |
|
} else { |
|
dotime = FALSE; |
|
D(fprintf(stderr,"timer c(%d,%d)\n",toberead,rtime)); |
|
} |
|
polls = pollc+1; |
|
if (pollc >= 0) { |
|
ufds[pollc].fd = cmdf; |
|
ufds[pollc].events = POLLIN; |
|
} |
|
if (dati != dato) { |
|
pollo = polls++; |
|
ufds[pollo].fd = outf; |
|
ufds[pollo].events = POLLOUT; |
|
} else { |
|
pollo = -1; |
|
} |
|
if (toberead > 0) { |
|
polli = polls++; |
|
ufds[polli].fd = currentf; |
|
ufds[polli].events = POLLIN; |
|
} else { |
|
polli = -1; |
|
} |
|
poll (&ufds[0], polls, dotime ? ((rtime-now) > 0) ? (rtime-now) : 0 : -1); |
|
if ((pollc >= 0) |
|
&& (ufds[pollc].revents & POLLIN)) { |
|
char *s1, *s2, *s3; |
|
if (combln >= MAX_DATA_COMB-HIGHWATER_COM) { |
|
combln -= HIGHWATER_COM; |
|
memmove (&combuf[0], &combuf[HIGHWATER_COM], combln); |
|
} |
|
combln += read (cmdf, &combuf[combln], MAX_DATA_COMB-combln); |
|
while (line_complete (&s1, &s2, &s3)) { |
|
command_do (s1, s2, s3); |
|
combln -= comlln; |
|
memmove (&combuf[0], &combuf[comlln], combln); |
|
} |
|
} |
|
if ((polli >= 0) |
|
&& (ufds[polli].revents & (POLLIN | POLLHUP | POLLERR))) { |
|
int l; |
|
if (ufds[polli].revents & POLLIN) { |
|
l = toberead; |
|
if (l > (MAX_ANOTATE - dati)) { |
|
l = MAX_ANOTATE - dati; |
|
} |
|
l = read (currentf, &data[dati], l); |
|
dati = (dati+l) & (MAX_ANOTATE-1); |
|
toberead -= l; |
|
} else { |
|
l = 0; |
|
} |
|
if (l == 0) { |
|
if ((nextf >= 0) |
|
|| (fdelay == 0)) { |
|
close (currentf); |
|
currentf = -1; |
|
} else { |
|
lseek (currentf,0,SEEK_SET); |
|
toberead = ((toberead-1) / TS_PACKET_SIZE) * TS_PACKET_SIZE; |
|
} |
|
ftime += fdelay; |
now = msec_now (); |
now = msec_now (); |
D (fprintf (stderr, "now(%x)\n", now)); |
if ((ftime-now) < 0) { |
if (currentf < 0) |
ftime = now; |
{ |
} |
toberead = 0; |
rtime = ftime; |
fdelay = nextfdelay; |
} |
if ((ftime - now) < 0) |
} |
{ |
if ((pollo >= 0) |
ftime = now; |
&& (ufds[pollo].revents & (POLLOUT | POLLHUP | POLLERR))) { |
} |
if (ufds[pollo].revents & POLLOUT) { |
rtime_base = rtime = ftime; |
int l; |
packet_count = 0; |
if (dati < dato) { |
currentf = nextf; |
l = MAX_ANOTATE - dato; |
nextf = -1; |
} else { |
D (fprintf (stderr, "next current(%d,%d)\n", currentf, fdelay)); |
l = dati - dato; |
} |
} |
if (currentf >= 0) |
l = write (outf, &data[dato], l); |
{ |
dato = (dato+l) & (MAX_ANOTATE-1); |
if ((rtime - now) <= 0) |
if (l == 0) { |
{ |
quit = TRUE; |
if ((((dato - dati - 1) & (MAX_ANOTATE - 1)) - toberead) > |
} |
TS_PACKET_SIZE) |
} else { |
{ |
quit = TRUE; |
toberead += TS_PACKET_SIZE; |
|
|
|
packet_count++; |
|
if (num_packets > 0) |
|
{ |
|
rtime = rtime_base + |
|
(t_msec)(((long long)packet_count * transmission_time) / |
|
num_packets); |
|
D (fprintf (stderr, "%d %d %d %d %d\n", |
|
rtime, rtime_base, packet_count, |
|
transmission_time, num_packets)); |
|
} |
|
|
|
dotime = TRUE; |
|
D (fprintf (stderr, "timer a(%d,%d)\n", toberead, rtime)); |
|
} |
|
else |
|
{ |
|
rtime_base = rtime = now; |
|
packet_count = 0; |
|
dotime = FALSE; |
|
D (fprintf (stderr, "timer b(%d,%d)\n", toberead, rtime)); |
|
} |
|
} |
|
else |
|
{ |
|
dotime = TRUE; |
|
D (fprintf (stderr, "timer c(%d,%d)\n", toberead, rtime)); |
|
} |
|
} |
|
else |
|
{ |
|
dotime = FALSE; |
|
D (fprintf (stderr, "timer c(%d,%d)\n", toberead, rtime)); |
|
} |
|
ufds[0].fd = cmdf; |
|
ufds[0].events = POLLIN; |
|
if (dati != dato) |
|
{ |
|
ufds[1].fd = outf; |
|
ufds[1].events = POLLOUT; |
|
pollo = 1; |
|
} |
|
else |
|
{ |
|
pollo = 0; |
|
} |
|
polls = pollo + 1; |
|
if (toberead > 0) |
|
{ |
|
polli = polls++; |
|
ufds[polli].fd = currentf; |
|
ufds[polli].events = POLLIN; |
|
} |
|
else |
|
{ |
|
polli = 0; |
|
} |
|
poll (&ufds[1], polls-1, |
|
dotime ? ((rtime - now) > 0) ? (rtime - now) : 0 : -1); |
|
if (ufds[0].revents & POLLIN) |
|
{ |
|
char *s1, *s2, *s3; |
|
if (combln >= MAX_DATA_COMB - HIGHWATER_COM) |
|
{ |
|
combln -= HIGHWATER_COM; |
|
memmove (&combuf[0], &combuf[HIGHWATER_COM], combln); |
|
} |
|
combln += read (cmdf, &combuf[combln], MAX_DATA_COMB - combln); |
|
while (line_complete (&s1, &s2, &s3)) |
|
{ |
|
command_do (s1, s2, s3); |
|
combln -= comlln; |
|
memmove (&combuf[0], &combuf[comlln], combln); |
|
} |
|
} |
|
if ((polli != 0) |
|
&& (ufds[polli].revents & (POLLIN | POLLHUP | POLLERR))) |
|
{ |
|
int l; |
|
if (ufds[polli].revents & POLLIN) |
|
{ |
|
l = toberead; |
|
if (l > (MAX_ANOTATE - dati)) |
|
{ |
|
l = MAX_ANOTATE - dati; |
|
} |
|
l = read (currentf, &data[dati], l); |
|
dati = (dati + l) & (MAX_ANOTATE - 1); |
|
toberead -= l; |
|
} |
|
else |
|
{ |
|
l = 0; |
|
} |
|
if (l == 0) |
|
{ |
|
if ((nextf >= 0) || (fdelay == 0)) |
|
{ |
|
close (currentf); |
|
currentf = -1; |
|
} |
|
else |
|
{ |
|
lseek (currentf, 0, SEEK_SET); |
|
toberead = |
|
((toberead - 1) / TS_PACKET_SIZE) * TS_PACKET_SIZE; |
|
} |
|
ftime += fdelay; |
|
now = msec_now (); |
|
if ((ftime - now) < 0) |
|
{ |
|
ftime = now; |
|
} |
|
rtime_base = rtime = ftime; |
|
packet_count = 0; |
|
} |
|
} |
|
if ((pollo != 0) |
|
&& (ufds[1].revents & (POLLOUT | POLLHUP | POLLERR))) |
|
{ |
|
if (ufds[1].revents & POLLOUT) |
|
{ |
|
int l; |
|
if (dati < dato) |
|
{ |
|
l = MAX_ANOTATE - dato; |
|
} |
|
else |
|
{ |
|
l = dati - dato; |
|
} |
|
l = write (outf, &data[dato], l); |
|
dato = (dato + l) & (MAX_ANOTATE - 1); |
|
if (l == 0) |
|
{ |
|
quit = TRUE; |
|
} |
|
} |
|
else |
|
{ |
|
quit = TRUE; |
|
} |
|
} |
|
} |
} |
return (EXIT_SUCCESS); |
} |
} |
} |
|
return (EXIT_SUCCESS); |
|
} |
return (EXIT_FAILURE); |
return (EXIT_FAILURE); |
} |
} |