# #include #include /* NOTE To compile cc -c ping.c To load ping.ld To run ping <-g> | <-i> | <-t> host */ /* icmpd signal info lock file contains process id for icmpd */ #define TFTPLCK "/icmpd/lock" #define UINRPT 16 /* error handling */ #define OK 0 #define ERR -1 #define EPARM 1 #define ECFILE 2 #define EWAIT 3 #define ESHOW 4 #define ESTFTPD 5 extern int errno; extern char *sys_errlist[]; int errnum; #define retok(value) { errnum = OK; return(value); } #define reterr(ecode) { errnum = ecode; return(ERR); } /* No. bytes in internet name */ #define INSZ 4 /* specs from user for icmpd command file */ union { char sp_hinet[INSZ]; /* foreign host internet addr */ long sp_hname; } outsp; long resolve_name(); /* command file info */ #define CFNAME "/icmpd/rcmdaxxxxx" #define CFLNAME "/icmpd/Rcmdaxxxxx" #define NCMDLINS 2 struct cmdfl { char cf_name[sizeof(CFNAME)]; char cf_lname[sizeof(CFNAME)]; int cf_leng; } cmdfile; FILE *ioptr; int gflag; /* ggp request */ int iflag; /* icmp request */ int tflag; /* timestamp request */ /* inode info about command file */ struct inode inodebf; #define SLEEPSEC 1 #define MAXMINS 10 #define LINESIZE 128 main(argc, argv) int argc; char *argv[]; { struct cmdfl *cmdptr; int nsecs, tcode; extern int die(); char *hostname; cmdptr = &cmdfile; if (chkpars(argc, argv, &hostname) == ERR) exit(errnum); if (mkcmd(cmdptr) == ERR) exit(errnum); signal(2, &die); if (sigicmp(cmdptr) == ERR) delexit(cmdptr, errnum); printf("Pinging %s at %o,%o,%o,%o: ", hostname, outsp.sp_hinet[0] & 0377, outsp.sp_hinet[1] & 0377, outsp.sp_hinet[2] & 0377, outsp.sp_hinet[3] & 0377); if ((nsecs = icmpwt(cmdptr)) == ERR) delexit(cmdptr, errnum); tcode = showend(hostname, cmdptr, nsecs); delexit(cmdptr, tcode); } die() { delexit(&cmdfile, -1); } chkpars(argc, argv, nameptr) int argc; char *argv[]; char **nameptr; { int i; if (argc < 2 || argc >4) { errarg("wrong number of arguments"); reterr( EPARM ); } for (i = 1; i < argc; i++) if (argv[i][0] == '-') switch (argv[i][1]) { case 'g': gflag++; break; case 'i': iflag++; break; case 't': tflag++; break; default: errarg("bad flag"); reterr(EPARM); } else { *nameptr = argv[i]; outsp.sp_hname = resolve_name(argv[i]); if (outsp.sp_hname == 0L) { printf ("No such host as %s\n", argv[i]); reterr(EPARM); } } retok( OK ); } errarg(msg) char *msg; { printf("Ping %s\n",msg); printf("Ping usage: ping [-g]|[-i]|[-t] \n"); retok( OK ); } mkcmd(cmdptr) struct cmdfl *cmdptr; { struct inode *statptr; mktmpn(cmdptr); if ( (ioptr = fopen(cmdptr->cf_name,"w")) == NULL) { printf("Ping cannot open temp. command file %s\n", cmdptr->cf_name); unlink(cmdptr->cf_name); reterr(ECFILE); } if (gflag) putsnl("ggp echo",ioptr); else if (tflag) putsnl("timestamp",ioptr); else putsnl("icmp echo",ioptr); fprintf(ioptr,"%o,%o,%o,%o\n",outsp.sp_hinet[0] & 0377, outsp.sp_hinet[1] & 0377,outsp.sp_hinet[2] & 0377, outsp.sp_hinet[3] & 0377); fclose(ioptr); statptr = &inodebf; stat(cmdptr->cf_name, statptr); cmdptr->cf_leng = statptr->size1; retok( OK ); } mktmpn(cmdptr) struct cmdfl *cmdptr; { int pid; int i, ip; char ch; strcpy(cmdptr->cf_name,CFNAME); strcpy(cmdptr->cf_lname,CFLNAME); ip = sizeof(CFNAME); pid = getpid(); for ( i = 2; i <= 6; i++) { ch = (pid & 07) + '0'; cmdptr->cf_name[ip-i] = ch; cmdptr->cf_lname[ip-i] = ch; pid =>> 3; } retok( OK ); } puts1(chp, iop) char *chp; FILE *iop; { char *s; for (s = chp; *s; s++) putc(*s, iop); retok( OK ); } putsnl(chp, iop) char *chp; FILE *iop; { char *s; for (s = chp; *s; s++) putc(*s, iop); putc('\n', iop); retok( OK ); } puthex(chp, chn, iop) char *chp; int chn; FILE *iop; { static char hexstr[] "0123456789ABCDEF"; char buf[2]; register int i, tmp; for (i = 0; i < chn; i++) { tmp = *chp++; buf[1] = hexstr[(tmp & 0xf)]; buf[0] = hexstr[((tmp >> 4) & 0xf)]; putc(buf[0], iop); putc(buf[1], iop); } putc('\n',iop); retok(OK); } /* * sigicmp * read icmp daemon's process id from lock file * link Rcmd name to identify command file for icmpd * signal icmpd */ sigicmp(cmdptr) struct cmdfl *cmdptr; { int lockfl; char procch[16]; int procid; if ( (lockfl = open(TFTPLCK, 0)) == ERR) { printf("Ping icmp daemon not alive\n"); reterr( ESTFTPD ); } read(lockfl, procch, 16); close(lockfl); procid = atoi(procch); if (procid <= 0) { printf("Ping cannot signal icmp daemon\n"); reterr( ESTFTPD ); } link(cmdptr->cf_name, cmdptr->cf_lname); if (kill(procid, UINRPT) == ERR) { printf("Ping cannot signal icmp daemon\n"); reterr( ESTFTPD ); } retok( OK ); } icmpwt(cmdptr) struct cmdfl *cmdptr; { struct inode *statptr; int nsecs; nsecs = 0; statptr = &inodebf; stat(cmdptr->cf_name, statptr); while (cmdptr->cf_leng == statptr->size1) { sleep(SLEEPSEC); if (stat(cmdptr->cf_name, statptr) == ERR) { printf("Ping error %d on status call for file %s\n", errno, cmdptr->cf_name); reterr( EWAIT ); } nsecs += SLEEPSEC; if (nsecs > (60 * MAXMINS)) { printf("Ping waited for %d minutes for transfer to complete, will quit waiting\n",(nsecs/60)); reterr( EWAIT ); } } retok( nsecs ); } showend(hostname, cmdptr, nsec) char *hostname; struct cmdfl *cmdptr; int nsec; { int i; char line[LINESIZE + 1]; char *p; int tcode, epcode; long size; float baud; if ( (ioptr = fopen(cmdptr->cf_name, "r")) == NULL) { printf("Ping cannot open %s for reading\n",cmdptr->cf_name); reterr( ESHOW ); } for (i = 0; i <= (NCMDLINS); i++) fgets(line, LINESIZE, ioptr); sscanf (line, "%*[^=]=%d\n", &tcode); if (tcode > 0) { printf ("system error %d\n%s\n", tcode, sys_errlist[tcode]); retok(tcode); } else while (fgets(line, LINESIZE, ioptr) != NULL) printf("%s",line); retok(tcode); } delexit(cmdptr, tcode) struct cmdfl *cmdptr; int tcode; { unlink(cmdptr->cf_name); unlink(cmdptr->cf_lname); exit(tcode); }