/* This file is in the public domain. */ #include #include #include #include #include #include #include #include extern const char *__progname; /* * Main program for scget, the get-data client. This is simple: crack * the arglist, open the network connection, and run the protocol. * * Usage: $0 [-h] host [-p] port start stop repo [repo [repo ...]] * * host and port are the address and port number to contact the daemon * on. start and stop are the endpoints of the timestamp interval of * interest. The rest of the arglist is repository names. * * start and stop are put into the network protocol directly as * strings; it is our caller's responsibility to use values which are * syntactic and meaningful. * * host may be marked with -h and port with -p. though this is unlikely * to be necessary. */ static const char *host = 0; static const char *port = 0; static int restac; static char **restav; static int net; static void handleargs(int ac, char **av) { int skip; int errs; skip = 0; errs = 0; for (ac--,av++;ac;ac--,av++) { if (skip > 0) { skip --; continue; } if (**av != '-') { if (! host) { host = *av; } else if (! port) { port = *av; } else { restac = ac; restav = av; break; } continue; } if (0) { needarg:; fprintf(stderr,"%s: %s needs a following argument\n",__progname,*av); errs = 1; continue; } #define WANTARG() do { if (++skip >= ac) goto needarg; } while (0) if (!strcmp(*av,"-h")) { WANTARG(); host = av[skip]; continue; } if (!strcmp(*av,"-p")) { WANTARG(); host = av[skip]; continue; } if (!strcmp(*av,"--")) { restac = ac - 1; restav = av + 1; break; } #undef WANTARG fprintf(stderr,"%s: unrecognized option `%s'\n",__progname,*av); errs = 1; } if (restac < 3) { fprintf(stderr,"%s: too few arguments (must be at least one repository name)\n",__progname); errs = 1; } if (!host || !port) { fprintf(stderr,"%s: host and port must be specified\n",__progname); errs = 1; } if (errs) exit(1); } static void open_net(void) { struct addrinfo hints; struct addrinfo *ai0; struct addrinfo *ai; int e; char ihost[NI_MAXHOST]; char iserv[NI_MAXSERV]; const char *emsg; hints.ai_flags = 0; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; hints.ai_addrlen = 0; hints.ai_addr = 0; hints.ai_canonname = 0; hints.ai_next = 0; e = getaddrinfo(host,port,&hints,&ai0); if (e) { fprintf(stderr,"%s: %s%s%s: %s\n",__progname,host?:"",(host&&port)?"/":"",port?:"",gai_strerror(e)); exit(1); } for (ai=ai0;ai;ai=ai->ai_next) { net = socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol); if (net < 0) { fprintf(stderr,"%s: socket (af %d): %s\n",__progname,ai->ai_family,strerror(errno)); continue; } if (connect(net,ai->ai_addr,ai->ai_addrlen) >= 0) return; emsg = strerror(errno); e = getnameinfo(ai->ai_addr,ai->ai_addrlen,&ihost[0],sizeof(ihost),&iserv[0],sizeof(iserv),NI_NUMERICHOST|NI_NUMERICSERV); if (e) { fprintf(stderr,"%s: connect [can't get numeric address: %s]: %s",__progname,gai_strerror(e),emsg); } else { fprintf(stderr,"%s: connect [%s/%s]: %s",__progname,&ihost[0],&iserv[0],emsg); } close(net); } fprintf(stderr,"%s: can't open network connection\n",__progname); exit(1); } static void protocol(void) { int ax; FILE *f; char *b; int a; int l; int c; int nc; int end[3]; int first; f = fdopen(net,"r+"); fprintf(f,"fetch%c",0); for (ax=2;ax= a) b = realloc(b,a=l+8); b[l++] = c; if (c == '\0') { if (first) { if (l > 1) { fprintf(stderr,"%s: %s\n",__progname,b); exit(1); } first = 0; l = 0; nc = 0; continue; } if ((l == 1) && (nc == 0)) break; end[nc++] = l; if (nc >= 3) { printf("%s %s %s\n",b,b+end[0],b+end[1]); nc = 0; l = 0; } } } } int main(int, char **); int main(int ac, char **av) { handleargs(ac,av); open_net(); protocol(); return(0); }