|
|
1.1 ! root 1: #include <sys/types.h> ! 2: #include <stdio.h> ! 3: #include <errno.h> ! 4: #include <sys/wait.h> ! 5: #include "dsh.h" ! 6: ! 7: int errno; /* global error location */ ! 8: ! 9: /* options */ ! 10: bool fflg = FALSE; /* if TRUE fanout stdin */ ! 11: bool hflg = FALSE; /* if TRUE use specified host */ ! 12: bool vflg = FALSE; /* tell hosts */ ! 13: bool nflg = FALSE; /* same as for rsh */ ! 14: bool aflg = FALSE; /* true if all nodes to be used */ ! 15: bool sflg = FALSE; /* like -n for make */ ! 16: ! 17: /* files to be rcp'd for input or output */ ! 18: struct rcpfile { ! 19: char *r_name; /* name of the file */ ! 20: struct rcpfile *r_next; ! 21: }; ! 22: struct rcpfile *rcpin = 0; /* list of files to copy to */ ! 23: struct rcpfile *rcpout = 0; /* list of files to copy from */ ! 24: ! 25: char *av[100]; /* the command */ ! 26: union wait pstatus; /* the return status of the job */ ! 27: struct hostdef *thehost; /* the hosts */ ! 28: char *spechost; /* the specified host */ ! 29: ! 30: /* external routines */ ! 31: int error(); ! 32: struct hostdef *highest(); ! 33: int getbids(); ! 34: double atof(); ! 35: bool aresynonyms(); ! 36: ! 37: main(argc, argv) ! 38: int argc; ! 39: char *argv[]; ! 40: { ! 41: int inda, indc, ind; ! 42: struct rcpfile *lin, *lout, *next; ! 43: struct hostdef *hp; ! 44: ! 45: /* now worry about the commands */ ! 46: for (inda = 1; inda < argc; inda++) { ! 47: ! 48: /* process an opton */ ! 49: if (argv[inda][0] == '-') { ! 50: ind = inda; ! 51: for (indc = 1; argv[ind][indc] != NULL; indc++) { ! 52: switch (argv[ind][indc]) { ! 53: ! 54: /* all nodes are specified */ ! 55: case 'a': ! 56: aflg = TRUE; ! 57: break; ! 58: ! 59: case 's': ! 60: sflg = TRUE; ! 61: break; ! 62: ! 63: /* fanout input */ ! 64: case 'f': ! 65: fflg = TRUE; ! 66: break; ! 67: ! 68: /* specify hosts */ ! 69: case 'h': ! 70: inda++; ! 71: if (inda < argc) { ! 72: hflg = TRUE; ! 73: spechost = argv[inda]; ! 74: } else { ! 75: fprintf (stderr, "%s: no host after -h\n", argv[0]); ! 76: exit (-1); ! 77: } ! 78: break; ! 79: ! 80: /* specify input files */ ! 81: case 'i': ! 82: inda++; ! 83: if (inda < argc) { ! 84: next = new (struct rcpfile); ! 85: if (rcpin == 0) { ! 86: rcpin = next; ! 87: } else { ! 88: lin->r_next = next; ! 89: } ! 90: lin = next; ! 91: lin->r_next = 0; ! 92: lin->r_name = argv[inda]; ! 93: } else { ! 94: fprintf (stderr, "%s: no input file after -i\n", argv[0]); ! 95: exit (-1); ! 96: } ! 97: break; ! 98: ! 99: /* specify output files */ ! 100: case 'o': ! 101: inda++; ! 102: if (inda < argc) { ! 103: next = new (struct rcpfile); ! 104: if (rcpout == 0) { ! 105: rcpout = next; ! 106: } else { ! 107: lout->r_next = next; ! 108: } ! 109: lout = next; ! 110: lout->r_next = 0; ! 111: lout->r_name = argv[inda]; ! 112: } else { ! 113: fprintf (stderr, "%s: no output file after -o\n", argv[0]); ! 114: exit (-1); ! 115: } ! 116: break; ! 117: ! 118: /* pipe from /dev/null */ ! 119: case 'n': ! 120: nflg = TRUE; ! 121: break; ! 122: ! 123: /* tell which machine we're using */ ! 124: case 'v': ! 125: vflg = TRUE; ! 126: break; ! 127: ! 128: default: ! 129: fprintf (stderr, "usage: %s [-anv][-io file] <command>\n", argv[0]); ! 130: exit (-1); ! 131: } ! 132: } ! 133: } else { ! 134: break; ! 135: } ! 136: } ! 137: ! 138: /* pick up the command */ ! 139: for (ind = 0; inda < argc; inda++, ind++) { ! 140: av[ind] = argv[inda]; ! 141: } ! 142: av[ind] = 0; ! 143: ! 144: /* process the defaults file */ ! 145: getnodes(); ! 146: ! 147: /* see if anyone wants to bid */ ! 148: getbids(av, thehost); ! 149: ! 150: /* execute the command */ ! 151: hp = highest (); ! 152: if (hp == 0) { ! 153: error ("no machine bid for the command"); ! 154: } ! 155: if (aflg) { ! 156: do { ! 157: rexecute (hp); ! 158: hp = highest (); ! 159: } while (hp != 0); ! 160: } else { ! 161: rexecute (hp); ! 162: } ! 163: ! 164: if (pstatus.w_T.w_Termsig != 0) { ! 165: fprintf (stderr, "(signal %d)", pstatus.w_T.w_Termsig); ! 166: pstatus.w_T.w_Retcode = 0; ! 167: } ! 168: if (pstatus.w_T.w_Coredump == 1) { ! 169: fprintf (stderr, "(core dumped)\n"); ! 170: pstatus.w_T.w_Retcode = 0; ! 171: } ! 172: ! 173: exit (pstatus.w_T.w_Retcode); ! 174: } ! 175: ! 176: /* ! 177: * find out which nodes to use ! 178: */ ! 179: char * ! 180: skipgrey(p) ! 181: char *p; ! 182: { ! 183: while (*p == ' ' || *p == '\t' || *p == ',' || *p == ')' || *p == '*') ! 184: p++; ! 185: return (p); ! 186: } ! 187: ! 188: char * ! 189: token (to, sp) ! 190: char *to; ! 191: char *sp; ! 192: { ! 193: while (*sp != ' ' && *sp != '\t' && *sp != ',' && *sp !=')' && *sp != 0) { ! 194: *to++ = *sp++; ! 195: } ! 196: return (sp); ! 197: } ! 198: ! 199: getnodes() ! 200: { ! 201: char *sp; ! 202: struct hostdef *last, *next; ! 203: bool account; ! 204: double weight; ! 205: char buf[132]; ! 206: int rv; ! 207: ! 208: thehost = 0; ! 209: rv = getstringrc (".dshrc", "hosts", buf); ! 210: if (rv < 0) { ! 211: rv = getstringrc ("/usr/lib/dshrc", "hosts", buf); ! 212: if (rv < 0) { ! 213: error ("dsh: no hosts in rc files"); ! 214: } ! 215: } ! 216: ! 217: /* convert to reasonable format */ ! 218: sp = buf; ! 219: while (*sp != 0) { ! 220: sp = skipgrey (sp); ! 221: ! 222: /* get the multiplier */ ! 223: weight = 1.0; ! 224: if ((*sp >= '0' && *sp <= '9') || *sp == '.') { ! 225: weight = atof (sp); ! 226: for (;*sp != '*' && *sp != 0; sp++); ! 227: sp = skipgrey (sp); ! 228: } ! 229: ! 230: if (*sp != 0) { ! 231: ! 232: /* allocate some space and chain it in */ ! 233: next = new (struct hostdef); ! 234: if (thehost == 0) { ! 235: thehost = next; ! 236: } else { ! 237: last->h_next = next; ! 238: } ! 239: last = next; ! 240: last->h_next = 0; ! 241: last->h_weight = weight; ! 242: ! 243: /* pick up the entry */ ! 244: if (*sp == '(') { ! 245: sp++; ! 246: sp = skipgrey (sp); ! 247: account = TRUE; ! 248: } else { ! 249: account = FALSE; ! 250: } ! 251: sp = token (last->h_name, sp); ! 252: if (account) { ! 253: sp = skipgrey (sp); ! 254: sp = token (last->h_user, sp); ! 255: } else { ! 256: *(last->h_user) = 0; ! 257: } ! 258: } ! 259: } ! 260: } ! 261: ! 262: /* ! 263: * execute a command ! 264: */ ! 265: execute (argv, block, justtell, ignore) ! 266: char *argv[]; /* the command */ ! 267: bool block; /* if true, block till the command is done */ ! 268: bool justtell; /* true if we shouldn't execute when debuging */ ! 269: bool ignore; /* ignore output */ ! 270: { ! 271: int argc; ! 272: int pid, rv; ! 273: int status, fd; ! 274: ! 275: if (sflg) { ! 276: ! 277: /* just say what we'll do */ ! 278: for (argc = 0;argv[argc] != 0; argc++) { ! 279: printf ("%s ", argv[argc]); ! 280: } ! 281: printf ("\n"); ! 282: } ! 283: if (!(justtell && sflg)) { ! 284: ! 285: /* really do it */ ! 286: if (pid = fork()) { ! 287: if (block) { ! 288: do { ! 289: rv = wait (&status); ! 290: } while (rv != -1 && rv != pid); ! 291: } ! 292: } else { ! 293: if (ignore) { ! 294: fd = open ("/dev/null", 2); ! 295: dup2 (fd, 1); ! 296: dup2 (fd, 2); ! 297: } ! 298: execvp (argv[0], argv); ! 299: _exit (0); ! 300: } ! 301: } ! 302: } ! 303: ! 304: /* ! 305: * remotely execute the command ! 306: */ ! 307: rexecute (hp) ! 308: struct hostdef *hp; /* the host to execute on */ ! 309: { ! 310: struct rcpfile *fp; ! 311: int rv; ! 312: int argc, ac; ! 313: char *argv[200]; ! 314: char mydir[PATHSIZE]; ! 315: bool local; ! 316: ! 317: if (vflg || aflg) { ! 318: fprintf (stderr, ">>%s<<\n", hp->h_name); ! 319: } ! 320: argc = 0; ! 321: local = aresynonyms (hp->h_name, myhostname()); ! 322: if (!local) { ! 323: /* get our directory if we're going to copy files */ ! 324: if (rcpin != 0 || rcpout != 0) { ! 325: getwd (mydir); ! 326: } ! 327: ! 328: /* make the directory we're going to use */ ! 329: argv[argc++] = "("; ! 330: argv[argc++] = "mkdir"; ! 331: argv[argc++] = hp->h_dir; ! 332: argv[argc++] = ";"; ! 333: ! 334: /* and hop to it */ ! 335: argv[argc++] = "cd"; ! 336: argv[argc++] = hp->h_dir; ! 337: argv[argc++] = ";"; ! 338: ! 339: /* copy over any files */ ! 340: if (rcpin != 0) { ! 341: argv[argc++] = "rcp"; ! 342: for (fp = rcpin; fp != 0; fp = fp->r_next) { ! 343: argv[argc] = (char *) malloc (HOSTNAMESIZE+2*PATHSIZE); ! 344: if (fp->r_name[0] == '/' || fp->r_name[0] == '~') { ! 345: sprintf (argv[argc++], "%s:%s", myhostname(), fp->r_name); ! 346: } else { ! 347: sprintf (argv[argc++], "%s:%s/%s", myhostname(), ! 348: mydir, fp->r_name); ! 349: } ! 350: } ! 351: argv[argc++] = "."; ! 352: argv[argc++] = ";"; ! 353: } ! 354: } ! 355: ! 356: /* execute the command */ ! 357: for (ac = 0; av[ac] != 0; ac++) { ! 358: argv[argc++] = av[ac]; ! 359: } ! 360: argv[argc++] = ";"; ! 361: ! 362: if (!local) { ! 363: ! 364: /* copy back any files */ ! 365: if (rcpout != 0) { ! 366: argv[argc++] = "rcp"; ! 367: for (fp = rcpout; fp != 0; fp = fp->r_next) { ! 368: argv[argc++] = fp->r_name; ! 369: } ! 370: argv[argc] = (char *) malloc (HOSTNAMESIZE+2*PATHSIZE); ! 371: sprintf (argv[argc++], "%s:%s", myhostname(), mydir); ! 372: argv[argc++] = ";"; ! 373: } ! 374: ! 375: /* clean up the directory */ ! 376: argv[argc++] = "cd"; ! 377: argv[argc++] = ".."; ! 378: argv[argc++] = ";"; ! 379: argv[argc++] = "/bin/rm"; ! 380: argv[argc++] = "-fr"; ! 381: argv[argc++] = hp->h_dir; ! 382: argv[argc++] = ")"; ! 383: } ! 384: argv[argc] = 0; ! 385: ! 386: rshell (hp, argv, TRUE, nflg, TRUE, FALSE); ! 387: } ! 388: ! 389: rshell (hp, av, block, usenflg, justtell, ignore) ! 390: struct hostdef *hp; /* all about the host */ ! 391: char *av[]; /* the command */ ! 392: bool block; /* true if we should block */ ! 393: bool usenflg; /* true if we should use the n flag */ ! 394: bool justtell; /* true if we shouldn't execute when debuging */ ! 395: bool ignore; /* ignore the output from the command */ ! 396: { ! 397: int rv; ! 398: int argc, ac; ! 399: char *argv[100]; ! 400: char command[256]; ! 401: char *p, *p1; ! 402: bool local; ! 403: ! 404: argc = 0; ! 405: local = aresynonyms (hp->h_name, myhostname()); ! 406: if (local) { ! 407: argv[argc++] = "csh"; ! 408: argv[argc++] = "-c"; ! 409: argv[argc++] = command; ! 410: p = command; ! 411: for (ac = 0; av[ac] != 0; ac++) { ! 412: *p++ = ' '; ! 413: for (p1 = av[ac]; *p1 != 0;){ ! 414: *p++ = *p1++; ! 415: } ! 416: } ! 417: *p = 0; ! 418: } else { ! 419: argv[argc++] = "rsh"; ! 420: argv[argc++] = hp->h_name; ! 421: if (usenflg) { ! 422: argv[argc++] = "-n"; ! 423: } ! 424: if (*(hp->h_user) != 0) { ! 425: argv[argc++] = "-l"; ! 426: argv[argc++] = hp->h_user; ! 427: } ! 428: for (ac = 0; av[ac] != 0; ac++) { ! 429: argv[argc++] = av[ac]; ! 430: } ! 431: } ! 432: argv[argc] = 0; ! 433: execute (argv, block, justtell, ignore); ! 434: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.