int stread(int sfd, void *p, size_t len){ int is_sock=issock(sfd); long nread; long left=len; do{ if(is_sock){ nread=read(sfd, p, left); }else{ nread=recv(sfd, p, left, MSG_WAITALL); } p=(char*)p+nread; left-=nread; }while(nread>0 && left>0); return left?-1:0; }
int stwrite(int sfd, const void *p, size_t len){ int is_sock=issock(sfd); long nwrite; long left=(long)len; do{ if(is_sock){ nwrite=send(sfd, p, len, MSG_NOSIGNAL); }else{ nwrite=write(sfd, p, left); } p=(char*)p+nwrite; left-=nwrite; }while(nwrite>0 && left>0); return left?-1:0; }
/*Write long messages with smaller buffer*/ int stwrite2(int sfd, const void *p, size_t len, size_t nbuf){ if(nbuf>len) nbuf=len; size_t nwrite; long left=len;//do not use size_t which is unsigned #ifdef __linux__ int is_sock=issock(sfd); #endif do{ #ifdef __linux__ if(is_sock){ nwrite=send(sfd, p, len, MSG_NOSIGNAL); }else #endif nwrite=write(sfd, p, nbuf); p=(char*)p+nwrite; left-=nwrite; }while(nwrite>0 && left>0); return left?-1:0; }
char *getmodes(File *file) { char *unknownmodes = "???????????"; char *modes = malloc((strlen(unknownmodes) + 1) * sizeof(*modes)); if (!modes) { return strdup(unknownmodes); } struct stat *pstat = getstat(file); if (!pstat) { free(modes); return strdup(unknownmodes); } char *p = modes; if (islink(file)) *p++ = 'l'; else if (isdir(file)) *p++ = 'd'; else if (isblockdev(file)) *p++ = 'b'; else if (ischardev(file)) *p++ = 'c'; else if (isfifo(file)) *p++ = 'p'; else if (issock(file)) *p++ = 's'; else *p++ = '-'; if (pstat->st_mode & S_IRUSR) *p++ = 'r'; else *p++ = '-'; if (pstat->st_mode & S_IWUSR) *p++ = 'w'; else *p++ = '-'; if (issetuid(file)) { if (pstat->st_mode & S_IXUSR) *p++ = 's'; else *p++ = 'S'; } else { if (pstat->st_mode & S_IXUSR) *p++ = 'x'; else *p++ = '-'; } if (pstat->st_mode & S_IRGRP) *p++ = 'r'; else *p++ = '-'; if (pstat->st_mode & S_IWGRP) *p++ = 'w'; else *p++ = '-'; if (issetgid(file)) { if (pstat->st_mode & S_IXGRP) *p++ = 's'; else *p++ = 'S'; } else { if (pstat->st_mode & S_IXGRP) *p++ = 'x'; else *p++ = '-'; } if (pstat->st_mode & S_IROTH) *p++ = 'r'; else *p++ = '-'; if (pstat->st_mode & S_IWOTH) *p++ = 'w'; else *p++ = '-'; if (issticky(file)) { if (pstat->st_mode & S_IXOTH) *p++ = 't'; else *p++ = 'T'; } else { if (pstat->st_mode & S_IXOTH) *p++ = 'x'; else *p++ = '-'; } /* POSIX says we should print a space if there are no extended ACLs, GNU ls prints nothing follow POSIX */ if (!islink(file) && hasacls(file)) *p++ = '+'; else *p++ = ' '; *p++ = '\0'; return modes; }
/* ARGSUSED */ int main(int argc, char *argv[]) { int on = 1; socklen_t fromlen; struct sockaddr_storage from; int fd = -1; extern char *optarg; char c; int tos = -1; krb5_context krb_context; krb5_keytab keytab = NULL; krb5_error_code status; char *realm = NULL; char *keytab_file = NULL; int encr_flag = 0; struct sockaddr_storage ouraddr; socklen_t ourlen; #ifdef DEBUG int debug_port = 0; #endif /* DEBUG */ openlog("rlogind", LOG_PID | LOG_ODELAY, LOG_DAEMON); while ((c = getopt(argc, argv, ARGSTR)) != -1) { switch (c) { case 'k': case '5': use_auth = KRB5_RECVAUTH_V5; break; case 'e': case 'E': case 'x': case 'X': encr_flag = 1; break; case 'M': realm = (char *)strdup(optarg); break; case 'S': keytab_file = (char *)strdup(optarg); break; case 'c': chksum_flag |= CHKSUM_REQUIRED; break; case 'i': chksum_flag |= CHKSUM_IGNORED; break; case 's': if (optarg == NULL || (tos = atoi(optarg)) < 0 || tos > 255) { syslog(LOG_ERR, "%s: illegal tos value: " "%s\n", argv[0], optarg); } else { if (tos < 0) tos = DEFAULT_TOS; } break; #ifdef DEBUG case 'D': debug_port = atoi(optarg); break; #endif /* DEBUG */ default: syslog(LOG_ERR, "Unrecognized command line option " "(-%c), exiting", optopt); exit(EXIT_FAILURE); } } if (use_auth == KRB5_RECVAUTH_V5) { status = krb5_init_context(&krb_context); if (status) { syslog(LOG_ERR, "Error initializing krb5: %s", error_message(status)); exit(EXIT_FAILURE); } if (realm != NULL) (void) krb5_set_default_realm(krb_context, realm); if (keytab_file != NULL) { if ((status = krb5_kt_resolve(krb_context, keytab_file, &keytab))) { com_err(argv[0], status, "while resolving srvtab file %s", keytab_file); exit(EXIT_FAILURE); } } } #ifdef DEBUG if (debug_port) { int s; struct sockaddr_in sin; if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { fatalperror(STDERR_FILENO, "Error in socket"); } (void) memset((char *)&sin, 0, sizeof (sin)); sin.sin_family = AF_INET; sin.sin_port = htons(debug_port); sin.sin_addr.s_addr = INADDR_ANY; (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)); if ((bind(s, (struct sockaddr *)&sin, sizeof (sin))) < 0) { fatalperror(STDERR_FILENO, "bind error"); } if ((listen(s, 5)) < 0) { fatalperror(STDERR_FILENO, "listen error"); } fromlen = sizeof (from); if ((fd = accept(s, (struct sockaddr *)&from, &fromlen)) < 0) { fatalperror(STDERR_FILENO, "accept error"); } (void) close(s); } else #endif /* DEBUG */ { if (!issock(STDIN_FILENO)) fatal(STDIN_FILENO, "stdin is not a socket file descriptor"); fd = STDIN_FILENO; } fromlen = sizeof (from); if (getpeername(fd, (struct sockaddr *)&from, &fromlen) < 0) fatalperror(STDERR_FILENO, "getpeername"); if (audit_rlogin_settid(fd)) /* set terminal ID */ fatalperror(STDERR_FILENO, "audit"); if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof (on)) < 0) syslog(LOG_WARNING, "setsockopt(SO_KEEPALIVE): %m"); if (!VALID_CHKSUM(chksum_flag)) { syslog(LOG_ERR, "Configuration error: mutually exclusive " "options specified (-c and -i)"); fatal(fd, "Checksums are required and ignored (-c and -i);" "these options are mutually exclusive - check " "the documentation."); } ourlen = sizeof (ouraddr); if (getsockname(fd, (struct sockaddr *)&ouraddr, &ourlen) == -1) { syslog(LOG_ERR, "getsockname error: %m"); exit(EXIT_FAILURE); } if (tos != -1 && ouraddr.ss_family != AF_INET6 && setsockopt(fd, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof (tos)) < 0 && errno != ENOPROTOOPT) { syslog(LOG_ERR, "setsockopt(IP_TOS %d): %m", tos); } doit(fd, &from, krb_context, encr_flag, keytab); return (0); }