/* $Id: fcast.c,v 1.4 2003/11/12 17:02:22 roca Exp $ */ /* * Copyright (c) 1999-2002 INRIA - Universite Paris 6 - All rights reserved * (main authors: Julien Laboure - julien.laboure@inrialpes.fr * Vincent Roca - vincent.roca@inrialpes.fr) * * 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. */ /* * fcast.c * * Fcast file transfert tool over MCL Multicast Library. */ #include "fcast.h" void Usage (int argc, char *argv[]); void ParseCommandLine (int argc, char *argv[]); void interrupted (void); /******** Globals */ /* * global variables common to ALC / NORM */ int id = 0; int verbose = 0; int stats = 0; unsigned long addr = 0; unsigned long src_addr = 0; unsigned long mcast_if = 0; int port = 9998; int demux_label = 0; int ttl = 1; /*float fec_ratio = 2.0;*/ float fec_ratio = 1.5; int mode = 0; int reuse_tx_buff = 1; int overwrite = PROMPT; char fileparam[MAX_PATH+MAX_FILENAME]; int recursive = 0; #ifdef WIN32 int pause = 0; #endif int silent = 0; int tx_huge_file = 0; #define MAX_FILE_NAME_LEN 256 char tmp_dir[MAX_FILE_NAME_LEN]; int tmp_dir_set = 0; int txprof_set = 0; /* set tx profile only once */ int txprof_mode = MCL_TX_PROFILE_MID_RATE_INTERNET; int txprof_dt_size = 0; /* default datagram size in bytes */ int txprof_rate = 0; /* default rate in pkts/s (converted from bps)*/ #if defined(ALC) /* * global variables specific to ALC */ int levels = 0; int nb_tx = 1; int delivery_mode = DEL_MODE_PUSH; int optimode = OPTIMIZE_SPEED; int single_layer = 0; #elif defined(NORM) /* * global variables specific to NORM */ #endif /* RM_PROTOCOL */ int main (int argc, char *argv[]) { int err = 0; /* return value of mcl_ctl functions */ signal(SIGINT, (sighandler_t)interrupted); ParseCommandLine(argc, argv); /* Parameters parsing... */ if (mode == SEND) /*sender */ { if ((id = mcl_open("w")) < 0) EXIT(("FcastSend: ERROR, mcl_open failed\n")) } else if (mode == RECV) /* or receiver */ { if ((id = mcl_open("r")) < 0) EXIT(("FcastSend: ERROR, mcl_open failed\n")) } else /* what? */ { PRINT(("Error: -send or -recv mode required\n")) Usage(argc, argv); return -1; } /* specify few important parameters... */ if (verbose > 0) { err += mcl_ctl(id, MCL_OPT_VERBOSITY, (void*)&verbose, sizeof(verbose)); EXIT_ON_ERROR(err, ("Fcast: ERROR, mcl_ctl failed for VERBOSITY\n")) } if (stats > 0) { err += mcl_ctl(id, MCL_OPT_STATS, (void*)&stats, sizeof(int)); EXIT_ON_ERROR(err, ("Fcast: ERROR, mcl_ctl failed for STATS\n")) } err += mcl_ctl(id, MCL_OPT_TX_PROFILE, (void*)&txprof_mode, sizeof(txprof_mode)); EXIT_ON_ERROR(err, ("Fcast: ERROR, mcl_ctl failed for TX_PROFILE\n")) #if defined(ALC) if (single_layer > 0) { /* must be before TX_PROFILE */ err += mcl_ctl(id, MCL_OPT_SINGLE_LAYER, (void*)&single_layer, sizeof(single_layer)); EXIT_ON_ERROR(err, ( "Fcast: ERROR, mcl_ctl failed for SINGLE_LAYER\n")) } #endif /* RM_PROTOCOL */ if (txprof_dt_size == 0) { err += mcl_ctl(id, MCL_OPT_TX_PROFILE, (void*)&txprof_mode, sizeof(txprof_mode)); EXIT_ON_ERROR(err, ( "Fcast: ERROR, mcl_ctl failed for TX_PROFILE\n")) } if (txprof_dt_size > 0) { /* must be after TX_PROFILE */ err += mcl_ctl(id, MCL_OPT_DATAGRAM_SIZE, (void*)&txprof_dt_size, sizeof(txprof_dt_size)); EXIT_ON_ERROR(err, ( "Fcast: ERROR, mcl_ctl failed for DATAGRAM_SIZE %d\n", txprof_dt_size)) } if (txprof_rate > 0) { /* must be after TX_PROFILE */ err += mcl_ctl(id, MCL_OPT_TX_RATE, (void*)&txprof_rate, sizeof(txprof_rate)); EXIT_ON_ERROR(err, ( "Fcast: ERROR, mcl_ctl failed for TX_RATE %d\n", txprof_rate)) } #if defined(ALC) if (levels > 0) { err += mcl_ctl(id, MCL_OPT_LAYER_NB, (void*)&levels, sizeof(int)); EXIT_ON_ERROR(err, ("Fcast: ERROR, mcl_ctl failed for LAYER_NB\n")) } #endif /* RM_PROTOCOL */ if (port > 0) { /* in host format! */ err += mcl_ctl(id, MCL_OPT_PORT, (void*)&port, sizeof(port)); EXIT_ON_ERROR(err, ("Fcast: ERROR, mcl_ctl failed for PORT\n")) } if (addr > 0) { /* in host format! */ err += mcl_ctl(id, MCL_OPT_ADDR, (void*)&addr, sizeof(addr)); EXIT_ON_ERROR(err, ("Fcast: ERROR, mcl_ctl failed for ADDR\n")) } if (mcast_if > 0) { /* in host format! */ err += mcl_ctl(id, MCL_OPT_NETIF, (void*)&mcast_if, sizeof(mcast_if)); EXIT_ON_ERROR(err, ("Fcast: ERROR, mcl_ctl failed for NETIF\n")) } #if defined(ALC) if (demux_label > 0) { err += mcl_ctl(id, MCL_OPT_DEMUX_LABEL, (void*)&demux_label, sizeof(demux_label)); EXIT_ON_ERROR(err, ( "Fcast: ERROR, mcl_ctl failed for DEMUX_LABEL\n")) } #endif /* RM_PROTOCOL */ if (ttl > 0) { err += mcl_ctl(id, MCL_OPT_TTL, (void*)&ttl, sizeof(ttl)); EXIT_ON_ERROR(err, ( "Fcast: ERROR, mcl_ctl failed for TTL\n")) } #if defined(ALC) if (nb_tx > 1) { err += mcl_ctl(id, MCL_OPT_NB_OF_TX, (void*)&nb_tx, sizeof(nb_tx)); EXIT_ON_ERROR(err, ( "Fcast: ERROR, mcl_ctl failed for NB_OF_TX\n")) } #endif /* RM_PROTOCOL */ if (tmp_dir_set) { err += mcl_ctl(id, MCL_OPT_TMP_DIR, (void*)&tmp_dir, strlen(tmp_dir)); EXIT_ON_ERROR(err, ( "Fcast: ERROR, mcl_ctl failed for TMP_DIR \"%s\"\n", tmp_dir)) } #if defined(ALC) err += mcl_ctl(id, MCL_OPT_DELIVERY_MODE, (void*)&delivery_mode, sizeof(delivery_mode)); EXIT_ON_ERROR(err, ("Fcast: ERROR, mcl_ctl failed for DELIVERY_MODE\n")) #endif /* RM_PROTOCOL */ if (mode == SEND) /*sender */ FcastSend(); else if (mode == RECV) /* or receiver */ FcastRecv(); #ifdef WIN32 if (pause) { system("pause"); } WSACleanup(); #endif return 0; } void Usage (int argc, char *argv[]) { int err = 0; /* return value of mcl_ctl functions */ if (id == 0) { /* need an MCL endpoint first */ if ((id = mcl_open("r")) < 0) EXIT(("Fcast: Usage: ERROR, mcl_open failed\n")) } PRINT(("\nFCAST Multicast File Transfert Tool\n")) mcl_ctl(id, MCL_OPT_MOREABOUT, NULL, 0); EXIT_ON_ERROR(err, ("Fcast: Usage: mcl_ctl failed for MOREABOUT\n")) PRINT(("\n\nUsage: %s [options] file|directory (in recursive mode)\n", argv[0])) PRINT((" COMMON OPTIONS\n")) PRINT((" -h[elp] this help\n")) PRINT((" -send or -recv choose Fcast mode: sender or receiver.\n")) PRINT((" -an[/p] set uni/multicast address or name to n and\n")) PRINT((" port number to p (default 127.0.0.1/%d)\n", port)) PRINT((" -ifn the network interface to use is the one attached to the\n")) PRINT((" local address n (only used on multi-homed hosts/routers)\n")) #if defined(ALC) PRINT((" -demuxn set the LCT Transport Session Id (TSI) to n (default 0)\n")) PRINT((" - at a sender TSI is included in each packet sent\n")) PRINT((" - at a receiver {src_addr; TSI} is used for packet filtering\n")) PRINT((" -ln set number of layers to n\n")) PRINT((" -singlelayer optimize transmissions for single layer.\n")) PRINT((" must be set by both sender/receiver!\n")) #elif defined(NORM) /* no equivalent */ #endif /* RM_PROTOCOL */ PRINT((" -vn set (MCL) verbosity level to n (add statistics too)\n")) PRINT((" -statn set (MCL) statistic level to n (0: none, 1: final, 2: all)\n")) PRINT((" -silent silent mode\n")) PRINT((" -tmpdir the temporary directory is dir (string)\n")) PRINT((" (unix default: \"/tmp\")\n")) PRINT((" -plow tx profile for Low Speed Internet\n")) PRINT((" -pmed tx profile for Med Speed Internet (default)\n")) PRINT((" -phigh tx profile for High Speed Internet\n")) PRINT((" -plan tx profile for High Speed LAN\n")) PRINT((" -psize[/rate] manual tx profile specification,\n")) PRINT((" size is the datagram size (bytes) (used by sender/recv)\n")) PRINT((" rate is the base layer tx rate (bits/s) (used by sender)\n")) #if defined(ALC) PRINT((" -ospeed use it to optimize speed (default)\n")) PRINT((" -ospace use it to reduce the required memory at receivers\n")) PRINT((" -ocpu use it if receiver is CPU limited\n")) #elif defined(NORM) /* no equivalent */ #endif /* RM_PROTOCOL */ #ifdef WIN32 PRINT((" -P Request user input (pause) before exiting (for win console)\n")) #endif PRINT((" SENDER SPECIFIC OPTIONS\n")) PRINT((" -tn set the ttl (time to live) to n (default 1)\n")) PRINT((" -R use recursive mode\n")) #if defined(ALC) PRINT((" -cont continuous delivery mode (same as -repeat)\n")) PRINT((" also known as ``on-demand'' mode (default is ``push'')\n")) PRINT((" -repeatn repeat n times on each layer then stop\n")) PRINT((" ignored in ``on-demand mode''\n")) #elif defined(NORM) /* no equivalent */ #endif /* RM_PROTOCOL */ PRINT((" -fecn set FEC ratio to n (float, must be >= 1.0) (default 2.0)\n")) PRINT((" (NB: 1.0 means no FEC as this is the n/k ratio)\n")) #if defined(ALC) #if 0 // removed! PRINT((" -huge huge file(s) to transmit (i.e. >> memory size), use\n")) PRINT((" appropriate measures (default FALSE)\n")) //PRINT((" The optional n parameter is the number of packets per sequence.\n")) #endif #elif defined(NORM) /* no equivalent */ #endif /* RM_PROTOCOL */ PRINT((" RECEIVER SPECIFIC OPTIONS\n")) PRINT((" -srcn set the source address or name to n (default 0)\n")) PRINT((" {src_addr; TSI} is used for incoming packet filtering.\n")) PRINT((" -int|-never|-force set overwriting mode (interactive|never|force)\n")) #ifdef WIN32 system("pause"); #endif exit(0); } #if defined(ALC) /* * ALC version */ void ParseCommandLine (int argc, char *argv[]) { int c; char *OptList = "a:v:h:l:s:r:o:p:f:n:i:c:RPt:d:"; #ifdef SOLARIS extern char *optarg; #elif defined(WIN32) char *optarg = NULL; #endif if(argc < 2) Usage(argc, argv); #ifdef WIN32 while ((c = GetOption(argc, argv, OptList, &optarg)) != 0) #else while ((c = getopt(argc, argv, OptList)) != EOF) #endif { switch (c) { case 'a': if (*optarg) { /* process addr/port argument */ char rname[128]; /* remote name string */ char *p; strncpy(rname, optarg, sizeof(rname)); if ((p = strchr(rname, '/')) != NULL) { *p = '\0'; /* in host order */ port = (unsigned short)atoi(p+1); } /* * addr must be in host byte order, but * gethostbyname/inet_addr return network order */ if (isalpha((int)rname[0])) { if (gethostbyname(rname) == NULL) EXIT(("Fcast: ERROR, unknown host ""%s""\n", rname)) addr = ntohl(*(unsigned long *) ((gethostbyname(rname))->h_addr)); } else addr = ntohl(inet_addr(rname)); } else EXIT(( "Fcast: ERROR, bad argument -a%s\n", optarg)) break; case 'd': if (!strncmp(optarg, "emux", 4) && isdigit((int)*(optarg+4))) { demux_label = atoi(optarg+4); } else EXIT(("Fcast: ERROR, bad argument -d%s (NB: dont use space between -demux and value)\n", optarg)) break; case 'v': /* verbosity level */ if (isdigit((int)*optarg)) { verbose = atoi(optarg); if (verbose > 0) stats = 2; } else EXIT(("Fcast: ERROR, bad argument -v%s\n", optarg)) break; #if 0 case 'h': #ifdef NEVERDEF /* the full-featured version */ if (!strncmp(optarg, "uge", 3)) { if (strlen(optarg) > 3 && isdigit((int)*(optarg+3))) { tx_huge_file = atoi(optarg+3); } else { tx_huge_file = 1; } } #else /* NEVERDEF */ /* the simplified version */ if (!strncmp(optarg, "uge", 3)) { tx_huge_file = 1; } #endif /* NEVERDEF */ else Usage(argc, argv); break; #endif case 'l': /* number of levels */ if (isdigit((int)*optarg)) { if (single_layer) EXIT(("Fcast: ERROR, argument -l%s is incompatible with single_layer mode\n", optarg)) levels = atoi(optarg); } else EXIT(("Fcast: ERROR, bad argument -l%s\n", optarg)) break; case 't': /* ttl value */ if (isdigit((int)*optarg)) ttl = atoi(optarg); else if(!strncmp(optarg, "mp", 2)) { strncpy(tmp_dir, optarg+2, sizeof(tmp_dir)); tmp_dir[MAX_FILE_NAME_LEN-1] = 0; /* add final / and \0 if not already present */ if (tmp_dir[strlen(tmp_dir)-1] != '/' && strlen(tmp_dir) <= MAX_FILE_NAME_LEN-2) strcat(tmp_dir, "/"); tmp_dir_set = 1; } else EXIT(("Fcast: ERROR, bad argument -t%s\n", optarg)) break; case 's': if (!strcmp(optarg, "end")) mode = SEND; else if (!strncmp(optarg, "rc", 2)) { /* process addr argument */ char rname[128]; /* remote name string */ strncpy(rname, (optarg + 2), sizeof(rname)); /* * addr must be in host byte order, but * gethostbyname/inet_addr return network order */ if (isalpha((int)rname[0])) { if (gethostbyname(rname) == NULL) EXIT(("Fcast: ERROR, unknown host ""%s""\n", rname)) src_addr = ntohl(*(unsigned long *) ((gethostbyname(rname))->h_addr)); } else src_addr = ntohl(inet_addr(rname)); } else if(!strcmp(optarg, "ilent")) silent = 1; else if(!strncmp(optarg, "tat", 3)) { if (isdigit((int)*(optarg+3))) stats = atoi(optarg+3); else EXIT(("Fcast: ERROR, bad argument -s%s\n (NB: dont use space between -stat and value)", optarg)) } else if(!strncmp(optarg, "inglelayer", 10)) { single_layer = 1; /* set/reset the associated parameters */ levels = 1; } else EXIT(("Fcast: ERROR, bad argument -s%s\n", optarg)) break; case 'r': if (!strcmp(optarg, "ecv")) mode = RECV; else if(!strncmp(optarg, "epeat", 5) && isdigit((int)*(optarg+5))) { /* nb of tx is original_tx + repeat_nb*/ nb_tx = atoi(optarg+5) + 1; } else EXIT(("Fcast: ERROR, bad argument -r%s (NB: dont use space between -repeat and value)\n", optarg)) break; case 'o': if (!strcmp(optarg, "space")) { optimode = OPTIMIZE_SPACE; } else if(!strcmp(optarg, "speed")) { optimode = OPTIMIZE_SPEED; } else if(!strcmp(optarg, "cpu")) { optimode = OPTIMIZE_CPU; } else { EXIT(("Fcast: ERROR, bad argument -o%s\n", optarg)) } break; case 'p': if (txprof_set) { EXIT(("Fcast: ERROR, tx profile can be set only once\n")) } else { txprof_set = 1; } if (!strcmp(optarg, "low")) { txprof_mode = MCL_TX_PROFILE_LOW_RATE_INTERNET; } else if(!strcmp(optarg, "med")) { txprof_mode = MCL_TX_PROFILE_MID_RATE_INTERNET; } else if(!strcmp(optarg, "high")) { txprof_mode = MCL_TX_PROFILE_HIGH_SPEED_INTERNET; } else if(!strcmp(optarg, "lan")) { txprof_mode = MCL_TX_PROFILE_HIGH_SPEED_LAN; single_layer = 1; /* true in a LAN! */ } else if (*optarg) { /* process size/rate argument */ char str[128]; /* size/rate string */ char *p; int rate = 0; strncpy(str, optarg, sizeof(str)); str[127] = '\0'; if ((p = strchr(str, '/')) != NULL) { *p = '\0'; /* cut str into two strings*/ rate = (int)atoi(p+1); if (rate <= 0) { EXIT(("Fcast: ERROR, invalid rate for argument -p%s\n", optarg)) } } txprof_dt_size = (int)atoi(str); if (txprof_dt_size <= 0) { EXIT(("Fcast: ERROR, invalid size for argument -p%s\n", optarg)) } if (rate > 0) { txprof_rate = (int)((float)rate / ((float)txprof_dt_size * 8.0)); /* no less than 1 pkt/s */ txprof_rate = max(1, txprof_rate); } /*PRINT(("fcast: txprof_dt_size=%d, rate=%d, txprof_rate=%d\n", txprof_dt_size, rate, txprof_rate))*/ } else { EXIT(("Fcast: ERROR, bad argument -p%s\n", optarg)) } break; case 'R': recursive = 1; break; case 'P': #ifdef WIN32 pause = 1; #endif break; case 'f': if (!strncmp(optarg, "ec", 2)) { if (isdigit((int)*(optarg+2))) fec_ratio = (float)atof(optarg+2); else EXIT(("Fcast: ERROR, bad argument -f%s (NB: dont use space between -fec and value)\n", optarg)) } else if (!strcmp(optarg, "orce")) { overwrite = ALWAYS; } else EXIT(("Fcast: ERROR, bad argument -f%s\n", optarg)) break; case 'c': if (!strcmp(optarg, "ont")) { delivery_mode = DEL_MODE_ON_DEMAND; } else EXIT(("Fcast: ERROR, bad argument -c%s\n", optarg)) break; case 'i': if (!strcmp(optarg, "nt")) { overwrite = PROMPT; } else if (!strncmp(optarg, "f", 1)) { if (*(optarg+1)) { /* process addr argument */ char rname[128];/* remote name string */ strncpy(rname, optarg+1, sizeof(rname)); /* * addr must be in host byte order, but * gethostbyname/inet_addr return network order */ if (isalpha((int)rname[0])) { if (gethostbyname(rname) == NULL) EXIT(("Fcast: ERROR, unknown host ""%s""\n", rname)) mcast_if = ntohl(*(unsigned long *) ((gethostbyname(rname))->h_addr)); } else mcast_if = ntohl(inet_addr(rname)); } else EXIT(("Fcast: ERROR, bad argument -i%s (NB: dont use space between -if and addr)\n", optarg)) } else EXIT(("Fcast: ERROR, bad argument -i%s\n", optarg)) break; case 'n': if (!strcmp(optarg, "ever")) { overwrite = NEVER; } else EXIT(("Fcast: ERROR, bad argument -n%s\n", optarg)) break; #ifdef WIN32 case 1: break; #endif default: /* * NB: getopt returns '?' when finding an * unknown argument; avoid the following * error msg in that case */ if (c != '?') PRINT(("bad argument %c\n", c)) Usage(argc, argv); break; } } /* last arg is file name */ ASSERT((argv[argc-1])) if( mode == SEND ) { strncpy(fileparam, argv[argc-1], MAX_PATH+MAX_FILENAME); } #if 0 /* if single_layer mode is not set, the nb of fec layers * must be integer. Enforce it... */ if (!single_layer) { int tmp_fec_ratio; tmp_fec_ratio = (int)fec_ratio; fec_ratio = (float)tmp_fec_ratio; } #endif } #elif defined(NORM) /* * NORM version */ void ParseCommandLine (int argc, char *argv[]) { int c; char *OptList = "a:v:s:r:p:f:n:i:RPt:"; #ifdef SOLARIS extern char *optarg; #elif defined(WIN32) char *optarg = NULL; #endif if(argc < 2) Usage(argc, argv); #ifdef WIN32 while ((c = GetOption(argc, argv, OptList, &optarg)) != 0) #else while ((c = getopt(argc, argv, OptList)) != EOF) #endif { switch (c) { case 'a': if (*optarg) { /* process addr/port argument */ char rname[128]; /* remote name string */ char *p; strncpy(rname, optarg, sizeof(rname)); if ((p = strchr(rname, '/')) != NULL) { *p = '\0'; /* in host order */ port = (unsigned short)atoi(p+1); } /* * addr must be in host byte order, but * gethostbyname/inet_addr return network order */ if (isalpha((int)rname[0])) { if (gethostbyname(rname) == NULL) EXIT(("Fcast: ERROR, unknown host ""%s""\n", rname)) addr = ntohl(*(unsigned long *) ((gethostbyname(rname))->h_addr)); } else addr = ntohl(inet_addr(rname)); } else EXIT(( "Fcast: ERROR, bad argument -a%s\n", optarg)) break; case 'v': /* verbosity level */ if (isdigit((int)*optarg)) { verbose = atoi(optarg); if (verbose > 0) stats = 2; } else EXIT(("Fcast: ERROR, bad argument -v%s\n", optarg)) break; case 't': /* ttl value */ if (isdigit((int)*optarg)) ttl = atoi(optarg); else if(!strncmp(optarg, "mp", 2)) { strncpy(tmp_dir, optarg+2, sizeof(tmp_dir)); tmp_dir[MAX_FILE_NAME_LEN-1] = 0; /* add final / and \0 if not already present */ if (tmp_dir[strlen(tmp_dir)-1] != '/' && strlen(tmp_dir) <= MAX_FILE_NAME_LEN-2) strcat(tmp_dir, "/"); tmp_dir_set = 1; } else EXIT(("Fcast: ERROR, bad argument -t%s\n", optarg)) break; case 's': if (!strcmp(optarg, "end")) mode = SEND; else if (!strncmp(optarg, "rc", 2)) { /* process addr argument */ char rname[128]; /* remote name string */ strncpy(rname, (optarg + 2), sizeof(rname)); /* * addr must be in host byte order, but * gethostbyname/inet_addr return network order */ if (isalpha((int)rname[0])) { if (gethostbyname(rname) == NULL) EXIT(("Fcast: ERROR, unknown host ""%s""\n", rname)) src_addr = ntohl(*(unsigned long *) ((gethostbyname(rname))->h_addr)); } else src_addr = ntohl(inet_addr(rname)); } else if(!strcmp(optarg, "ilent")) silent = 1; else if(!strncmp(optarg, "tat", 3)) { if (isdigit((int)*(optarg+3))) stats = atoi(optarg+3); else EXIT(("Fcast: ERROR, bad argument -s%s\n (NB: dont use space between -stat and value)", optarg)) } else EXIT(("Fcast: ERROR, bad argument -s%s\n", optarg)) break; case 'r': if (!strcmp(optarg, "ecv")) mode = RECV; else EXIT(("Fcast: ERROR, bad argument -r%s (NB: dont use space between -repeat and value)\n", optarg)) break; case 'p': if (!strcmp(optarg, "low")) { txprof_mode = MCL_TX_PROFILE_LOW_RATE_INTERNET; } else if(!strcmp(optarg, "med")) { txprof_mode = MCL_TX_PROFILE_MID_RATE_INTERNET; } else if(!strcmp(optarg, "high")) { txprof_mode = MCL_TX_PROFILE_HIGH_SPEED_INTERNET; } else if(!strcmp(optarg, "lan")) { txprof_mode = MCL_TX_PROFILE_HIGH_SPEED_LAN; } else { EXIT(("Fcast: ERROR, bad argument -p%s\n", optarg)) } break; case 'R': recursive = 1; break; case 'P': #ifdef WIN32 pause = 1; #endif break; case 'f': if (!strncmp(optarg, "ec", 2)) { if (isdigit((int)*(optarg+2))) fec_ratio = (float)atof(optarg+2); else EXIT(("Fcast: ERROR, bad argument -f%s (NB: dont use space between -fec and value)\n", optarg)) } else if (!strcmp(optarg, "orce")) { overwrite = ALWAYS; } else EXIT(("Fcast: ERROR, bad argument -f%s\n", optarg)) break; case 'i': if (!strcmp(optarg, "nt")) { overwrite = PROMPT; } else if (!strncmp(optarg, "f", 1)) { if (*(optarg+1)) { /* process addr argument */ char rname[128];/* remote name string */ strncpy(rname, optarg+1, sizeof(rname)); /* * addr must be in host byte order, but * gethostbyname/inet_addr return network order */ if (isalpha((int)rname[0])) { if (gethostbyname(rname) == NULL) EXIT(("Fcast: ERROR, unknown host ""%s""\n", rname)) mcast_if = ntohl(*(unsigned long *) ((gethostbyname(rname))->h_addr)); } else mcast_if = ntohl(inet_addr(rname)); } else EXIT(( "Fcast: ERROR, bad argument -i%s (NB: dont use space between -if and addr)\n", optarg)) } else EXIT(("Fcast: ERROR, bad argument -i%s\n", optarg)) break; case 'n': if (!strcmp(optarg, "ever")) { overwrite = NEVER; } else EXIT(("Fcast: ERROR, bad argument -n%s\n", optarg)) break; #ifdef WIN32 case 1: break; #endif default: /* * NB: getopt returns '?' when finding an * unknown argument; avoid the following * error msg in that case */ if (c != '?') PRINT(("bad argument %c\n", c)) Usage(argc, argv); break; } } /* last arg is file name */ ASSERT((argv[argc-1])) if( mode == SEND ) { strncpy(fileparam, argv[argc-1], MAX_PATH+MAX_FILENAME); } } #endif /* RM_PROTOCOL */ /* * we received a SIGINT... */ void interrupted (void) { static int abort_in_progress = 0; if (!abort_in_progress) { abort_in_progress = 1; PRINT(("fcast: aborted, call mcl_abort()\n")); mcl_abort(id); PRINT(("fcast: aborted, exit\n")); exit(2); } /* else do nothing */ }