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