ypxfr.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,787 行 · 第 1/3 页
C
1,787 行
char dbfile[MAXNAMLEN + 1]; struct stat filestat; int len; if (!pname || ((len = strlen(pname)) == 0) || (len + 5) > (MAXNAMLEN + 1) ) { return (FALSE); } errno = 0; (void) strcpy(dbfile, pname); (void) strcat(dbfile, ".dir"); if (stat(dbfile, &filestat) != -1) { (void) strcpy(dbfile, pname); (void) strcat(dbfile, ".pag"); if (stat(dbfile, &filestat) != -1) { return (TRUE); } else { if (errno != ENOENT) { logprintf( "Stat error on map file %s.\n", dbfile); } return (FALSE); } } else { if (errno != ENOENT) { logprintf( "Stat error on map file %s.\n", dbfile); } return (FALSE); }}/* * This creates <pname>.dir and <pname>.pag */boolnew_mapfiles(pname) char *pname;{ char dbfile[MAXNAMLEN + 1]; int f; int len; if (!pname || ((len = strlen(pname)) == 0) || (len + 5) > (MAXNAMLEN + 1) ) { return (FALSE); } errno = 0; (void) strcpy(dbfile, pname); (void) strcat(dbfile, ".dir"); if ((f = open(dbfile, (O_WRONLY | O_CREAT | O_TRUNC), 0600)) >= 0) { (void) close(f); (void) strcpy(dbfile, pname); (void) strcat(dbfile, ".pag"); if ((f = open(dbfile, (O_WRONLY | O_CREAT | O_TRUNC), 0600)) >= 0) { (void) close(f); return (TRUE); } else { return (FALSE); } } else { return (FALSE); }}count_callback(status) int status;{ if (status != YP_TRUE) { if (status != YP_NOMORE) { logprintf( "Error from ypserv on %s (ypall_callback) = %s.\n", master, yperr_string(ypprot_err(status))); } return(TRUE); } entry_count++; return(FALSE);}/* * This counts the entries in the dbm file after the transfer to * make sure that the dbm file was built correctly. * Returns TRUE if everything is OK, FALSE if they mismatch. */count_mismatch(pname,oldcount) char *pname; int oldcount;{ datum key, value; struct dom_binding domb; enum clnt_stat s; struct ypreq_nokey allreq; struct ypall_callback cbinfo; entry_count = 0; dbminit(pname); for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) entry_count++; dbmclose(pname); if (oldcount != entry_count) { logprintf( "*** Count mismatch in dbm file %s: old=%d, new=%d ***\n", map, oldcount, entry_count); return(FALSE); }# ifdef REALLY_PARANOID domb.dom_server_addr.sin_addr = master_addr; domb.dom_server_addr.sin_family = AF_INET; domb.dom_server_addr.sin_port = htons((u_short) 0); domb.dom_server_port = htons((u_short) 0); domb.dom_socket = RPC_ANYSOCK; if ((domb.dom_client = clnttcp_create(&(domb.dom_server_addr), YPPROG, master_prog_vers, &(domb.dom_socket), 0, 0)) == (CLIENT *) NULL) { clnt_pcreateerror( "ypxfr (mismatch) - TCP channel create failure"); return(FALSE); } if (master_prog_vers == YPVERS) { int tmpstat; allreq.domain = domain; allreq.map = map; cbinfo.foreach = count_callback; tmpstat = 0; cbinfo.data = (char *) &tmpstat; entry_count = 0; s = clnt_call(domb.dom_client, YPPROC_ALL, xdr_ypreq_nokey, &allreq, xdr_ypall, &cbinfo, tcp_timeout); if (tmpstat == 0) { if (s == RPC_SUCCESS) { } else { clnt_perror(domb.dom_client, "ypxfr (get_map/all) - RPC clnt_call (TCP) failure"); return(FALSE); } } else { return(FALSE); } } else { logprintf("Wrong version number!\n"); return(FALSE); } clnt_destroy(domb.dom_client); close(domb.dom_socket); entry_count += 2; /* add in YP_entries */ if (oldcount != entry_count) { logprintf( "*** Count mismatch after enumerate %s: old=%d, new=%d ***\n", map, oldcount, entry_count); return(FALSE); }# endif REALLY_PARANOID return(TRUE);}/* * This sets up a TCP connection to the master server, and either gets * ypall_callback to do all the work of writing it to the local dbm file * (if the ypserv is current version), or does it itself for an old ypserv. */boolget_map(pname, pushstat) char *pname; int *pushstat;{ struct dom_binding domb; enum clnt_stat s; struct ypreq_nokey allreq; struct ypall_callback cbinfo; struct yprequest oldreq; struct ypresponse resp; bool retval = FALSE; int tmpstat; domb.dom_server_addr.sin_addr = master_addr; domb.dom_server_addr.sin_family = AF_INET; domb.dom_server_addr.sin_port = htons((u_short) 0); domb.dom_server_port = htons((u_short) 0); domb.dom_socket = RPC_ANYSOCK; if ((domb.dom_client = clnttcp_create(&(domb.dom_server_addr), YPPROG, master_prog_vers, &(domb.dom_socket), 0, 0)) == (CLIENT *) NULL) { clnt_pcreateerror( "ypxfr (get_map) - TCP channel create failure"); *pushstat = YPPUSH_RPC; return(FALSE); } entry_count = 0; if (master_prog_vers == YPVERS) { allreq.domain = domain; allreq.map = map; cbinfo.foreach = ypall_callback; tmpstat = 0; cbinfo.data = (char *) &tmpstat; s = clnt_call(domb.dom_client, YPPROC_ALL, xdr_ypreq_nokey, &allreq, xdr_ypall, &cbinfo, tcp_timeout); if (tmpstat == 0) { if (s == RPC_SUCCESS) { retval = TRUE; } else { clnt_perror(domb.dom_client, "ypxfr (get_map/all) - RPC clnt_call (TCP) failure"); *pushstat = YPPUSH_RPC; } } else { *pushstat = tmpstat; } } else { datum inkey, inval; oldreq.yp_reqtype = YPFIRST_REQTYPE; oldreq.ypfirst_req_domain = domain; oldreq.ypfirst_req_map = map; resp.ypfirst_resp_keyptr = NULL; resp.ypfirst_resp_keysize = 0; resp.ypfirst_resp_valptr = NULL; resp.ypfirst_resp_valsize = 0; if((s = clnt_call(domb.dom_client, YPOLDPROC_FIRST, _xdr_yprequest, &oldreq, _xdr_ypresponse, &resp, tcp_timeout)) != RPC_SUCCESS) { clnt_perror(domb.dom_client, "ypxfr (get_map/first) - RPC clnt_call (TCP) failure"); *pushstat = YPPUSH_RPC; goto cleanup; } if (resp.ypfirst_resp_status != YP_TRUE) { logprintf( "Error from ypserv on %s (get first) = %s.\n", master, yperr_string(ypprot_err( resp.ypfirst_resp_status))); *pushstat = YPPUSH_RPC; goto cleanup; } inkey = resp.ypfirst_resp_keydat; inval = resp.ypfirst_resp_valdat; /* * Continue to get the next entries in the map as long as * there are no errors, and there are entries remaining. */ oldreq.yp_reqtype = YPNEXT_REQTYPE; oldreq.ypnext_req_domain = domain; oldreq.ypnext_req_map = map; while (TRUE) { if (strncmp(inkey.dptr,"YP_",3)) { if (store(inkey, inval) < 0) { logprintf( "Can't do dbm store into temp map %s.\n", pname); *pushstat = YPPUSH_DBM; goto cleanup; } entry_count++; } CLNT_FREERES(domb.dom_client, _xdr_ypresponse, &resp); oldreq.ypnext_req_keydat = inkey; resp.ypnext_resp_keydat.dptr = NULL; resp.ypnext_resp_valdat.dptr = NULL; resp.ypnext_resp_keydat.dsize = 0; resp.ypnext_resp_valdat.dsize = 0; if ((s = clnt_call(domb.dom_client, YPOLDPROC_NEXT, _xdr_yprequest, &oldreq, _xdr_ypresponse, &resp, tcp_timeout)) != RPC_SUCCESS) { clnt_perror(domb.dom_client, "ypxfr (get_map/next) - RPC clnt_call (TCP) failure"); *pushstat = YPPUSH_RPC; break; } if (resp.ypnext_resp_status != YP_TRUE) { if (resp.ypnext_resp_status == YP_NOMORE) { retval = TRUE; } else { logprintf( "Error from ypserv on %s (get next) = %d.\n", master, yperr_string(ypprot_err( resp.ypnext_resp_status))); *pushstat = YPPUSH_RPC; } break; } inkey = resp.ypnext_resp_keydat; inval = resp.ypnext_resp_valdat; } }cleanup: clnt_destroy(domb.dom_client); close(domb.dom_socket); return (retval);}/* * This sticks each key-value pair into the current map. It returns FALSE as * long as it wants to keep getting called back, and TRUE on error conditions * and "No more k-v pairs". */intypall_callback(status, key, kl, val, vl, pushstat) int status; char *key; int kl; char *val; int vl; int *pushstat;{ datum keydat; datum valdat; datum test; if (status != YP_TRUE) { if (status != YP_NOMORE) { logprintf( "Error from ypserv on %s (ypall_callback) = %s.\n", master, yperr_string(ypprot_err(status))); *pushstat = map_yperr_to_pusherr(status); } return(TRUE); } keydat.dptr = key; keydat.dsize = kl; valdat.dptr = val; valdat.dsize = vl; entry_count++;# ifdef PARANOID test = fetch(keydat); if (test.dptr!=NULL) { logprintf("Duplicate key %s in map %s\n",key,map); *pushstat = YPPUSH_DBM; return(TRUE); }# endif PARANOID if (store(keydat, valdat) < 0) { logprintf( "Can't do dbm store into temp map %s.\n",map); *pushstat = YPPUSH_DBM; return(TRUE); }# ifdef PARANOID test = fetch(keydat); if (test.dptr==NULL) { logprintf("Key %s was not inserted into dbm file %s\n", key,map); *pushstat = YPPUSH_DBM; return(TRUE); }# endif PARANOID return(FALSE);}/* * This maps a YP_xxxx error code into a YPPUSH_xxxx error code */intmap_yperr_to_pusherr(yperr) int yperr;{ int reason; switch (yperr) { case YP_NOMORE: reason = YPPUSH_SUCC; break; case YP_NOMAP: reason = YPPUSH_NOMAP; break; case YP_NODOM: reason = YPPUSH_NODOM; break; case YP_NOKEY: reason = YPPUSH_YPERR; break; case YP_BADARGS: reason = YPPUSH_BADARGS; break; case YP_BADDB: reason = YPPUSH_YPERR; break; default: reason = YPPUSH_XFRERR; break; } return(reason);}/* * This writes the last-modified and master entries into the new dbm file */booladd_private_entries(pname) char *pname;{ datum key; datum val; if (!fake_master_version) { key.dptr = yp_last_modified; key.dsize = sizeof (yp_last_modified) - 1; val.dptr = master_ascii_version; val.dsize = strlen(master_ascii_version); if (store(key, val) < 0) { logprintf( "Can't do dbm store into temp map %s.\n", pname); return (FALSE); } entry_count++; } if (master_name) { key.dptr = yp_master_name; key.dsize = sizeof (yp_master_name) - 1; val.dptr = master_name; val.dsize = strlen(master_name); if (store(key, val) < 0) { logprintf( "Can't do dbm store into temp map %s.\n", pname); return (FALSE); } entry_count++; } return (TRUE);} /* * This sends a YPPROC_CLEAR message to the local ypserv process. If the * local ypserv is a v.1 protocol guy, we'll just say we succeeded. Such a * situation is outlandish - why are they running the old ypserv at the same * place they are running ypxfr? And who are they, anyway? */boolsend_ypclear(pushstat) int *pushstat;{ struct sockaddr_in myaddr; struct dom_binding domb; char local_host_name[256]; unsigned int progvers; get_myaddress(&myaddr); if (gethostname(local_host_name, 256)) { logprintf( "Can't get local machine name.\n"); *pushstat = YPPUSH_RSRC; return (FALSE); } if (!bind_to_server(local_host_name, myaddr.sin_addr, &domb, &progvers) ) { *pushstat = YPPUSH_CLEAR; return (FALSE); } if (progvers == YPOLDVERS) return (TRUE); if((enum clnt_stat) clnt_call(domb.dom_client, YPPROC_CLEAR, xdr_void, 0, xdr_void, 0, udp_timeout) != RPC_SUCCESS) { logprintf( "Can't send ypclear message to ypserv on the local machine.\n"); xfr_exit(YPPUSH_CLEAR); } return (TRUE);}/* * This decides if send_callback has to get called, and does the process exit. */voidxfr_exit(status) int status;{ if (callback) { send_callback(&status); } if (status == YPPUSH_SUCC) { exit(0); } else { exit(1); }}/* * This sets up a UDP connection to the yppush process which contacted our * parent ypserv, and sends him a status on the requested transfer. */voidsend_callback(status) int *status;{ struct yppushresp_xfr resp; struct dom_binding domb;#ifdef ORIGINALSUN resp.transid = (unsigned long) htonl(atoi(tid)); resp.status = (unsigned long) htonl(*status);#endif ORIGINALSUN resp.transid = (unsigned long) atoi(tid); resp.status = (unsigned long) *status; domb.dom_server_addr.sin_addr.s_addr = inet_addr(ipadd); domb.dom_server_addr.sin_family = AF_INET; domb.dom_server_addr.sin_port = (unsigned short) htons(atoi(port)); domb.dom_server_port = domb.dom_server_addr.sin_port; domb.dom_socket = RPC_ANYSOCK; udp_intertry.tv_sec = CALLINTER_TRY; udp_timeout.tv_sec = CALLTIMEOUT;/* ORIGINALSUN code had htons(atoi(proto)) in the following call. * It fails.. */ if ((domb.dom_client = clntudp_create(&(domb.dom_server_addr), (unsigned long) atoi(proto), YPPUSHVERS, udp_intertry, &(domb.dom_socket) ) ) == NULL) { clnt_perror(domb.dom_client, "ypxfr: clntudp_create failure"); *status = YPPUSH_RPC; return; } if((enum clnt_stat) clnt_call(domb.dom_client, YPPUSHPROC_XFRRESP, xdr_yppushresp_xfr, &resp, xdr_void, 0, udp_timeout) != RPC_SUCCESS) { clnt_perror(domb.dom_client, "ypxfr: clnt_call back failure"); *status = YPPUSH_RPC; return; } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?