int GetSerialPortNumber(const char *desc)
{
    assert(desc != NULL);

    std::vector<serial::PortInfo> ports = serial::list_ports();
    if (ports.empty())
    {
        return -1;
    }

    std::vector<serial::PortInfo>::const_iterator it = std::find_if(ports.cbegin(), ports.cend(), 
        [&desc](const serial::PortInfo &portInfo) -> bool
        {
            return portInfo.description.find(desc) != std::string::npos;
        });

    if (it != ports.cend())
    {
        return PortNumber(it->port);
    }
    else
    {
        return -1;
    }
}
Example #2
0
// Return stringified port number
std::string EndpointAddress::Port()
{
        unsigned short port = PortNumber();
        std::string str;
        std::ostringstream o;

        if (!(o << port))
                return "???";
        return o.str();
}
Example #3
0
int
MainCommand(struct cmd_syndesc *as, void *arock)
{
    register int i;
    osi_socket s;
    int j;
    struct sockaddr_in taddr;
    afs_int32 host;
    struct in_addr hostAddr;
    short port;
    struct hostent *th;
    register afs_int32 code;
    int nodally;
    int allconns;
    int rxstats;
    int onlyClient, onlyServer;
    afs_int32 onlyHost;
    short onlyPort;
    int onlyAuth;
    int flag;
    int dallyCounter;
    int withSecStats;
    int withAllConn;
    int withRxStats;
    int withWaiters;
    int withIdleThreads;
    int withWaited;
    int withPeers;
    int withPackets;
    struct rx_debugStats tstats;
    char *portName, *hostName;
    char hoststr[20];
    struct rx_debugConn tconn;
    short noConns;
    short showPeers;
    short showLong;
    int version_flag;
    char version[64];
    afs_int32 length = 64;

    afs_uint32 supportedDebugValues = 0;
    afs_uint32 supportedStatValues = 0;
    afs_uint32 supportedConnValues = 0;
    afs_uint32 supportedPeerValues = 0;
    afs_int32 nextconn = 0;
    afs_int32 nextpeer = 0;

    nodally = (as->parms[2].items ? 1 : 0);
    allconns = (as->parms[3].items ? 1 : 0);
    rxstats = (as->parms[4].items ? 1 : 0);
    onlyServer = (as->parms[5].items ? 1 : 0);
    onlyClient = (as->parms[6].items ? 1 : 0);
    version_flag = (as->parms[10].items ? 1 : 0);
    noConns = (as->parms[11].items ? 1 : 0);
    showPeers = (as->parms[12].items ? 1 : 0);
    showLong = (as->parms[13].items ? 1 : 0);

    if (as->parms[0].items)
	hostName = as->parms[0].items->data;
    else
	hostName = NULL;

    if (as->parms[1].items)
	portName = as->parms[1].items->data;
    else
	portName = NULL;

    if (as->parms[7].items) {
	char *name = as->parms[7].items->data;
	if ((onlyPort = PortNumber(name)) == -1)
	    onlyPort = PortName(name);
	if (onlyPort == -1) {
	    printf("rxdebug: can't resolve port name %s\n", name);
	    exit(1);
	}
    } else
	onlyPort = -1;

    if (as->parms[8].items) {
	char *name = as->parms[8].items->data;
	struct hostent *th;
	th = hostutil_GetHostByName(name);
	if (!th) {
	    printf("rxdebug: host %s not found in host table\n", name);
	    exit(1);
	}
	memcpy(&onlyHost, th->h_addr, sizeof(afs_int32));
    } else
	onlyHost = -1;

    if (as->parms[9].items) {
	char *name = as->parms[9].items->data;
	if (strcmp(name, "clear") == 0)
	    onlyAuth = 0;
	else if (strcmp(name, "auth") == 0)
	    onlyAuth = 1;
	else if (strcmp(name, "crypt") == 0)
	    onlyAuth = 2;
	else if ((strcmp(name, "null") == 0) || (strcmp(name, "none") == 0)
		 || (strncmp(name, "noauth", 6) == 0)
		 || (strncmp(name, "unauth", 6) == 0))
	    onlyAuth = -1;
	else {
	    fprintf(stderr, "Unknown authentication level: %s\n", name);
	    exit(1);
	}
    } else
	onlyAuth = 999;

    /* lookup host */
    if (hostName) {
	th = hostutil_GetHostByName(hostName);
	if (!th) {
	    printf("rxdebug: host %s not found in host table\n", hostName);
	    exit(1);
	}
	memcpy(&host, th->h_addr, sizeof(afs_int32));
    } else
	host = htonl(0x7f000001);	/* IP localhost */

    if (!portName)
	port = htons(7000);	/* default is fileserver */
    else {
	if ((port = PortNumber(portName)) == -1)
	    port = PortName(portName);
	if (port == -1) {
	    printf("rxdebug: can't resolve port name %s\n", portName);
	    exit(1);
	}
    }

    dallyCounter = 0;

    hostAddr.s_addr = host;
    afs_inet_ntoa_r(hostAddr.s_addr, hoststr);
    printf("Trying %s (port %d):\n", hoststr, ntohs(port));
    s = socket(AF_INET, SOCK_DGRAM, 0);
    taddr.sin_family = AF_INET;
    taddr.sin_port = 0;
    taddr.sin_addr.s_addr = 0;
#ifdef STRUCT_SOCKADDR_HAS_SA_LEN
    taddr.sin_len = sizeof(struct sockaddr_in);
#endif
    code = bind(s, (struct sockaddr *)&taddr, sizeof(struct sockaddr_in));
    if (code) {
	perror("bind");
	exit(1);
    }

    if (version_flag) {

	code = rx_GetServerVersion(s, host, port, length, version);
	if (code < 0) {
	    printf("get version call failed with code %d, errno %d\n", code,
		   errno);
	    exit(1);
	}
	printf("AFS version: %s\n", version);
	fflush(stdout);

	exit(0);

    }


    code = rx_GetServerDebug(s, host, port, &tstats, &supportedDebugValues);
    if (code < 0) {
	printf("getstats call failed with code %d\n", code);
	exit(1);
    }

    withSecStats = (supportedDebugValues & RX_SERVER_DEBUG_SEC_STATS);
    withAllConn = (supportedDebugValues & RX_SERVER_DEBUG_ALL_CONN);
    withRxStats = (supportedDebugValues & RX_SERVER_DEBUG_RX_STATS);
    withWaiters = (supportedDebugValues & RX_SERVER_DEBUG_WAITER_CNT);
    withIdleThreads = (supportedDebugValues & RX_SERVER_DEBUG_IDLE_THREADS);
    withWaited = (supportedDebugValues & RX_SERVER_DEBUG_WAITED_CNT);
    withPeers = (supportedDebugValues & RX_SERVER_DEBUG_ALL_PEER);
    withPackets = (supportedDebugValues & RX_SERVER_DEBUG_PACKETS_CNT);

    if (withPackets)
        printf("Free packets: %d/%d, packet reclaims: %d, calls: %d, used FDs: %d\n",
               tstats.nFreePackets, tstats.nPackets, tstats.packetReclaims, 
               tstats.callsExecuted, tstats.usedFDs);
    else
        printf("Free packets: %d, packet reclaims: %d, calls: %d, used FDs: %d\n",
               tstats.nFreePackets, tstats.packetReclaims, tstats.callsExecuted,
               tstats.usedFDs);
    if (!tstats.waitingForPackets)
	printf("not ");
    printf("waiting for packets.\n");
    if (withWaiters)
	printf("%d calls waiting for a thread\n", tstats.nWaiting);
    if (withIdleThreads)
	printf("%d threads are idle\n", tstats.idleThreads);
    if (withWaited)
	printf("%d calls have waited for a thread\n", tstats.nWaited);

    if (rxstats) {
	if (!withRxStats) {
	  noRxStats:
	    withRxStats = 0;
	    fprintf(stderr,
		    "WARNING: Server doesn't support retrieval of Rx statistics\n");
	} else {
	    struct rx_statistics rxstats;

	    /* should gracefully handle the case where rx_stats grows */
	    code =
		rx_GetServerStats(s, host, port, &rxstats,
				  &supportedStatValues);
	    if (code < 0) {
		printf("rxstats call failed with code %d\n", code);
		exit(1);
	    }
	    if (code != sizeof(rxstats)) {
		struct rx_debugIn debug;
		memcpy(&debug, &rxstats, sizeof(debug));
		if (debug.type == RX_DEBUGI_BADTYPE)
		    goto noRxStats;
		printf
		    ("WARNING: returned Rx statistics of unexpected size (got %d)\n",
		     code);
		/* handle other versions?... */
	    }

	    rx_PrintTheseStats(stdout, &rxstats, sizeof(rxstats),
			       tstats.nFreePackets, tstats.version);
	}
    }

    if (!noConns) {
	if (allconns) {
	    if (!withAllConn)
		fprintf(stderr,
			"WARNING: Server doesn't support retrieval of all connections,\n         getting only interesting instead.\n");
	}

	if (onlyServer)
	    printf("Showing only server connections\n");
	if (onlyClient)
	    printf("Showing only client connections\n");
	if (onlyAuth != 999) {
	    static char *name[] =
		{ "unauthenticated", "rxkad_clear", "rxkad_auth",
		"rxkad_crypt"
	    };
	    printf("Showing only %s connections\n", name[onlyAuth + 1]);
	}
	if (onlyHost != -1) {
	    hostAddr.s_addr = onlyHost;
	    afs_inet_ntoa_r(hostAddr.s_addr, hoststr);
	    printf("Showing only connections from host %s\n",
		   hoststr);
	}
	if (onlyPort != -1)
	    printf("Showing only connections on port %u\n", ntohs(onlyPort));

	for (i = 0;; i++) {
	    code =
		rx_GetServerConnections(s, host, port, &nextconn, allconns,
					supportedDebugValues, &tconn,
					&supportedConnValues);
	    if (code < 0) {
		printf("getconn call failed with code %d\n", code);
		break;
	    }
	    if (tconn.cid == (afs_int32) 0xffffffff) {
		printf("Done.\n");
		break;
	    }

	    /* see if we're in nodally mode and all calls are dallying */
	    if (nodally) {
		flag = 0;
		for (j = 0; j < RX_MAXCALLS; j++) {
		    if (tconn.callState[j] != RX_STATE_NOTINIT
			&& tconn.callState[j] != RX_STATE_DALLY) {
			flag = 1;
			break;
		    }
		}
		if (flag == 0) {
		    /* this call looks too ordinary, bump skipped count and go
		     * around again */
		    dallyCounter++;
		    continue;
		}
	    }
	    if ((onlyHost != -1) && (onlyHost != tconn.host))
		continue;
	    if ((onlyPort != -1) && (onlyPort != tconn.port))
		continue;
	    if (onlyServer && (tconn.type != RX_SERVER_CONNECTION))
		continue;
	    if (onlyClient && (tconn.type != RX_CLIENT_CONNECTION))
		continue;
	    if (onlyAuth != 999) {
		if (onlyAuth == -1) {
		    if (tconn.securityIndex != 0)
			continue;
		} else {
		    if (tconn.securityIndex != 2)
			continue;
		    if (withSecStats && (tconn.secStats.type == 3)
			&& (tconn.secStats.level != onlyAuth))
			continue;
		}
	    }

	    /* now display the connection */
	    hostAddr.s_addr = tconn.host;
	    afs_inet_ntoa_r(hostAddr.s_addr, hoststr);
	    printf("Connection from host %s, port %hu, ", hoststr,
		   ntohs(tconn.port));
	    if (tconn.epoch)
		printf("Cuid %x/%x", tconn.epoch, tconn.cid);
	    else
		printf("cid %x", tconn.cid);
	    if (tconn.error)
		printf(", error %d", tconn.error);
	    printf("\n  serial %d, ", tconn.serial);
	    printf(" natMTU %d, ", tconn.natMTU);

	    if (tconn.flags) {
		printf("flags");
		if (tconn.flags & RX_CONN_MAKECALL_WAITING)
		    printf(" MAKECALL_WAITING");
		if (tconn.flags & RX_CONN_DESTROY_ME)
		    printf(" DESTROYED");
		if (tconn.flags & RX_CONN_USING_PACKET_CKSUM)
		    printf(" pktCksum");
                if (tconn.flags & RX_CONN_KNOW_WINDOW)
                    printf(" knowWindow");
                if (tconn.flags & RX_CONN_RESET)
                    printf(" reset");
                if (tconn.flags & RX_CONN_BUSY)
                    printf(" busy");
                if (tconn.flags & RX_CONN_ATTACHWAIT)
                    printf(" attachWait");
		printf(", ");
	    }
	    printf("security index %d, ", tconn.securityIndex);
	    if (tconn.type == RX_CLIENT_CONNECTION)
		printf("client conn\n");
	    else
		printf("server conn\n");

	    if (withSecStats) {
		switch ((int)tconn.secStats.type) {
		case 0:
		    if (tconn.securityIndex == 2)
			printf
			    ("  no GetStats procedure for security object\n");
		    break;
		case 1:
		    printf("  rxnull level=%d, flags=%d\n",
			   tconn.secStats.level, tconn.secStats.flags);
		    break;
		case 2:
		    printf("  rxvab level=%d, flags=%d\n",
			   tconn.secStats.level, tconn.secStats.flags);
		    break;
		case 3:{
			char *level;
			char flags = tconn.secStats.flags;
			if (tconn.secStats.level == 0)
			    level = "clear";
			else if (tconn.secStats.level == 1)
			    level = "auth";
			else if (tconn.secStats.level == 2)
			    level = "crypt";
			else
			    level = "unknown";
			printf("  rxkad: level %s", level);
			if (flags)
			    printf(", flags");
			if (flags & 1)
			    printf(" unalloc");
			if (flags & 2)
			    printf(" authenticated");
			if (flags & 4)
			    printf(" expired");
			if (flags & 8)
			    printf(" pktCksum");
			if (tconn.secStats.expires)
			    /* Apparently due to a bug in the RT compiler that
			     * prevents (afs_uint32)0xffffffff => (double) from working,
			     * this code produces negative lifetimes when run on the
			     * RT. */
			    printf(", expires in %.1f hours",
				   ((afs_uint32) tconn.secStats.expires -
				    time(0)) / 3600.0);
			if (!(flags & 1)) {
			    printf("\n  Received %u bytes in %u packets\n",
				   tconn.secStats.bytesReceived,
				   tconn.secStats.packetsReceived);
			    printf("  Sent %u bytes in %u packets\n",
				   tconn.secStats.bytesSent,
				   tconn.secStats.packetsSent);
			} else
			    printf("\n");
			break;
		    }

		default:
		    printf("  unknown\n");
		}
	    }

	    for (j = 0; j < RX_MAXCALLS; j++) {
		printf("    call %d: # %d, state ", j, tconn.callNumber[j]);
		if (tconn.callState[j] == RX_STATE_NOTINIT) {
		    printf("not initialized\n");
		    continue;
		} else if (tconn.callState[j] == RX_STATE_PRECALL)
		    printf("precall, ");
		else if (tconn.callState[j] == RX_STATE_ACTIVE)
		    printf("active, ");
		else if (tconn.callState[j] == RX_STATE_DALLY)
		    printf("dally, ");
		else if (tconn.callState[j] == RX_STATE_HOLD)
		    printf("hold, ");
		else if (tconn.callState[j] == RX_STATE_RESET)
		    printf("reset, ");
		printf("mode: ");
		if (tconn.callMode[j] == RX_MODE_SENDING)
		    printf("sending");
		else if (tconn.callMode[j] == RX_MODE_RECEIVING)
		    printf("receiving");
		else if (tconn.callMode[j] == RX_MODE_ERROR)
		    printf("error");
		else if (tconn.callMode[j] == RX_MODE_EOF)
		    printf("eof");
		else
		    printf("unknown");
		if (tconn.callFlags[j]) {
		    printf(", flags:");
		    if (tconn.callFlags[j] & RX_CALL_READER_WAIT)
			printf(" reader_wait");
		    if (tconn.callFlags[j] & RX_CALL_WAIT_WINDOW_ALLOC)
			printf(" window_alloc");
		    if (tconn.callFlags[j] & RX_CALL_WAIT_WINDOW_SEND)
			printf(" window_send");
		    if (tconn.callFlags[j] & RX_CALL_WAIT_PACKETS)
			printf(" wait_packets");
		    if (tconn.callFlags[j] & RX_CALL_WAIT_PROC)
			printf(" waiting_for_process");
		    if (tconn.callFlags[j] & RX_CALL_RECEIVE_DONE)
			printf(" receive_done");
		    if (tconn.callFlags[j] & RX_CALL_CLEARED)
			printf(" call_cleared");
		}
		if (tconn.callOther[j] & RX_OTHER_IN)
		    printf(", has_input_packets");
		if (tconn.callOther[j] & RX_OTHER_OUT)
		    printf(", has_output_packets");
		printf("\n");
	    }
	}
	if (nodally)
	    printf("Skipped %d dallying connections.\n", dallyCounter);
    }
    if (showPeers && withPeers) {
	for (i = 0;; i++) {
	    struct rx_debugPeer tpeer;
	    code =
		rx_GetServerPeers(s, host, port, &nextpeer, allconns, &tpeer,
				  &supportedPeerValues);
	    if (code < 0) {
		printf("getpeer call failed with code %d\n", code);
		break;
	    }
	    if (tpeer.host == 0xffffffff) {
		printf("Done.\n");
		break;
	    }

	    if ((onlyHost != -1) && (onlyHost != tpeer.host))
		continue;
	    if ((onlyPort != -1) && (onlyPort != tpeer.port))
		continue;

	    /* now display the peer */
	    hostAddr.s_addr = tpeer.host;
	    afs_inet_ntoa_r(hostAddr.s_addr, hoststr);
	    printf("Peer at host %s, port %hu\n", hoststr, 
		   ntohs(tpeer.port));
	    printf("\tifMTU %hu\tnatMTU %hu\tmaxMTU %hu\n", tpeer.ifMTU,
		   tpeer.natMTU, tpeer.maxMTU);
	    printf("\tpackets sent %u\tpacket resends %u\n", tpeer.nSent,
		   tpeer.reSends);
	    printf("\tbytes sent high %u low %u\n", tpeer.bytesSent.high,
		   tpeer.bytesSent.low);
	    printf("\tbytes received high %u low %u\n",
		   tpeer.bytesReceived.high, tpeer.bytesReceived.low);
	    printf("\trtt %u msec, rtt_dev %u msec\n", tpeer.rtt >> 3,
		   tpeer.rtt_dev >> 2);
	    printf("\ttimeout %u.%03u sec\n", tpeer.timeout.sec,
		   tpeer.timeout.usec / 1000);
	    if (!showLong)
		continue;

	    printf("\tin/out packet skew: %d/%d\n", tpeer.inPacketSkew,
		    tpeer.outPacketSkew);
	    printf("\tcongestion window %d, MTU %d\n", tpeer.cwind,
		   tpeer.MTU);
	    printf("\tcurrent/if/max jumbogram size: %d/%d/%d\n",
		   tpeer.nDgramPackets, tpeer.ifDgramPackets,
		   tpeer.maxDgramPackets);
	}
    }
    exit(0);
}
Example #4
0
static int
CommandProc(struct cmd_syndesc *as, void *arock)
{
    char *hostName, *portName, *times;
    afs_int32 hostAddr;
    register afs_int32 i, j, code;
    short port;
    int int32p;
    time_t now, then, diff, newtime;
    struct hostent *th;
    struct rx_connection *tconn;
    struct rx_securityClass *sc;
    struct ubik_debug udebug;
    struct ubik_sdebug usdebug;
    int oldServer = 0;		/* are we talking to a pre 3.5 server? */
    afs_int32 isClone = 0;

    int32p = (as->parms[2].items ? 1 : 0);

    if (as->parms[0].items)
	hostName = as->parms[0].items->data;
    else
	hostName = NULL;

    if (as->parms[1].items)
	portName = as->parms[1].items->data;
    else
	portName = NULL;

    /* lookup host */
    if (hostName) {
	th = hostutil_GetHostByName(hostName);
	if (!th) {
	    printf("udebug: host %s not found in host table\n", hostName);
	    exit(1);
	}
	memcpy(&hostAddr, th->h_addr, sizeof(afs_int32));
    } else
	hostAddr = htonl(0x7f000001);	/* IP localhost */

    if (!portName)
	port = htons(3000);	/* default */
    else {
	port = PortNumber(portName);
	if (port < 0)
	    port = PortName(portName);
	if (port < 0) {
	    printf("udebug: can't resolve port name %s\n", portName);
	    exit(1);
	}
	port = htons(port);
    }

    rx_Init(0);
    sc = rxnull_NewClientSecurityObject();
    tconn = rx_NewConnection(hostAddr, port, VOTE_SERVICE_ID, sc, 0);

    /* now do the main call */
    code = VOTE_XDebug(tconn, &udebug, &isClone);
    if (code)
	code = VOTE_Debug(tconn, &udebug);
    if (code == RXGEN_OPCODE) {
	oldServer = 1;		/* talking to a pre 3.5 server */
	memset(&udebug, 0, sizeof(udebug));
	code = VOTE_DebugOld(tconn, &udebug);
    }

    if (code) {
	printf("return code %d from VOTE_Debug\n", code);
	exit(0);
    }
    now = time(0);
    then = udebug.now;

    /* now print the main info */
    times = ctime(&then);
    times[24] = 0;
    if (!oldServer) {
	printf("Host's addresses are: ");
	for (j = 0; udebug.interfaceAddr[j] && (j < UBIK_MAX_INTERFACE_ADDR);
	     j++)
	    printf("%s ", afs_inet_ntoa(htonl(udebug.interfaceAddr[j])));
	printf("\n");
    }
    printf("Host's %s time is %s\n", afs_inet_ntoa(hostAddr), times);

    times = ctime(&now);
    times[24] = 0;
    diff = now - udebug.now;
    printf("Local time is %s (time differential %d secs)\n", times, (int)diff);
    if (abs((int)diff) >= MAXSKEW)
	printf("****clock may be bad\n");

    /* UBIK skips the voting if 1 server - so we fudge it here */
    if (udebug.amSyncSite && (udebug.nServers == 1)) {
	udebug.lastYesHost = hostAddr;
	udebug.lastYesTime = udebug.now;
	udebug.lastYesState = 1;
	udebug.lastYesClaim = udebug.now;
	udebug.syncVersion.epoch = udebug.localVersion.epoch;
	udebug.syncVersion.counter = udebug.localVersion.counter;
    }

    /* sockaddr is always in net-order */
    if (udebug.lastYesHost == 0xffffffff) {
	printf("Last yes vote not cast yet \n");
    } else {
	diff = udebug.now - udebug.lastYesTime;
	printf("Last yes vote for %s was %d secs ago (%ssync site); \n",
	       afs_inet_ntoa(udebug.lastYesHost), (int)diff,
	       ((udebug.lastYesState) ? "" : "not "));

	diff = udebug.now - udebug.lastYesClaim;
	newtime = now - diff;
	times = ctime(&newtime);
	times[24] = 0;
	printf("Last vote started %d secs ago (at %s)\n", (int)diff, times);
    }

    printf("Local db version is %d.%d\n", udebug.localVersion.epoch,
	   udebug.localVersion.counter);

    if (udebug.amSyncSite) {
	if (udebug.syncSiteUntil == 0x7fffffff) {
	    printf("I am sync site forever (%d server%s)\n", udebug.nServers,
		   ((udebug.nServers > 1) ? "s" : ""));
	} else {
	    diff = udebug.syncSiteUntil - udebug.now;
	    newtime = now + diff;
	    times = ctime(&newtime);
	    times[24] = 0;
	    printf
		("I am sync site until %d secs from now (at %s) (%d server%s)\n",
		 (int)diff, times, udebug.nServers,
		 ((udebug.nServers > 1) ? "s" : ""));
	}
	printf("Recovery state %x\n", udebug.recoveryState);
	if (udebug.activeWrite) {
	    printf("I am currently managing write trans %d.%d\n",
		   udebug.epochTime, udebug.tidCounter);
	}
    } else {
	if (isClone)
	    printf("I am a clone and never can become sync site\n");
	else
	    printf("I am not sync site\n");
	diff = udebug.now - udebug.lowestTime;
	printf("Lowest host %s was set %d secs ago\n",
	       afs_inet_ntoa(htonl(udebug.lowestHost)),
	       (int)diff);

	diff = udebug.now - udebug.syncTime;
	printf("Sync host %s was set %d secs ago\n",
	       afs_inet_ntoa(htonl(udebug.syncHost)),
	       (int)diff);
    }

    printf("Sync site's db version is %d.%d\n", udebug.syncVersion.epoch,
	   udebug.syncVersion.counter);
    printf("%d locked pages, %d of them for write\n", udebug.lockedPages,
	   udebug.writeLockedPages);

    if (udebug.anyReadLocks)
	printf("There are read locks held\n");
    if (udebug.anyWriteLocks)
	printf("There are write locks held\n");

    if (udebug.currentTrans) {
	if (udebug.writeTrans)
	    printf("There is an active write transaction\n");
	else
	    printf("There is at least one active read transaction\n");
	printf("Transaction tid is %d.%d\n", udebug.syncTid.epoch,
	       udebug.syncTid.counter);
    }
    if (udebug.epochTime) {
	diff = udebug.now - udebug.epochTime;
	newtime = now - diff;
	times = ctime(&newtime);
	times[24] = 0;
	printf
	    ("Last time a new db version was labelled was:\n\t %d secs ago (at %s)\n",
	     (int)diff, times);
    }

    if (int32p || udebug.amSyncSite) {
	/* now do the subcalls */
	for (i = 0;; i++) {
	    isClone = 0;
	    code = VOTE_XSDebug(tconn, i, &usdebug, &isClone);
	    if (code < 0) {
		if (oldServer) {	/* pre 3.5 server */
		    memset(&usdebug, 0, sizeof(usdebug));
		    code = VOTE_SDebugOld(tconn, i, &usdebug);
		} else
		    code = VOTE_SDebug(tconn, i, &usdebug);
	    }
	    if (code > 0)
		break;		/* done */
	    if (code < 0) {
		printf("error code %d from VOTE_SDebug\n", code);
		break;
	    }
	    /* otherwise print the structure */
	    printf("\nServer (%s", afs_inet_ntoa(htonl(usdebug.addr)));
	    for (j = 0;
		 ((usdebug.altAddr[j]) && (j < UBIK_MAX_INTERFACE_ADDR - 1));
		 j++)
		printf(" %s", afs_inet_ntoa(htonl(usdebug.altAddr[j])));
	    printf("): (db %d.%d)", usdebug.remoteVersion.epoch,
		   usdebug.remoteVersion.counter);
	    if (isClone)
		printf("    is only a clone!");
	    printf("\n");

	    if (usdebug.lastVoteTime == 0) {
		printf("    last vote never rcvd \n");
	    } else {
		diff = udebug.now - usdebug.lastVoteTime;
		newtime = now - diff;
		times = ctime(&newtime);
		times[24] = 0;
		printf("    last vote rcvd %d secs ago (at %s),\n", (int)diff,
		       times);
	    }

	    if (usdebug.lastBeaconSent == 0) {
		printf("    last beacon never sent \n");
	    } else {
		diff = udebug.now - usdebug.lastBeaconSent;
		newtime = now - diff;
		times = ctime(&newtime);
		times[24] = 0;
		printf
		    ("    last beacon sent %d secs ago (at %s), last vote was %s\n",
		     (int)diff, times, ((usdebug.lastVote) ? "yes" : "no"));
	    }

	    printf("    dbcurrent=%d, up=%d beaconSince=%d\n",
		   usdebug.currentDB, usdebug.up, usdebug.beaconSinceDown);
	}
    }
    return (0);
}