1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 #pragma ident "%Z%%M% %I% %E% SMI"
41
42 #include <stdio.h>
43 #include <ctype.h>
44 #include <setjmp.h>
45 #include <utmpx.h>
46 #include <pwd.h>
47 #include <time.h>
48 #include <sys/time.h>
49 #include <sys/resource.h>
50 #include <sys/param.h>
51 #include <sys/types.h>
52 #include <sys/errno.h>
53 #include <rpc/rpc.h>
54 #include <rpc/pmap_clnt.h>
55 #include <rpcsvc/mount.h>
56 #include <rpcsvc/rwall.h>
57 #include <sys/socket.h>
58 #include <netinet/in.h>
59 #include <netdb.h>
60 #include <locale.h>
61 #include <sys/syslog.h>
62 #include <zone.h>
63 #include <signal.h>
64
65 /*
66 * /usr/etc/shutdown when [messages]
67 *
68 * allow super users to tell users and remind users
69 * of iminent shutdown of unix
70 * and shut it down automatically
71 * and even reboot or halt the machine if they desire
72 */
73
74 #define EPATH "PATH=/usr/ucb:/usr/bin:/usr/sbin:"
75 #define REBOOT "/usr/sbin/reboot"
76 #define HALT "/usr/sbin/halt"
77 #define MAXINTS 20
78 #define HOURS *3600
79 #define MINUTES *60
80 #define SECONDS
81 #define NLOG 600 /* no of bytes possible for message */
82 #define NOLOGTIME 5 MINUTES
83 #define IGNOREUSER "sleeper"
84
85 struct hostlist {
86 char *host;
87 struct hostlist *nxt;
88 } *hostlist;
89
90 char hostname[MAXHOSTNAMELEN];
91 char mbuf[BUFSIZ];
92
93 extern char *malloc();
94
95 extern char *ctime();
96 extern struct tm *localtime();
97
98 extern char *strcpy();
99 extern char *strncat();
100 extern off_t lseek();
101
102 struct utmpx *utmpx;
103
104 int sint;
105 int stogo;
106 char tpath[] = "/dev/";
107 int nlflag = 1; /* nolog yet to be done */
108 int killflg = 1;
109 int doreboot = 0;
110 int halt = 0;
111 int fast = 0;
112 char *nosync = NULL;
113 char nosyncflag[] = "-n";
114 char term[sizeof tpath + sizeof (utmpx->ut_line)];
115 char tbuf[BUFSIZ];
116 char nolog1[] = "\n\nNO LOGINS: System going down at %5.5s\n\n";
117 char mesg[NLOG+1];
118 #ifdef DEBUG
119 char fastboot[] = "fastboot";
120 #else
121 char fastboot[] = "/fastboot";
122 #endif
123 char nologin[] = "/etc/nologin";
124 time_t nowtime;
125 jmp_buf alarmbuf;
126
127 struct interval {
128 int stogo;
129 int sint;
130 } interval[] = {
131 4 HOURS, 1 HOURS,
132 2 HOURS, 30 MINUTES,
133 1 HOURS, 15 MINUTES,
134 30 MINUTES, 10 MINUTES,
135 15 MINUTES, 5 MINUTES,
136 10 MINUTES, 5 MINUTES,
137 5 MINUTES, 3 MINUTES,
138 2 MINUTES, 1 MINUTES,
139 1 MINUTES, 30 SECONDS,
140 0 SECONDS, 0 SECONDS
141 };
142
143 char *msg1 = "shutdown: '%c' - unknown flag\n";
144 char *msg2 = "Usage: shutdown [ -krhfn ] shutdowntime [ message ]\n";
145 char *msg3 = "Usage: shutdown [ -krhfn ] shutdowntime [ message ]";
146 char *msg4 = "Usage: shutdown [ -krhfn ] shutdowntime [ message ]\n";
147 char *msg5 = "Usage: shutdown [ -krhfn ] shutdowntime [ message ]";
148 char *msg6 = "\n\007\007System shutdown time has arrived\007\007\n";
149 char *msg7 = "but you'll have to do it yourself\n";
150 char *msg8 = "but you'll have to do it yourself";
151 char *msg9 = "-l (without fsck's)\n";
152 char *msg10 = "-l %s\n";
153 char *msg11 = " (without fsck's)\n";
154 char *msg12 = "That must be tomorrow\nCan't you wait till then?\n";
155 char *msg13 = "That must be tomorrow";
156 char *msg14 = "Can't you wait till then?";
157 char *msg15 = "\007\007\t*** %sSystem shutdown message from %s@%s ***\r\n\n";
158 char *msg16 = "System going down at %5.5s\r\n";
159 char *msg17 = "System going down in %d minute%s\r\n";
160 char *msg18 = "System going down in %d second%s\r\n";
161 char *msg19 = "System going down IMMEDIATELY\r\n";
162 char *msg20 = "Can't get PID for init\n";
163
164 char *shutter, *getlogin();
165
166 static void timeout(void);
167 static void gethostlist(void);
168 static void finish(char *, char *, int);
169 static void nolog(time_t);
170 static void rprintf(char *, char *);
171 static void rwarn(char *, time_t, time_t, char *, int);
172 static void doitfast(void);
173 static void warn(FILE *, time_t, time_t, char *, int);
174 static time_t getsdt(char *);
175
176 pid_t
get_initpid(void)177 get_initpid(void)
178 {
179 pid_t init_pid;
180
181 if (zone_getattr(getzoneid(), ZONE_ATTR_INITPID, &init_pid,
182 sizeof (init_pid)) != sizeof (init_pid)) {
183 (void) fprintf(stderr, gettext(msg20));
184 exit(1);
185 }
186 return (init_pid);
187 }
188
189 int
main(int argc,char ** argv)190 main(int argc, char **argv)
191 {
192 int i;
193 char *f;
194 char *ts;
195 time_t sdt;
196 int h, m;
197 int first;
198 void finish_sig();
199 FILE *termf;
200 struct passwd *pw, *getpwuid();
201 extern char *strcat();
202 extern uid_t geteuid();
203 struct hostlist *hl;
204 char *shutdown_program;
205 char *shutdown_action;
206 int fd;
207
208 (void) setlocale(LC_ALL, "");
209
210 #if !defined(TEXT_DOMAIN)
211 #define TEXT_DOMAIN "SYS_TEST"
212 #endif
213 (void) textdomain(TEXT_DOMAIN);
214
215 audit_shutdown_setup(argc, argv);
216
217 shutter = getlogin();
218 if (shutter == 0 && (pw = getpwuid(getuid())))
219 shutter = pw->pw_name;
220 if (shutter == 0)
221 shutter = "???";
222 (void) gethostname(hostname, sizeof (hostname));
223 openlog("shutdown", 0, LOG_AUTH);
224 argc--, argv++;
225 while (argc > 0 && (f = argv[0], *f++ == '-')) {
226 while (i = *f++) {
227 switch (i) {
228 case 'k':
229 killflg = 0;
230 continue;
231 case 'n':
232 nosync = nosyncflag;
233 continue;
234 case 'f':
235 fast = 1;
236 continue;
237 case 'r':
238 doreboot = 1;
239 continue;
240 case 'h':
241 halt = 1;
242 continue;
243 default:
244 (void) fprintf(stderr, gettext(msg1),
245 i);
246 (void) fprintf(stderr, gettext(msg2));
247 finish(gettext(msg3), "", 1);
248 }
249 }
250 argc--, argv++;
251 }
252 if (argc < 1) {
253 (void) fprintf(stderr, gettext(msg4));
254 finish(gettext(msg5), "", 1);
255 }
256 if (doreboot && halt) {
257 (void) fprintf(stderr,
258 gettext("shutdown: Incompatible switches '-r' & '-h'\n"));
259 finish(gettext("shutdown: Incompatible switches '-r' & '-h'"),
260 "", 1);
261 }
262 if (fast && (nosync == nosyncflag)) {
263 (void) fprintf(stderr,
264 gettext("shutdown: Incompatible switches '-f' & '-n'\n"));
265 finish(gettext("shutdown: Incompatible switches '-f' & '-n'"),
266 "", 1);
267 }
268 if (geteuid()) {
269 (void) fprintf(stderr, gettext("shutdown: NOT super-user\n"));
270 finish(gettext("shutdown: NOT super-user"), "", 1);
271 }
272 gethostlist();
273 nowtime = time((time_t *)NULL);
274 sdt = getsdt(argv[0]);
275 argc--, argv++;
276 mesg[0] = '\0';
277 i = 0;
278 while (argc-- > 0) {
279 if (i + strlen(*argv) > NLOG)
280 break; /* no more room for the message */
281 i += strlen(*argv) + 1;
282 (void) strcat(mesg, *argv++);
283 (void) strcat(mesg, " ");
284 }
285 if (i != 0)
286 mesg[i - 1] = '\0'; /* remove trailing blank */
287 m = ((stogo = sdt - nowtime) + 30)/60;
288 h = m/60;
289 m %= 60;
290 ts = ctime(&sdt);
291 (void) printf(gettext("Shutdown at %5.5s (in "), ts+11);
292 if (h > 0)
293 (void) printf("%d hour%s ", h, h != 1 ? "s" : "");
294 (void) printf("%d minute%s) ", m, m != 1 ? "s" : "");
295 #ifndef DEBUG
296 (void) signal(SIGHUP, SIG_IGN);
297 (void) signal(SIGQUIT, SIG_IGN);
298 (void) signal(SIGINT, SIG_IGN);
299 #endif
300 (void) signal(SIGTTOU, SIG_IGN);
301 (void) signal(SIGINT, finish_sig);
302 (void) signal(SIGALRM, (void(*)())timeout);
303 (void) setpriority(PRIO_PROCESS, 0, PRIO_MIN);
304 (void) fflush(stdout);
305 #ifndef DEBUG
306 if (i = fork()) {
307 (void) printf(gettext("[pid %d]\n"), i);
308 exit(0);
309 }
310 #else
311 (void) putc('\n', stdout);
312 #endif
313 sint = 1 HOURS;
314 f = "";
315 first = 1;
316 if (doreboot) {
317 shutdown_program = REBOOT;
318 shutdown_action = "reboot";
319 } else if (halt) {
320 shutdown_program = HALT;
321 shutdown_action = "halt";
322 } else {
323 shutdown_program = NULL;
324 shutdown_action = "shutdown";
325 }
326 for (;;) {
327 for (i = 0; stogo <= interval[i].stogo && interval[i].sint; i++)
328 sint = interval[i].sint;
329 if (stogo > 0 && (stogo-sint) < interval[i].stogo)
330 sint = stogo - interval[i].stogo;
331 if (stogo <= NOLOGTIME && nlflag) {
332 nlflag = 0;
333 nolog(sdt);
334 }
335 if (sint >= stogo || sint == 0)
336 f = "FINAL ";
337 nowtime = time((time_t *)NULL);
338
339 setutxent();
340
341 while ((utmpx = getutxent()) != NULL) {
342 if (utmpx->ut_name[0] &&
343 strncmp(utmpx->ut_name, IGNOREUSER,
344 sizeof (utmpx->ut_name))) {
345 /*
346 * don't write to pty's unless they're rlogin sessions
347 */
348 if (utmpx->ut_type != USER_PROCESS &&
349 utmpx->ut_user[0] != '\0')
350 continue;
351
352 if (setjmp(alarmbuf))
353 continue;
354 (void) strcpy(term, tpath);
355 (void) strncat(term, utmpx->ut_line,
356 sizeof (utmpx->ut_line));
357 (void) alarm(5);
358
359 /* check if device is really a tty */
360 if ((fd = open(term, O_WRONLY|O_NOCTTY)) == -1) {
361 fprintf(stderr, gettext("Cannot open %s.\n"),
362 term);
363 (void) alarm(0);
364 continue;
365 } else {
366 if (!isatty(fd)) {
367 fprintf(stderr,
368 gettext("%.*s in utmpx is not a tty\n"),
369 sizeof (utmpx->ut_line), utmpx->ut_line);
370 syslog(LOG_CRIT, "%.*s in utmpx is not "
371 "a tty\n", sizeof (utmpx->ut_line),
372 utmpx->ut_line);
373 close(fd);
374 (void) alarm(0);
375 continue;
376 }
377 }
378 close(fd);
379 #ifdef DEBUG
380 if ((termf = stdout) != NULL)
381 #else
382 if ((termf = fopen(term, "w")) != NULL)
383 #endif
384 {
385 (void) alarm(0);
386 setbuf(termf, tbuf);
387 (void) fprintf(termf, "\n\r\n");
388 warn(termf, sdt, nowtime, f, first);
389 (void) alarm(5);
390 #ifdef DEBUG
391 (void) fflush(termf);
392 #else
393 (void) fclose(termf);
394 #endif
395 (void) alarm(0);
396 }
397 }
398 } /* while */
399
400 endutxent();
401
402 for (hl = hostlist; hl != NULL; hl = hl->nxt)
403 rwarn(hl->host, sdt, nowtime, f, first);
404 if (stogo <= 0) {
405 (void) printf(gettext(msg6));
406 if (*mesg)
407 syslog(LOG_CRIT, "%s by %s: %s",
408 shutdown_action, shutter, mesg);
409 else
410 syslog(LOG_CRIT, "%s by %s",
411 shutdown_action, shutter);
412 sleep(2);
413 (void) unlink(nologin);
414 if (!killflg) {
415 (void) printf(gettext(msg7));
416 finish(gettext(msg8), "", 0);
417 }
418 if (fast)
419 doitfast();
420 #ifndef DEBUG
421 (void) putenv(EPATH);
422 if (shutdown_program != NULL) {
423 audit_shutdown_success();
424 execlp(shutdown_program, shutdown_program,
425 "-l", nosync, (char *)0);
426 } else {
427 if (geteuid() == 0) {
428 audit_shutdown_success();
429 sleep(5);
430 }
431 if (getzoneid() == GLOBAL_ZONEID) {
432 (void) system(
433 "/sbin/bootadm -a update_all");
434 }
435
436 (void) kill(get_initpid(), SIGINT); /* sync */
437 (void) kill(get_initpid(), SIGINT); /* sync */
438 sleep(20);
439 }
440 #else
441 if (shutdown_program) {
442 (void) printf("%s ", shutdown_program);
443 if (fast)
444 (void) printf(gettext(msg9));
445 else if (nosync != NULL)
446 (void) printf(gettext(msg10), nosync);
447 else
448 (void) printf(gettext("-l\n"));
449 } else {
450 (void) printf("/sbin/bootadm -a update_all");
451 (void) printf("kill -INT 1");
452 if (fast)
453 (void) printf(gettext(msg11));
454 else
455 (void) printf("\n");
456 }
457 #endif
458 finish("", "", 0);
459 }
460 stogo = sdt - time((time_t *)NULL);
461 if (stogo > 0 && sint > 0)
462 sleep((unsigned)(sint < stogo ? sint : stogo));
463 stogo -= sint;
464 first = 0;
465 }
466 /* NOTREACHED */
467 }
468
469 static time_t
getsdt(char * s)470 getsdt(char *s)
471 {
472 time_t t, t1, tim;
473 char c;
474 struct tm *lt;
475 int c_count;
476
477 if (strcmp(s, "now") == 0)
478 return (nowtime);
479 if (*s == '+') {
480 ++s;
481 t = 0;
482 for (c_count = 1; ; c_count++) {
483 c = *s++;
484 if (!isdigit(c)) {
485 if (c_count == 1) {
486 goto badform;
487 } else {
488 break;
489 }
490 }
491 t = t * 10 + c - '0';
492 }
493 if (t <= 0)
494 t = 5;
495 t *= 60;
496 tim = time((time_t *)NULL) + t;
497 return (tim);
498 }
499 t = 0;
500 while (strlen(s) > 2 && isdigit(*s))
501 t = t * 10 + *s++ - '0';
502 if (*s == ':')
503 s++;
504 if (t > 23)
505 goto badform;
506 tim = t*60;
507 t = 0;
508 while (isdigit(*s))
509 t = t * 10 + *s++ - '0';
510 if (t > 59)
511 goto badform;
512 tim += t;
513 tim *= 60;
514 t1 = time((time_t *)NULL);
515 lt = localtime(&t1);
516 t = lt->tm_sec + lt->tm_min*60 + lt->tm_hour*3600;
517 if (tim < t || tim >= (24*3600)) {
518 /* before now or after midnight */
519 (void) printf(gettext(msg12));
520 finish(gettext(msg13), gettext(msg14), 0);
521 }
522 return (t1 + tim - t);
523 badform:
524 (void) printf(gettext("Bad time format\n"));
525 finish(gettext("Bad time format"), "", 0);
526 return (0);
527 /* NOTREACHED */
528 }
529
530 static void
warn(FILE * termf,time_t sdt,time_t now,char * type,int first)531 warn(FILE *termf, time_t sdt, time_t now, char *type, int first)
532 {
533 char *ts;
534 time_t delay = sdt - now;
535
536 if (delay > 8)
537 while (delay % 5)
538 delay++;
539
540 (void) fprintf(termf, gettext(msg15), type, shutter, hostname);
541
542 ts = ctime(&sdt);
543 if (delay > 10 MINUTES)
544 (void) fprintf(termf, gettext(msg16), ts+11);
545 else if (delay > 95 SECONDS) {
546 (void) fprintf(termf, gettext(msg17), (delay+30)/60,
547 (delay+30)/60 != 1 ? "s" : "");
548 } else if (delay > 0) {
549 (void) fprintf(termf, gettext(msg18), delay,
550 delay != 1 ? "s" : "");
551 } else
552 (void) fprintf(termf, gettext(msg19));
553
554 if (first || sdt - now > 1 MINUTES) {
555 if (*mesg)
556 (void) fprintf(termf, "\t...%s\r\n", mesg);
557 }
558 }
559
560 static void
doitfast(void)561 doitfast(void)
562 {
563 FILE *fastd;
564
565 if ((fastd = fopen(fastboot, "w")) != NULL) {
566 (void) putc('\n', fastd);
567 (void) fclose(fastd);
568 }
569 }
570
571 static void
rwarn(char * host,time_t sdt,time_t now,char * type,int first)572 rwarn(char *host, time_t sdt, time_t now, char *type, int first)
573 {
574 char *ts;
575 time_t delay = sdt - now;
576 char *bufp;
577
578 if (delay > 8)
579 while (delay % 5)
580 delay++;
581
582 (void) sprintf(mbuf,
583 "\007\007\t*** %sShutdown message for %s from %s@%s ***\r\n\n",
584 type, hostname, shutter, hostname);
585 ts = ctime(&sdt);
586 bufp = mbuf + strlen(mbuf);
587 if (delay > 10 MINUTES) {
588 (void) sprintf(bufp, "%s going down at %5.5s\r\n", hostname,
589 ts+11);
590 } else if (delay > 95 SECONDS) {
591 (void) sprintf(bufp, "%s going down in %d minute%s\r\n",
592 hostname, (delay+30)/60, (delay+30)/60 != 1 ? "s" : "");
593 } else if (delay > 0) {
594 (void) sprintf(bufp, "%s going down in %d second%s\r\n",
595 hostname, delay, delay != 1 ? "s" : "");
596 } else {
597 (void) sprintf(bufp, "%s going down IMMEDIATELY\r\n",
598 hostname);
599 }
600 bufp = mbuf + strlen(mbuf);
601 if (first || sdt - now > 1 MINUTES) {
602 if (*mesg)
603 (void) sprintf(bufp, "\t...%s\r\n", mesg);
604 }
605 rprintf(host, mbuf);
606 }
607
608 static void
rprintf(char * host,char * bufp)609 rprintf(char *host, char *bufp)
610 {
611 int err;
612
613 #ifdef DEBUG
614 (void) fprintf(stderr, gettext("about to call %s\n"), host);
615 #endif
616 if (err = callrpcfast(host, (rpcprog_t)WALLPROG, (rpcvers_t)WALLVERS,
617 (rpcproc_t)WALLPROC_WALL, xdr_dirpath, (char *)&bufp, xdr_void,
618 (char *)NULL)) {
619 #ifdef DEBUG
620 (void) fprintf(stderr, gettext("couldn't make rpc call: "));
621 clnt_perrno(err);
622 (void) fprintf(stderr, "\n");
623 #endif
624 }
625 }
626
627 static void
nolog(time_t sdt)628 nolog(time_t sdt)
629 {
630 FILE *nologf;
631
632 (void) unlink(nologin); /* in case linked to std file */
633 if ((nologf = fopen(nologin, "w")) != NULL) {
634 (void) fprintf(nologf, nolog1, (ctime(&sdt)) + 11);
635 if (*mesg)
636 (void) fprintf(nologf, "\t%s\n", mesg);
637 (void) fclose(nologf);
638 }
639 }
640
641 void
finish_sig(void)642 finish_sig(void)
643 {
644 finish("SIGINT", "", 1);
645 }
646
647 static void
finish(char * s1,char * s2,int exitcode)648 finish(char *s1, char *s2, int exitcode)
649 {
650 (void) signal(SIGINT, SIG_IGN);
651 exit(exitcode);
652 }
653
654 static void
timeout(void)655 timeout(void)
656 {
657 (void) signal(SIGALRM, (void(*)())timeout);
658 longjmp(alarmbuf, 1);
659 }
660
661 static void
gethostlist(void)662 gethostlist(void)
663 {
664 int s;
665 struct mountbody *ml;
666 struct hostlist *hl;
667 struct sockaddr_in addr;
668 CLIENT *cl;
669 static struct timeval TIMEOUT = { 25, 0 };
670
671 /*
672 * check for portmapper
673 */
674 get_myaddress(&addr);
675 s = socket(AF_INET, SOCK_STREAM, 0);
676 if (s < 0)
677 return;
678 if (connect(s, (struct sockaddr *)&addr, sizeof (addr)) < 0)
679 return;
680 (void) close(s);
681
682 /*
683 * First try tcp, then drop back to udp if
684 * tcp is unavailable (an old version of mountd perhaps)
685 * Using tcp is preferred because it can handle
686 * arbitrarily long export lists.
687 */
688 cl = clnt_create(hostname, (ulong_t)MOUNTPROG, (ulong_t)MOUNTVERS,
689 "tcp");
690 if (cl == NULL) {
691 cl = clnt_create(hostname, (ulong_t)MOUNTPROG,
692 (ulong_t)MOUNTVERS, "udp");
693 if (cl == NULL) {
694 if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED) {
695 clnt_pcreateerror("shutdown warning");
696 }
697 return;
698 }
699 }
700
701 ml = NULL;
702 if (clnt_call(cl, MOUNTPROC_DUMP,
703 xdr_void, 0, xdr_mountlist, (char *)&ml, TIMEOUT) != RPC_SUCCESS) {
704 clnt_perror(cl, "shutdown warning");
705 return;
706 }
707 for (; ml != NULL; ml = ml->ml_next) {
708 for (hl = hostlist; hl != NULL; hl = hl->nxt)
709 if (strcmp(ml->ml_hostname, hl->host) == 0)
710 goto again;
711 hl = (struct hostlist *)malloc(sizeof (struct hostlist));
712 hl->host = ml->ml_hostname;
713 hl->nxt = hostlist;
714 hostlist = hl;
715 again:;
716 }
717 }
718
719 /*
720 * Don't want to wait for usual portmapper timeout you get with
721 * callrpc or clnt_call, so use rmtcall instead. Use timeout
722 * of 8 secs, based on the per try timeout of 3 secs for rmtcall
723 */
724 int
callrpcfast(char * host,rpcprog_t prognum,rpcprog_t versnum,rpcprog_t procnum,xdrproc_t inproc,xdrproc_t outproc,char * in,char * out)725 callrpcfast(char *host, rpcprog_t prognum, rpcprog_t versnum,
726 rpcprog_t procnum, xdrproc_t inproc, xdrproc_t outproc,
727 char *in, char *out)
728 {
729 struct sockaddr_in server_addr;
730 struct hostent *hp;
731 struct timeval rpctimeout;
732 rpcport_t port;
733
734 if ((hp = gethostbyname(host)) == NULL)
735 return ((int)RPC_UNKNOWNHOST);
736 bcopy(hp->h_addr, (char *)&server_addr.sin_addr, hp->h_length);
737 server_addr.sin_family = AF_INET;
738 server_addr.sin_port = 0;
739 rpctimeout.tv_sec = 8;
740 rpctimeout.tv_usec = 0;
741 return ((int)pmap_rmtcall(&server_addr, prognum, versnum, procnum,
742 inproc, in, outproc, out, rpctimeout, &port));
743 }
744