|
|
1.1 ! root 1: /* ! 2: * domach - install a file on a (single) machine. ! 3: * ! 4: * Output from the installation is appended to the ! 5: * "output" list. The result is a null string on success, ! 6: * non-null on failure. ! 7: */ ! 8: ! 9: #include "decl.h" ! 10: #include <signal.h> ! 11: #include <errno.h> ! 12: #include <ipc.h> ! 13: ! 14: extern int alarm (int); ! 15: ! 16: static const int bufsize = 4096; ! 17: static const int timeout = 60*10; ! 18: ! 19: static void ! 20: alarmcatch() ! 21: { ! 22: signal (SIGALRM, alarmcatch); ! 23: } ! 24: ! 25: static void ! 26: pipecatch() ! 27: { ! 28: signal (SIGPIPE, pipecatch); ! 29: } ! 30: ! 31: static int ! 32: twrite (int fd, char* buf, int n) ! 33: { ! 34: SIG_TYP pipesave = signal (SIGPIPE, (SIG_ARG_TYP) pipecatch); ! 35: alarm (timeout); ! 36: int r = write (fd, buf, n); ! 37: alarm (0); ! 38: signal (SIGPIPE, (SIG_ARG_TYP) pipesave); ! 39: return r; ! 40: } ! 41: ! 42: static int ! 43: tread (int fd, char* buf, int n) ! 44: { ! 45: alarm (timeout); ! 46: int r = read (fd, buf, n); ! 47: alarm (0); ! 48: return r; ! 49: } ! 50: ! 51: String ! 52: domach (String machname, Path file, String_list& output) ! 53: { ! 54: checksum cs; ! 55: signal (SIGALRM, alarmcatch); ! 56: ! 57: /* Open the input file */ ! 58: int infd = open (String(file), 0); ! 59: if (infd < 0) { ! 60: output += "cannot open package"; ! 61: return ""; ! 62: } ! 63: ! 64: /* Establish a connection to the remote machine */ ! 65: errno = 0; ! 66: int remfd = ipcopen(ipcpath(charstr(machname),"dk","asd"), "heavy delim"); ! 67: if (remfd < 0) { ! 68: close (infd); ! 69: ! 70: switch (errno) { ! 71: ! 72: /* permanent errors */ ! 73: case ENOENT: /* illegal destination name */ ! 74: case EACCES: /* permission denied */ ! 75: if (errstr) ! 76: output += errstr; ! 77: return ""; ! 78: ! 79: default: ! 80: if (errstr) ! 81: return errstr; ! 82: return "cannot connect"; ! 83: ! 84: case 0: ! 85: ; ! 86: } ! 87: } ! 88: ! 89: char buf[bufsize]; ! 90: int n, w; ! 91: ! 92: /* verify that we are talking to a dkinstall process */ ! 93: n = tread (remfd, buf, bufsize); ! 94: if (n != 4 || strncmp (buf, "asd\n", 4) != 0) { ! 95: close (infd); ! 96: close (remfd); ! 97: output += "cannot ship to this destination"; ! 98: output += dec(n) + (": " + String(buf,n>0?n-1:0)); ! 99: return ""; ! 100: } ! 101: ! 102: /* copy the file data to the remote system */ ! 103: while ((n = read (infd, buf, bufsize)) > 0) { ! 104: cs.combine (buf, n); ! 105: w = twrite (remfd, buf, n); ! 106: if (w != n) { ! 107: close (infd); ! 108: close (remfd); ! 109: return "error while writing to remote"; ! 110: } ! 111: } ! 112: ! 113: close (infd); ! 114: if (n != 0) { ! 115: close (remfd); ! 116: return "input error"; ! 117: } ! 118: ! 119: /* Indicate end of file */ ! 120: if (twrite (remfd, "", 0) != 0) { ! 121: close (remfd); ! 122: return "cannot write eof"; ! 123: } ! 124: ! 125: /* Send the checksum */ ! 126: SIG_TYP pipesave = signal (SIGPIPE, (SIG_ARG_TYP) pipecatch); ! 127: alarm (timeout); ! 128: n = write (remfd, cs); ! 129: alarm (0); ! 130: signal (SIGPIPE, (SIG_ARG_TYP) pipesave); ! 131: if (n != cksize) { ! 132: close (remfd); ! 133: return "cannot send checksum"; ! 134: } ! 135: ! 136: /* ! 137: * Read the acknowledgment. If the acknowledgment begins ! 138: * with a null record, it indicates success or permanent ! 139: * failure. Otherwise it is a temporary failure. ! 140: */ ! 141: ! 142: if ((n = tread (remfd, buf, bufsize)) != 0) { ! 143: close (remfd); ! 144: if (n < 0) ! 145: return "error reading ack"; ! 146: String msg (buf, n); ! 147: if ((n = msg.strchr('\n')) >= 0) ! 148: msg = msg (0, n); ! 149: return msg; ! 150: } ! 151: ! 152: /* ! 153: * We got here only if we saw a null record from the remote. ! 154: * ! 155: * Read and handle the stuff coming in from the remote. ! 156: * Discard leading null lines, which are probably ! 157: * keep-alive messages but are good to remove even ! 158: * even if they aren't. ! 159: */ ! 160: String remnant; ! 161: int gotdata = 0; ! 162: while ((n = tread (remfd, buf, bufsize)) > 0) { ! 163: register char *p = buf; ! 164: char *lastp = p, *lim = p + n; ! 165: while (p < lim) { ! 166: if (*p == '\n') { ! 167: String line = remnant + ! 168: String (lastp, p - lastp); ! 169: if (gotdata || line.length() != 0) { ! 170: output += line; ! 171: gotdata = 1; ! 172: } ! 173: remnant = ""; ! 174: lastp = p + 1; ! 175: } ! 176: p++; ! 177: } ! 178: remnant += String (lastp, p - lastp); ! 179: } ! 180: ! 181: if (remnant.length() != 0) ! 182: output += remnant; ! 183: ! 184: /* remove trailing normal status message */ ! 185: String s; ! 186: if (output.lastX (s)) { ! 187: if (s == "return code 0") ! 188: output.unput(); ! 189: } ! 190: ! 191: close (remfd); ! 192: ! 193: if (n < 0) ! 194: return "error reading return status"; ! 195: ! 196: return ""; ! 197: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.