17c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/ 27c478bd9Sstevel@tonic-gate /*PROTOLIB1*/ 37c478bd9Sstevel@tonic-gate /* 4*fe0e7ec4Smaheshvs * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 57c478bd9Sstevel@tonic-gate * Use is subject to license terms. 67c478bd9Sstevel@tonic-gate */ 77c478bd9Sstevel@tonic-gate /* 87c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 97c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 107c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 117c478bd9Sstevel@tonic-gate */ 127c478bd9Sstevel@tonic-gate 137c478bd9Sstevel@tonic-gate /* line below is from UCB 5.4 12/11/85 */ 147c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 157c478bd9Sstevel@tonic-gate 167c478bd9Sstevel@tonic-gate #include <myrcmd.h> 177c478bd9Sstevel@tonic-gate #include <stdio.h> 187c478bd9Sstevel@tonic-gate #include <locale.h> 197c478bd9Sstevel@tonic-gate #include <ctype.h> 207c478bd9Sstevel@tonic-gate #include <pwd.h> 217c478bd9Sstevel@tonic-gate #include <string.h> 227c478bd9Sstevel@tonic-gate #include <signal.h> 237c478bd9Sstevel@tonic-gate #include <sys/mtio.h> 247c478bd9Sstevel@tonic-gate #include <sys/socket.h> 257c478bd9Sstevel@tonic-gate #include <unistd.h> 267c478bd9Sstevel@tonic-gate #include <netdb.h> 277c478bd9Sstevel@tonic-gate #include <locale.h> 287c478bd9Sstevel@tonic-gate #include <stdlib.h> 297c478bd9Sstevel@tonic-gate #include <errno.h> 307c478bd9Sstevel@tonic-gate #include <rmt.h> 317c478bd9Sstevel@tonic-gate #include <libintl.h> 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #define sigvec sigaction 347c478bd9Sstevel@tonic-gate #define sv_handler sa_handler 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include <netinet/in.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate extern int32_t tp_bsize; 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #define TS_CLOSED 0 417c478bd9Sstevel@tonic-gate #define TS_OPEN 1 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate static int rmtstate = TS_CLOSED; 447c478bd9Sstevel@tonic-gate static int rmtape = -1; 457c478bd9Sstevel@tonic-gate static int rmtversion = 0; 467c478bd9Sstevel@tonic-gate static char *rmtpeer, *rmtpeer_malloc; 477c478bd9Sstevel@tonic-gate static uint_t ntrec; /* blocking factor on tape */ 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate static char *domainname = "hsm_libdump"; /* for dgettext() */ 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate #ifdef __STDC__ 527c478bd9Sstevel@tonic-gate static void rmtmsg(const char *, ...); /* package print routine */ 537c478bd9Sstevel@tonic-gate static void rmtconnaborted(int); 547c478bd9Sstevel@tonic-gate static void rmtgetconn(void); 557c478bd9Sstevel@tonic-gate static int rmtstatus_extended(struct mtget *); 567c478bd9Sstevel@tonic-gate static int rmtioctl_extended(int, long); 577c478bd9Sstevel@tonic-gate static int map_extended_ioctl(int); 587c478bd9Sstevel@tonic-gate static int okname(char *); 597c478bd9Sstevel@tonic-gate static int rmtcall(char *, char *); 607c478bd9Sstevel@tonic-gate static int rmtreply(char *); 617c478bd9Sstevel@tonic-gate static int rmtpush(char *, uint_t); 627c478bd9Sstevel@tonic-gate static void rmtgets(char *, int); 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate static void (*print)(const char *, ...); /* print routine */ 657c478bd9Sstevel@tonic-gate static void (*Exit)(int); /* exit routine */ 667c478bd9Sstevel@tonic-gate #else 677c478bd9Sstevel@tonic-gate static void rmtmsg(); 687c478bd9Sstevel@tonic-gate static void rmtconnaborted(); 697c478bd9Sstevel@tonic-gate static void rmtgetconn(); 707c478bd9Sstevel@tonic-gate static int okname(); 717c478bd9Sstevel@tonic-gate static int rmtstatus_extended(); 727c478bd9Sstevel@tonic-gate static int rmtioctl_extended(); 737c478bd9Sstevel@tonic-gate static int map_extended_ioctl(); 747c478bd9Sstevel@tonic-gate static int rmtcall(); 757c478bd9Sstevel@tonic-gate static int rmtreply(); 767c478bd9Sstevel@tonic-gate static int rmtpush(); 777c478bd9Sstevel@tonic-gate static void rmtgets(); 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate static void (*print)(); 807c478bd9Sstevel@tonic-gate static void (*Exit)(); 817c478bd9Sstevel@tonic-gate #endif 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* 847c478bd9Sstevel@tonic-gate * Get a program-specific print and exit routine into 857c478bd9Sstevel@tonic-gate * the package. This is primarily for dump's benefit. 867c478bd9Sstevel@tonic-gate * This routine is optional -- if not called the two 877c478bd9Sstevel@tonic-gate * default to fprintf(stderr) and exit. 887c478bd9Sstevel@tonic-gate */ 897c478bd9Sstevel@tonic-gate #ifdef __STDC__ 907c478bd9Sstevel@tonic-gate void 917c478bd9Sstevel@tonic-gate rmtinit( 927c478bd9Sstevel@tonic-gate void (*errmsg)(const char *, ...), /* print routine */ 937c478bd9Sstevel@tonic-gate void (*errexit)(int)) /* exit routine */ 947c478bd9Sstevel@tonic-gate #else 957c478bd9Sstevel@tonic-gate void 96*fe0e7ec4Smaheshvs rmtinit(void (*errmsg)(), void (*errexit)()) 977c478bd9Sstevel@tonic-gate #endif 987c478bd9Sstevel@tonic-gate { 997c478bd9Sstevel@tonic-gate print = errmsg; 1007c478bd9Sstevel@tonic-gate Exit = errexit; 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate 103*fe0e7ec4Smaheshvs int 104*fe0e7ec4Smaheshvs rmthost(char *host, uint_t blocksize) 1057c478bd9Sstevel@tonic-gate { 1067c478bd9Sstevel@tonic-gate struct sigvec sv; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate #ifdef __STDC__ 1097c478bd9Sstevel@tonic-gate if (print == (void (*)(const char *, ...))0) 1107c478bd9Sstevel@tonic-gate #else 1117c478bd9Sstevel@tonic-gate if (print == (void (*)())0) 1127c478bd9Sstevel@tonic-gate #endif 1137c478bd9Sstevel@tonic-gate print = rmtmsg; 1147c478bd9Sstevel@tonic-gate #ifdef __STDC__ 1157c478bd9Sstevel@tonic-gate if (Exit == (void (*)(int))0) 1167c478bd9Sstevel@tonic-gate #else 1177c478bd9Sstevel@tonic-gate if (Exit == (void (*)())0) 1187c478bd9Sstevel@tonic-gate #endif 1197c478bd9Sstevel@tonic-gate Exit = exit; 1207c478bd9Sstevel@tonic-gate if (rmtape >= 0 && rmtstate != TS_OPEN) { 1217c478bd9Sstevel@tonic-gate (void) close(rmtape); 1227c478bd9Sstevel@tonic-gate rmtape = -1; 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate if (rmtpeer_malloc) 1257c478bd9Sstevel@tonic-gate (void) free(rmtpeer_malloc); 1267c478bd9Sstevel@tonic-gate rmtpeer = rmtpeer_malloc = strdup(host); 1277c478bd9Sstevel@tonic-gate if (rmtpeer == (char *)0) 1287c478bd9Sstevel@tonic-gate return (0); 1297c478bd9Sstevel@tonic-gate ntrec = blocksize; 1307c478bd9Sstevel@tonic-gate sv.sa_flags = SA_RESTART; 1317c478bd9Sstevel@tonic-gate (void) sigemptyset(&sv.sa_mask); 1327c478bd9Sstevel@tonic-gate sv.sv_handler = rmtconnaborted; 1337c478bd9Sstevel@tonic-gate (void) sigvec(SIGPIPE, &sv, (struct sigvec *)0); 1347c478bd9Sstevel@tonic-gate rmtgetconn(); 1357c478bd9Sstevel@tonic-gate if (rmtape < 0) 1367c478bd9Sstevel@tonic-gate return (0); 1377c478bd9Sstevel@tonic-gate return (1); 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1417c478bd9Sstevel@tonic-gate static void 142*fe0e7ec4Smaheshvs rmtconnaborted(int sig) 1437c478bd9Sstevel@tonic-gate { 1447c478bd9Sstevel@tonic-gate print(dgettext(domainname, "Lost connection to remote host.\n")); 1457c478bd9Sstevel@tonic-gate Exit(1); 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate static void 1497c478bd9Sstevel@tonic-gate #ifdef __STDC__ 1507c478bd9Sstevel@tonic-gate rmtgetconn(void) 1517c478bd9Sstevel@tonic-gate #else 1527c478bd9Sstevel@tonic-gate rmtgetconn() 1537c478bd9Sstevel@tonic-gate #endif 1547c478bd9Sstevel@tonic-gate { 1557c478bd9Sstevel@tonic-gate static struct servent *sp = 0; 1567c478bd9Sstevel@tonic-gate static struct passwd *pwd = 0; 1577c478bd9Sstevel@tonic-gate char *tuser, *host, *device; 1587c478bd9Sstevel@tonic-gate uint_t size; 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate if (sp == 0) { 1617c478bd9Sstevel@tonic-gate sp = getservbyname("shell", "tcp"); 1627c478bd9Sstevel@tonic-gate if (sp == 0) { 1637c478bd9Sstevel@tonic-gate print(dgettext(domainname, 1647c478bd9Sstevel@tonic-gate "shell/tcp: unknown service\n")); 1657c478bd9Sstevel@tonic-gate Exit(1); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate pwd = getpwuid(getuid()); 1687c478bd9Sstevel@tonic-gate if (pwd == 0) { 1697c478bd9Sstevel@tonic-gate print(dgettext(domainname, 1707c478bd9Sstevel@tonic-gate "Cannot find password entry for uid %d\n"), 1717c478bd9Sstevel@tonic-gate getuid()); 1727c478bd9Sstevel@tonic-gate Exit(1); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate } 1757c478bd9Sstevel@tonic-gate /* Was strrchr(), be consistent with dump */ 1767c478bd9Sstevel@tonic-gate host = strchr(rmtpeer, '@'); 1777c478bd9Sstevel@tonic-gate if (host) { 1787c478bd9Sstevel@tonic-gate tuser = rmtpeer; 1797c478bd9Sstevel@tonic-gate *host++ = 0; 1807c478bd9Sstevel@tonic-gate rmtpeer = host; 1817c478bd9Sstevel@tonic-gate if (!okname(tuser)) 1827c478bd9Sstevel@tonic-gate Exit(1); 1837c478bd9Sstevel@tonic-gate } else { 1847c478bd9Sstevel@tonic-gate host = rmtpeer; 1857c478bd9Sstevel@tonic-gate tuser = pwd->pw_name; 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate /* Was strrchr() - be consistent with dump and restore */ 1887c478bd9Sstevel@tonic-gate device = strchr(host, ':'); 1897c478bd9Sstevel@tonic-gate if (device) 1907c478bd9Sstevel@tonic-gate *device = 0; /* throw away device name */ 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * myrcmd() replaces the contents of rmtpeer with a pointer 1937c478bd9Sstevel@tonic-gate * to a static copy of the canonical host name. However, 1947c478bd9Sstevel@tonic-gate * since we never refer to rmtpeer again (other than to 1957c478bd9Sstevel@tonic-gate * overwrite it in the next rmthost() invocation), we don't 1967c478bd9Sstevel@tonic-gate * really care. 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate /* LINTED sp->s_port is an int, even though port numbers are 1..65535 */ 1997c478bd9Sstevel@tonic-gate rmtape = myrcmd(&rmtpeer, (ushort_t)sp->s_port, pwd->pw_name, 2007c478bd9Sstevel@tonic-gate tuser, "/etc/rmt"); 2017c478bd9Sstevel@tonic-gate if (rmtape < 0) { 2027c478bd9Sstevel@tonic-gate if (*myrcmd_stderr) 2037c478bd9Sstevel@tonic-gate print("%s", myrcmd_stderr); 2047c478bd9Sstevel@tonic-gate } else { 2057c478bd9Sstevel@tonic-gate size = ntrec * tp_bsize; 2067c478bd9Sstevel@tonic-gate while (size > tp_bsize && 2077c478bd9Sstevel@tonic-gate setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, (char *)&size, 2087c478bd9Sstevel@tonic-gate sizeof (size)) < 0) 2097c478bd9Sstevel@tonic-gate size -= tp_bsize; 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate static int 214*fe0e7ec4Smaheshvs okname(char *cp0) 2157c478bd9Sstevel@tonic-gate { 2167c478bd9Sstevel@tonic-gate char *cp; 2177c478bd9Sstevel@tonic-gate uchar_t c; 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate for (cp = cp0; *cp; cp++) { 2207c478bd9Sstevel@tonic-gate c = (uchar_t)*cp; 2217c478bd9Sstevel@tonic-gate if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) { 2227c478bd9Sstevel@tonic-gate print(dgettext(domainname, 2237c478bd9Sstevel@tonic-gate "invalid user name %s\n"), cp0); 2247c478bd9Sstevel@tonic-gate return (0); 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate return (1); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 230*fe0e7ec4Smaheshvs int 231*fe0e7ec4Smaheshvs rmtopen(char *tape, int mode) 2327c478bd9Sstevel@tonic-gate { 2337c478bd9Sstevel@tonic-gate struct mtget mt; 2347c478bd9Sstevel@tonic-gate char buf[256]; 2357c478bd9Sstevel@tonic-gate int fd; 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "O%s\n%d\n", tape, mode); 2387c478bd9Sstevel@tonic-gate rmtstate = TS_OPEN; 2397c478bd9Sstevel@tonic-gate fd = rmtcall(tape, buf); 2407c478bd9Sstevel@tonic-gate if (fd != -1) { 2417c478bd9Sstevel@tonic-gate /* see if the rmt server supports the extended protocol */ 2427c478bd9Sstevel@tonic-gate rmtversion = rmtioctl(-1, 0); 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate /* 2457c478bd9Sstevel@tonic-gate * Some rmt daemons apparently close the connection 2467c478bd9Sstevel@tonic-gate * when they get a bogus ioctl. See 1210852 (ignore 2477c478bd9Sstevel@tonic-gate * the evaluation). Make sure we can still talk to 2487c478bd9Sstevel@tonic-gate * the device, re-opening it if necessary. 2497c478bd9Sstevel@tonic-gate */ 2507c478bd9Sstevel@tonic-gate if (rmtversion < 1) { 2517c478bd9Sstevel@tonic-gate if (rmtstatus(&mt) < 0) { 2527c478bd9Sstevel@tonic-gate rmtclose(); 2537c478bd9Sstevel@tonic-gate rmtgetconn(); 2547c478bd9Sstevel@tonic-gate rmtversion = 0; 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate return (fd); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate void 2627c478bd9Sstevel@tonic-gate #ifdef __STDC__ 2637c478bd9Sstevel@tonic-gate rmtclose(void) 2647c478bd9Sstevel@tonic-gate #else 2657c478bd9Sstevel@tonic-gate rmtclose() 2667c478bd9Sstevel@tonic-gate #endif 2677c478bd9Sstevel@tonic-gate { 2687c478bd9Sstevel@tonic-gate if (rmtstate != TS_OPEN) 2697c478bd9Sstevel@tonic-gate return; 2707c478bd9Sstevel@tonic-gate (void) rmtcall("close", "C\n"); 2717c478bd9Sstevel@tonic-gate rmtstate = TS_CLOSED; 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate 274*fe0e7ec4Smaheshvs int 275*fe0e7ec4Smaheshvs rmtstatus(struct mtget *mt) 2767c478bd9Sstevel@tonic-gate { 2777c478bd9Sstevel@tonic-gate char *buf = (char *)mt; 2787c478bd9Sstevel@tonic-gate int n, i, cc; 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate if (rmtversion > 0) 2817c478bd9Sstevel@tonic-gate return (rmtstatus_extended(mt)); 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate n = rmtcall("status", "S"); 2847c478bd9Sstevel@tonic-gate if (n < 0) { 2857c478bd9Sstevel@tonic-gate return (-1); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate if ((unsigned)n > sizeof (*mt)) { 2887c478bd9Sstevel@tonic-gate print(dgettext(domainname, 2897c478bd9Sstevel@tonic-gate "rmtstatus: expected response size %d, got %d\n"), 2907c478bd9Sstevel@tonic-gate sizeof (struct mtget), n); 2917c478bd9Sstevel@tonic-gate print(dgettext(domainname, 2927c478bd9Sstevel@tonic-gate "This means the remote rmt daemon is not compatible.\n")); 2937c478bd9Sstevel@tonic-gate rmtconnaborted(0); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate i = 0; 2967c478bd9Sstevel@tonic-gate while (i < n) { 2977c478bd9Sstevel@tonic-gate cc = read(rmtape, buf+i, n - i); 2987c478bd9Sstevel@tonic-gate if (cc <= 0) 2997c478bd9Sstevel@tonic-gate rmtconnaborted(0); 3007c478bd9Sstevel@tonic-gate i += cc; 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate return (n); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate static int 306*fe0e7ec4Smaheshvs rmtstatus_extended(struct mtget *mt) 3077c478bd9Sstevel@tonic-gate { 3087c478bd9Sstevel@tonic-gate if ((mt->mt_type = rmtcall("status", "sT")) == -1) 3097c478bd9Sstevel@tonic-gate return (-1); 3107c478bd9Sstevel@tonic-gate mt->mt_dsreg = rmtcall("status", "sD"); 3117c478bd9Sstevel@tonic-gate mt->mt_erreg = rmtcall("status", "sE"); 3127c478bd9Sstevel@tonic-gate mt->mt_resid = rmtcall("status", "sR"); 3137c478bd9Sstevel@tonic-gate mt->mt_fileno = rmtcall("status", "sF"); 3147c478bd9Sstevel@tonic-gate mt->mt_blkno = rmtcall("status", "sB"); 3157c478bd9Sstevel@tonic-gate mt->mt_flags = rmtcall("status", "sf"); 3167c478bd9Sstevel@tonic-gate mt->mt_bf = rmtcall("status", "sb"); 3177c478bd9Sstevel@tonic-gate return (0); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 320*fe0e7ec4Smaheshvs int 321*fe0e7ec4Smaheshvs rmtread(char *buf, uint_t count) 3227c478bd9Sstevel@tonic-gate { 3237c478bd9Sstevel@tonic-gate char line[30]; 3247c478bd9Sstevel@tonic-gate int n, i, cc; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate (void) snprintf(line, sizeof (line), "R%d\n", count); 3277c478bd9Sstevel@tonic-gate n = rmtcall("read", line); 3287c478bd9Sstevel@tonic-gate if (n < 0) { 3297c478bd9Sstevel@tonic-gate return (-1); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate if (n > count) { 3327c478bd9Sstevel@tonic-gate print(dgettext(domainname, 3337c478bd9Sstevel@tonic-gate "rmtread: expected response size %d, got %d\n"), 3347c478bd9Sstevel@tonic-gate count, n); 3357c478bd9Sstevel@tonic-gate print(dgettext(domainname, 3367c478bd9Sstevel@tonic-gate "This means the remote rmt daemon is not compatible.\n")); 3377c478bd9Sstevel@tonic-gate rmtconnaborted(0); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate i = 0; 3407c478bd9Sstevel@tonic-gate while (i < n) { 3417c478bd9Sstevel@tonic-gate cc = read(rmtape, buf+i, n - i); 3427c478bd9Sstevel@tonic-gate if (cc <= 0) 3437c478bd9Sstevel@tonic-gate rmtconnaborted(0); 3447c478bd9Sstevel@tonic-gate i += cc; 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate return (n); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate 349*fe0e7ec4Smaheshvs int 350*fe0e7ec4Smaheshvs rmtwrite(char *buf, uint_t count) 3517c478bd9Sstevel@tonic-gate { 3527c478bd9Sstevel@tonic-gate int retval; 3537c478bd9Sstevel@tonic-gate char line[64]; /* numbers can get big */ 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate (void) snprintf(line, sizeof (line), "W%d\n", count); 3567c478bd9Sstevel@tonic-gate retval = rmtpush(line, strlen(line)); 3577c478bd9Sstevel@tonic-gate if (retval <= 0) 3587c478bd9Sstevel@tonic-gate return (-1); 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate retval = rmtpush(buf, count); 3617c478bd9Sstevel@tonic-gate if (retval <= 0) 3627c478bd9Sstevel@tonic-gate return (-1); 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate return (rmtreply("write")); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate int 368*fe0e7ec4Smaheshvs rmtpush(char *buf, uint_t count) 3697c478bd9Sstevel@tonic-gate { 3707c478bd9Sstevel@tonic-gate int retval; 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate do { 3737c478bd9Sstevel@tonic-gate retval = write(rmtape, buf, count); 3747c478bd9Sstevel@tonic-gate buf += retval; 3757c478bd9Sstevel@tonic-gate count -= retval; 3767c478bd9Sstevel@tonic-gate } while (count && retval > 0); 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate return (retval); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate int 382*fe0e7ec4Smaheshvs rmtseek(int offset, int pos) 3837c478bd9Sstevel@tonic-gate { 3847c478bd9Sstevel@tonic-gate char line[80]; 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate (void) snprintf(line, sizeof (line), "L%d\n%d\n", offset, pos); 3877c478bd9Sstevel@tonic-gate return (rmtcall("seek", line)); 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate int 391*fe0e7ec4Smaheshvs rmtioctl(int cmd, long count) 3927c478bd9Sstevel@tonic-gate { 3937c478bd9Sstevel@tonic-gate char buf[256]; 3947c478bd9Sstevel@tonic-gate int xcmd; 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate if (count < 0) 3977c478bd9Sstevel@tonic-gate return (-1); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate if ((xcmd = map_extended_ioctl(cmd)) != -1) 4007c478bd9Sstevel@tonic-gate return (rmtioctl_extended(xcmd, count)); 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "I%d\n%ld\n", cmd, count); 4037c478bd9Sstevel@tonic-gate return (rmtcall("ioctl", buf)); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate /* 4077c478bd9Sstevel@tonic-gate * Map from the standard Sun ioctl commands into the extended version, 4087c478bd9Sstevel@tonic-gate * if possible. 4097c478bd9Sstevel@tonic-gate */ 4107c478bd9Sstevel@tonic-gate static int 411*fe0e7ec4Smaheshvs map_extended_ioctl(int cmd) 4127c478bd9Sstevel@tonic-gate { 4137c478bd9Sstevel@tonic-gate int xcmd; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate if (rmtversion <= 0) 4167c478bd9Sstevel@tonic-gate return (-1); /* extended protocol not supported */ 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate switch (cmd) { 4197c478bd9Sstevel@tonic-gate case MTRETEN: 4207c478bd9Sstevel@tonic-gate xcmd = 2; 4217c478bd9Sstevel@tonic-gate break; 4227c478bd9Sstevel@tonic-gate case MTERASE: 4237c478bd9Sstevel@tonic-gate xcmd = 3; 4247c478bd9Sstevel@tonic-gate break; 4257c478bd9Sstevel@tonic-gate case MTEOM: 4267c478bd9Sstevel@tonic-gate xcmd = 4; 4277c478bd9Sstevel@tonic-gate break; 4287c478bd9Sstevel@tonic-gate case MTNBSF: 4297c478bd9Sstevel@tonic-gate xcmd = 5; 4307c478bd9Sstevel@tonic-gate break; 4317c478bd9Sstevel@tonic-gate default: 4327c478bd9Sstevel@tonic-gate xcmd = -1; /* not supported */ 4337c478bd9Sstevel@tonic-gate break; 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate return (xcmd); 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate static int 439*fe0e7ec4Smaheshvs rmtioctl_extended(int cmd, long count) 4407c478bd9Sstevel@tonic-gate { 4417c478bd9Sstevel@tonic-gate char buf[256]; 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "i%d\n%ld\n", cmd, count); 4447c478bd9Sstevel@tonic-gate return (rmtcall("ioctl", buf)); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate static int 448*fe0e7ec4Smaheshvs rmtcall(char *cmd, char *buf) 4497c478bd9Sstevel@tonic-gate { 4507c478bd9Sstevel@tonic-gate if (rmtpush(buf, strlen(buf)) != strlen(buf)) 4517c478bd9Sstevel@tonic-gate rmtconnaborted(0); 4527c478bd9Sstevel@tonic-gate return (rmtreply(cmd)); 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate static int 456*fe0e7ec4Smaheshvs rmtreply(char *cmd) 4577c478bd9Sstevel@tonic-gate { 4587c478bd9Sstevel@tonic-gate char code[30], emsg[BUFSIZ]; 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate rmtgets(code, sizeof (code)); 4617c478bd9Sstevel@tonic-gate if (*code == 'E' || *code == 'F') { 4627c478bd9Sstevel@tonic-gate rmtgets(emsg, sizeof (emsg)); 4637c478bd9Sstevel@tonic-gate /* 4647c478bd9Sstevel@tonic-gate * don't print error message for ioctl or status; 4657c478bd9Sstevel@tonic-gate * or if we are opening up a full path (i.e. device) 4667c478bd9Sstevel@tonic-gate * and the tape is not loaded (EIO error) 4677c478bd9Sstevel@tonic-gate */ 4687c478bd9Sstevel@tonic-gate if (strcmp(cmd, "ioctl") != 0 && 4697c478bd9Sstevel@tonic-gate strcmp(cmd, "status") != 0 && 4707c478bd9Sstevel@tonic-gate !(cmd[0] == '/' && atoi(code + 1) == EIO)) 4717c478bd9Sstevel@tonic-gate print("%s: %s\n", cmd, emsg); 4727c478bd9Sstevel@tonic-gate errno = atoi(code + 1); 4737c478bd9Sstevel@tonic-gate if (*code == 'F') { 4747c478bd9Sstevel@tonic-gate rmtstate = TS_CLOSED; 4757c478bd9Sstevel@tonic-gate return (-1); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate return (-1); 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate if (*code != 'A') { 4807c478bd9Sstevel@tonic-gate print(dgettext(domainname, 4817c478bd9Sstevel@tonic-gate "Protocol to remote tape server botched (code %s?).\n"), 4827c478bd9Sstevel@tonic-gate code); 4837c478bd9Sstevel@tonic-gate rmtconnaborted(0); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate return (atoi(code + 1)); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate static void 489*fe0e7ec4Smaheshvs rmtgets(char *cp, int len) 4907c478bd9Sstevel@tonic-gate { 4917c478bd9Sstevel@tonic-gate int i, n; 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate n = recv(rmtape, cp, len-1, MSG_PEEK); 4947c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) 4957c478bd9Sstevel@tonic-gate if (cp[i] == '\n') 4967c478bd9Sstevel@tonic-gate break; 4977c478bd9Sstevel@tonic-gate n = i + 1; /* characters to read at once */ 4987c478bd9Sstevel@tonic-gate for (i = 0; i < len; i += n, n = 1) { 4997c478bd9Sstevel@tonic-gate n = read(rmtape, cp, n); 5007c478bd9Sstevel@tonic-gate if (n <= 0) 5017c478bd9Sstevel@tonic-gate rmtconnaborted(0); 5027c478bd9Sstevel@tonic-gate cp += n; 5037c478bd9Sstevel@tonic-gate if (cp[-1] == '\n') { 5047c478bd9Sstevel@tonic-gate cp[-1] = '\0'; 5057c478bd9Sstevel@tonic-gate return; 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate print(dgettext(domainname, 5097c478bd9Sstevel@tonic-gate "Protocol to remote tape server botched (in rmtgets).\n")); 5107c478bd9Sstevel@tonic-gate rmtconnaborted(0); 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate #ifdef __STDC__ 5147c478bd9Sstevel@tonic-gate #include <stdarg.h> 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate /* VARARGS1 */ 5177c478bd9Sstevel@tonic-gate static void 5187c478bd9Sstevel@tonic-gate rmtmsg(const char *fmt, ...) 5197c478bd9Sstevel@tonic-gate { 5207c478bd9Sstevel@tonic-gate va_list args; 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate va_start(args, fmt); 5237c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, args); 5247c478bd9Sstevel@tonic-gate (void) fflush(stderr); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate #else 5277c478bd9Sstevel@tonic-gate #include <varargs.h> 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate /* VARARGS */ 5307c478bd9Sstevel@tonic-gate static void 531*fe0e7ec4Smaheshvs rmtmsg(va_dcl) 5327c478bd9Sstevel@tonic-gate { 5337c478bd9Sstevel@tonic-gate va_list args; 5347c478bd9Sstevel@tonic-gate char *fmt; 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate va_start(args); 5377c478bd9Sstevel@tonic-gate fmt = va_arg(args, char *); 5387c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, args); 5397c478bd9Sstevel@tonic-gate (void) fflush(stderr); 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate #endif 542