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: }